学者之家电子论坛--打造电子工程师共同致富的平台's Archiver

aokikyon 发表于 2009-11-26 21:24

S3C6410的USB-HOST驱动

idea6410开发手册中提到使用usb-host功能必须将无源晶振改为48MHz有源晶振,最近看了一下,使用OHCI兼容的USB-Host功能,可以通过EPLL提供时钟,也就是说外接晶振完全无用。果然,经过一晚的奋斗,USB-HOST功能搞定,记录一下过程。

(1)首先看了S3C6410的数据手册,25章USB-HOST就薄薄两页,和S3C2410基本一样,大意是你去参考OHCI手册吧。
这说明S3C6410的USB基本上是做好的,兼容OHCI,不需要我们做太多修改。

(2)修改内核,添加USB支持,添加OHCI HOST HCD支持,添加U盘等支持。发现以前写的帖子还蛮管用的:
[url]http://hi.baidu.com/aokikyon/blog/item/8545893e3a8a6ffc838b1307.html[/url]

(3)选择完毕,开始编译,发现以下问题:
CC      drivers/usb/host/ohci-hcd.o
drivers/usb/host/ohci-hcd.c:1091:2: error: #error "missing bus glue for ohci-hcd"
make[3]: *** [drivers/usb/host/ohci-hcd.o] 错误 1
make[2]: *** [drivers/usb/host] 错误 2
make[1]: *** [drivers/usb] 错误 2
make: *** [drivers] 错误 2

看了一下OHCI文件,发现要想三星芯片使用,需要包含ohci-s3c2410.c文件,如果没哟包含这个文件,就会提示找不到hcd的以上错误。
这段代码在ohci-hcd.c中是这样定义的
#ifdef CONFIG_ARCH_S3C2410
#include "ohci-s3c2410.c"
#define PLATFORM_DRIVER   ohci_hcd_s3c2410_driver
#endif

由于我们使用的是S3C6410,并没有CONFIG_ARCH_S3C2410,手动修改一下好了:
#ifdef CONFIG_ARCH_S3C64XX
#include "ohci-s3c2410.c"
#define PLATFORM_DRIVER   ohci_hcd_s3c2410_driver
#endif

(4)编译完毕后完全没有反应,参考2.6.24代码,发现需要添加platform-device注册信息:
/plat-s3c64xx/devs.c
/* USB Host Controller */
static struct resource s3c_usb_resource[] = {
[0] = {
   .start = S3C24XX_PA_USBHOST,
   .end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
   .flags = IORESOURCE_MEM,
},
#if !defined(CONFIG_CPU_S3C6400) && !defined(CONFIG_CPU_S3C6410)
[1] = {
   .start = IRQ_USBH,
   .end   = IRQ_USBH,
   .flags = IORESOURCE_IRQ,
}
#else
[1] = {
   .start = IRQ_UHOST,
   .end   = IRQ_UHOST,
   .flags = IORESOURCE_IRQ,
}
#endif
};

static u64 s3c_device_usb_dmamask = 0xffffffffUL;

struct platform_device s3c_device_usb = {
.name    = "s3c2410-ohci",
.id    = -1,
.num_resources   = ARRAY_SIZE(s3c_usb_resource),
.resource   = s3c_usb_resource,
.dev              = {
   .dma_mask = &s3c_device_usb_dmamask,
   .coherent_dma_mask = 0xffffffffUL
}
};
EXPORT_SYMBOL(s3c_device_usb);

编译后还是发现错误,S3C24XX_PA_USBHOST、S3C24XX_PA_USBHOST、IRQ_USBH都没有定义。
查找半天后发现HOST的物理地址0x74300000没有定义,手动填入这个地址好了。
SIZE大概写一个尺寸,比如1K就可以(实际上用到很少)。
至于中断号,开始我填了中断控制器中的位置47,可惜不对,后来发现头文件中有定义,填IRQ_USBH.
一下是修改后代码:
/* USB Host Controller add by rockie */

