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]