Chinaunix首页 | 论坛 | 博客
  • 博客访问: 160522
  • 博文数量: 70
  • 博客积分: 2050
  • 博客等级: 大尉
  • 技术积分: 690
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-22 22:04
文章分类

全部博文(70)

文章存档

2014年(1)

2013年(1)

2012年(3)

2011年(48)

2010年(17)

我的朋友

分类: 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 分别归为hostgadgetstorage等。基本确定问题就在ohci-s3c2410.c中。


原来是USB Host的48MHz时钟没有起来。

s3c6410支持三个PLL分别是APLLMPLLEPLLAPLLARM提供时钟,产生ARMCLKMPLL为所有和AXI/AHB/APB相连的模块提供时钟,产生HCLKPCLKEPLL为特殊的外设提供时钟,产生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);


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