static struct resource s3c_usb_resource[] = {
[0] = {
   .start = 0x74300000,//S3C24XX_PA_USBHOST,
   .end   = 0x74301000,//S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
   .flags = IORESOURCE_MEM,
},
[1] = {
   .start = IRQ_USBH,//IRQ_UHOST,
   .end   = IRQ_USBH,//IRQ_UHOST,
   .flags = IORESOURCE_IRQ,
}
};

static u64 s3c_device_usb_dmamask = 0xffffffffUL;

struct platform_device s3c_device_usb = {
.name    = "s3c2410-ohci",
.id    = -1,
.num_resources   = ARRAY_SIZE(s3c_usb_resource),
.resource   = s3c_usb_resource,
.dev              = {
   .dma_mask = &s3c_device_usb_dmamask,
   .coherent_dma_mask = 0xffffffffUL
}
};

EXPORT_SYMBOL(s3c_device_usb);

还需要注册进平台设备:
/mach-smdk6410/mach-s3c6410.c添加

static struct platform_device *smdk6410_devices[] __initdata = {
...
&s3c_device_usb, //<——添加这句即可
...
}


(5)编译完毕,初始化怎么还是错误?
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 79, io mem 0x74300000
s3c2410-ohci s3c2410-ohci: init err (00000000 0000)
ohci_hcd: can't start s3c24xx
s3c2410-ohci s3c2410-ohci: startup error -75
s3c2410-ohci s3c2410-ohci: USB bus 1 deregistered
s3c2410-ohci: probe of s3c2410-ohci failed with error -75
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.

原来还要完成初始化时钟的函数:
/mach-smdk6410/mach-s3c6410.c

#if defined(CONFIG_USB_GADGET_S3C_OTGD) || defined(CONFIG_USB_OHCI_HCD)
#include <plat/regs-otg.h>

#include <linux/usb/ch9.h>
#endif

/*************************************************************************************
* USB HOST
**************************************************************************************/
#ifdef CONFIG_USB_OHCI_HCD
void usb_host_clk_en(int usb_host_clksrc)
{
printk("Usb Host CLK enable! 2009 by Rockie \n");

switch (usb_host_clksrc)
{
case 0: // epll clk
   writel((readl(S3C_CLK_SRC)& ~S3C_CLKSRC_UHOST_MASK) | S3C_CLKSRC_EPLL_CLKSEL | S3C_CLKSRC_UHOST_EPLL, S3C_CLK_SRC);

   // USB host colock divider ratio is 2 /
   //writel((readl(S3C_CLK_DIV1)& ~S3C_CLKDIVN_UHOST_MASK) | S3C_CLKDIV1_USBDIV2, S3C_CLK_DIV1);
   *(volatile unsigned long*) S3C_CLK_DIV1 |= (0<<20);
   break;
case 1: // oscillator 48M clk /
   writel(readl(S3C_CLK_SRC)& ~S3C_CLKSRC_UHOST_MASK, S3C_CLK_SRC);
   //otg_phy_init(otg_phy_clk);

   // USB host colock divider ratio is 1 /
   //writel(readl(S3C_CLK_DIV1)& ~S3C_CLKDIVN_UHOST_MASK, S3C_CLK_DIV1);
   *(volatile unsigned long*) S3C_CLK_DIV1 |= (0<<20);
   break;
default:
   printk(KERN_INFO "Unknown USB Host Clock Source\n");
   BUG();
   break;

}

writel(readl(S3C_HCLK_GATE)|S3C_CLKCON_HCLK_UHOST|S3C_CLKCON_HCLK_SECUR, S3C_HCLK_GATE);
writel(readl(S3C_SCLK_GATE)|S3C_CLKCON_SCLK_UHOST, S3C_SCLK_GATE);

}
EXPORT_SYMBOL(usb_host_clk_en);
#endif

最后别忘了初始化时调用这个函数:
usb_host_clk_en(0);

页: [1]

Powered by Discuz! Archiver 7.1  © 2001-2009 Comsenz Inc.

302 Found

302 Found


nginx/1.8.0