Chinaunix首页 | 论坛 | 博客
  • 博客访问: 569257
  • 博文数量: 169
  • 博客积分: 2656
  • 博客等级: 少校
  • 技术积分: 1685
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 13:03
文章分类

全部博文(169)

文章存档

2011年(1)

2010年(135)

2009年(33)

我的朋友

分类: 嵌入式

2010-05-16 21:02:18

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盘等支持。发现以前写的帖子还蛮管用的:
http://hi.baidu.com/aokikyon/blog/item/8545893e3a8a6ffc838b1307.html

还得修改/drivers/usb/kconfig

添加config USB_ARCH_HAS_OHCI对S3C64XX的支持

default y if ARCH_S3C64XX

(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

#include  
#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);

最好用宏圈住

#ifdef CONFIG_USB_OHCI_HCD
usb_host_clk_en(0);
#endif

(6)初始化通过
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
usb usb1: New USB device found, idVendor=1d6b, idProduct=0001
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: S3C24XX OHCI
usb usb1: Manufacturer: Linux 2.6.29 ohci_hcd
usb usb1: SerialNumber: s3c24xx
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.

但是插上U盘提示错误:
/ # usb 1-1: new full speed USB device using s3c2410-ohci and address 2
usb 1-1: device descriptor read/64, error -62
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 3
usb 1-1: device descriptor read/64, error -62
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 4
usb 1-1: device not accepting address 4, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 5
usb 1-1: device not accepting address 5, error -62
hub 1-0:1.0: unable to enumerate USB device on port 1

怎么回事呢?原来EPLL初始化时只有24MHz,怎么分频也到不了 48MHz啊!
S3C24XX Clocks, (c) 2004 Simtec Electronics
S3C64XX: PLL settings, A=666000000, M=532000000, E=24000000
S3C64XX: HCLK2=266000000, HCLK=133000000, PCLK=66500000
mout_apll: source is fout_apll (1), rate is 666000000
mout_epll: source is fout_epll (1), rate is 24000000
mout_mpll: source is mpll (1), rate is 532000000
mmc_bus: source is mout_epll (0), rate is 24000000
mmc_bus: source is mout_epll (0), rate is 24000000
mmc_bus: source is mout_epll (0), rate is 24000000
usb-bus-host: source is clk_48m (0), rate is 48000000
uclk1: source is dout_mpll (1), rate is 66500000
spi-bus: source is mout_epll (0), rate is 24000000
spi-bus: source is mout_epll (0), rate is 24000000
audio-bus: source is mout_epll (0), rate is 24000000
audio-bus: source is mout_epll (0), rate is 24000000
irda-bus: source is mout_epll (0), rate is 24000000

在Linux内核里尝试修改EPLL_CON0,M=0x20 P=1 S=3,计算出32*12MHz/(2^3)=48MHz
可是Linux中总是写这个寄存器不成功,最后怒了,直接修改U-boot,从汇编了改了回来。
在board/samsung/smdk6410/lowlevel_init.S中有用到
ldr r1, =APLL_VAL
str r1, [r0, #APLL_CON_OFFSET] //这里写APLL_CON寄存器
ldr r1, =MPLL_VAL
str r1, [r0, #MPLL_CON_OFFSET] //这里写MPLL_CON寄存器

ldr r1, =0x80200203    /* FOUT of EPLL is 96MHz */
str r1, [r0, #EPLL_CON0_OFFSET]
ldr r1, =0x0
str r1, [r0, #EPLL_CON1_OFFSET]

ldr r1, [r0, #CLK_SRC_OFFSET] /* APLL, MPLL, EPLL select to Fout */

看这段,注释EPLL是96MHz,实际这样配置只有24MHz。
ldr r1, =0x80200203    /* FOUT of EPLL is 24MHz */
修改为
ldr r1, =0x80200103    /* FOUT of EPLL is 48MHz */

(7)编译,通过。
S3C24XX Clocks, (c) 2004 Simtec Electronics
S3C64XX: PLL settings, A=666000000, M=532000000, E=48000000
S3C64XX: HCLK2=266000000, HCLK=133000000, PCLK=66500000
mout_apll: source is fout_apll (1), rate is 666000000
mout_epll: source is fout_epll (1), rate is 48000000
mout_mpll: source is mpll (1), rate is 532000000
mmc_bus: source is mout_epll (0), rate is 48000000
mmc_bus: source is mout_epll (0), rate is 48000000
mmc_bus: source is mout_epll (0), rate is 48000000
usb-bus-host: source is clk_48m (0), rate is 48000000
uclk1: source is dout_mpll (1), rate is 66500000
spi-bus: source is mout_epll (0), rate is 48000000
spi-bus: source is mout_epll (0), rate is 48000000
audio-bus: source is mout_epll (0), rate is 48000000
audio-bus: source is mout_epll (0), rate is 48000000
irda-bus: source is mout_epll (0), rate is 48000000

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
usb usb1: New USB device found, idVendor=1d6b, idProduct=0001
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: S3C24XX OHCI
usb usb1: Manufacturer: Linux 2.6.29 ohci_hcd
usb usb1: SerialNumber: s3c24xx
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
Initializing USB Mass Storage driver...


至此USB-HOST功能可以正常使用:
/ # usb 1-1: new full speed USB device using s3c2410-ohci and address 2
usb 1-1: New USB device found, idVendor=1976, idProduct=1307
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: USB Reader
usb 1-1: Manufacturer: ChipsBnk
usb 1-1: SerialNumber: 110074973765
usb 1-1: configuration #1 chosen from 1 choice
uba: unknown partition table

/ # mount -t vfat /dev/uba1 /mnt
/ # cd mnt
/mnt # ls
4020 NorFlash_bootloader
??
?????
??????
??ACM????200?
?tcp ip?????? ????????????(???????).pdf
ARMKiller???????????.doc
Jlink Driver
TCPIP list
elf
elf2
elf3
elf5
elf6
elf7
ieka
linux-2.6.28.tar.bz2
modsile
reserve_mmu
test_sdram.elf
xme30.zip
/mnt # cd .. 
/ # umount /mnt
/ # usb 1-1: USB disconnect, address 2

阿虚(Rockie Cheng

本文为原创,转载请注明出处

如有错误,欢迎指正!

阅读(2133) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~