查看文章
 
linux-2.6.28系统移植s3c6410开发板USB不能识别的处理
2010-05-14 10:09

初始化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的不能识别的错误就解决了


类别:默认分类||添加到搜藏 |分享到i贴吧|浏览(2046)|评论 (0)
 
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu