分类: LINUX
2011-11-14 19:00:05
http://hi.baidu.com/musi11630019/blog/item/9091a795676ec912d31b700c.html
初始化OK,一插上usb就报如下错误:
/ # 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
解决方法:
根据终端打印的错误
cd include/asm-generic/errno.h
u-boot/include/asm-arm/errno.H
找到:
#define ETIME 62 /*timer expired*/
再由:
error-codes.txt 去找usb error code
http://ftp.gnu.org/tmp/linux-libre-fsf2_2.6.28/linux-2.6.28/Documentation/usb/error-codes.txt
-ETIME (**) No response packet received within the prescribed
bus turn-around time. This error may instead be
reported as -EPROTO or -EILSEQ.
由此可以判断,这个错误与USB设备超时有关。报告这个错误的地方在drivers/usb/core/hub.c中的hub_port_init部分,由于usb_get_device_descriptor获取usb设备资讯的时候产生了超时,这样基本可以确定三种情况,1.USB设备及介面有问题,2、usbcore有问题3、usb driver有问题。
我们可以很容易的派出1.2的可能性,问题应该在usb driverimplement部分造成。2.6的内核usb driver把usb规范中对usb的操作集中到了core里面,针对不同设备的implement 分别归为host、gadget、storage等。基本确定问题就在ohci-s3c2410.c中。
s3c6410支持三个PLL分别是APLL,MPLL和EPLL。APLL为ARM提供时钟,产生ARMCLK,MPLL为所有和AXI/AHB/APB相连的模块提供时钟,产生HCLK和PCLK,EPLL为特殊的外设提供时钟,产生SCLK。
如图所示为EPLL_CON的 M、 P 和 S的取值。
根据s3c6410的数据手册:
如图所示,描述的是用于IrDA和USB host 的时钟发生器,通常USB借口需要48M的操作时钟。
从图中可也以说明,HCLK_GATE,PCLK_GATE和SCL_GATE控制时钟操作。如果一个位设置,则通过每个时钟分频器相应的时钟将会被提供,否则,将被屏蔽。
HCLK_GATE控制HCLK,用于每个Ips。每个IP的AHB接口逻辑被独立地屏蔽,以减少动态电力消耗。PCLK_GATE控制PCLK。通过SCLK_GATE时钟被控制。
根据上图EPLL通道写出一下程序。
58 #define EPLL_CON01 0
359
360 #define UPLL_SRC_MASK ((1<<2)|(3<<5))
361 #define UPLL_SRC ((1<<2)|(1<<5))
362 #define UPLL_DIV1_MASK (0xf<<20)
363 #define UPLL_DIV1 (0<<20)
364 #define UPLL_GATE_MASK (1<<30)
365 #define UPLL_GATE (1<<30)
void set_upll(void)
368 {
369 unsigned int tmp;
370
371 while(__raw_readl(S3C_EPLL_CON0)!=EPLL_CON00)
372 __raw_writel(EPLL_CON00,S3C_EPLL_CON0);
373
374 while(__raw_readl(S3C_EPLL_CON1)!=EPLL_CON01)
375 __raw_writel(EPLL_CON01,S3C_EPLL_CON1);
376
377 while(((tmp= __raw_readl(S3C_CLK_SRC))&UPLL_SRC_MASK)!=UPLL_SRC)
378 __raw_writel((tmp&UPLL_SRC_MASK)|UPLL_SRC,S3C_CLK_SRC);
379 while(((tmp=__raw_readl(S3C_CLK_DIV1))&UPLL_DIV1_MASK)!=UPLL_DIV1)
380 __raw_writel((tmp&UPLL_DIV1_MASK)|UPLL_DIV1,S3C_CLK_DIV1);
381 while(((tmp=__raw_readl(S3C_SCLK_GATE))&UPLL_GATE_MASK)!=UPLL_GATE)
382 __raw_writel((tmp&UPLL_GATE_MASK)|UPLL_GATE,S3C_SCLK_GATE);
383 }
在probe中加入上面的函数修改USB host的时钟:
386 static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
387 struct platform_device *dev)
388 {
389 struct usb_hcd *hcd = NULL;
390 int retval;
391
392 #if !defined(CONFIG_ARCH_2410)
393 usb_host_clk_en();
394 #endif
395
396 set_upll();
然后编译内核。
USB的不能识别的错误就解决了
http://blog.csdn.net/ll_0520/article/details/6125882
在网上查了下说是UPLLCON赋值的问题。
试了些办法,最终延长了MPLLCON寄存器赋值和UPLLCON寄存器赋值之间延迟后解决了错误。
具体修改了以下代码:
vi uboot1.1.4/board/fl2440/fl2440.c
修改board_init函数以下语句:
clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
/* some delay between MPLL and UPLL */
delay (4000);
/* configure UPLL */
clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
将其改为:
clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
/* some delay between MPLL and UPLL */
delay (4000);
delay (4000);
/* configure UPLL */
clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
也就是多加一个delay (4000);