etup-usb-s5p.c文件中的内容替换成下面的代码:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- ints5p_usb_phy_init(structplatform_device*pdev,inttype)
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- ints5p_usb_phy_init(structplatform_device*pdev,inttype)
- {
- interr;
- structclk*otg_clk;
- if(type!=S5P_USB_PHY_HOST)
- return-EINVAL;
- otg_clk=clk_get(&pdev->dev,"otg");
- if(IS_ERR(otg_clk)){
- dev_err(&pdev->dev,"Failedtogetotgclock");
- returnPTR_ERR(otg_clk);
- }
- err=clk_enable(otg_clk);
- if(err){
- clk_put(otg_clk);
- returnerr;
- }
- if(readl(S5PV210_USB_PHY_CON)&(0x1<1)){
- clk_disable(otg_clk);
- clk_put(otg_clk);
- return0;
- }
- __raw_writel(__raw_readl(S5PV210_USB_PHY_CON)|(0x1<1),
- S5PV210_USB_PHY_CON);
- __raw_writel((__raw_readl(S3C_PHYPWR)
- &~(0x1<7)&~(0x1<6))|(0x1<8)|(0x1<5)|(0x1<4),
- S3C_PHYPWR);
- __raw_writel((__raw_readl(S3C_PHYCLK)&~(0x1<7))|(0x3<0),
- S3C_PHYCLK);
- __raw_writel((__raw_readl(S3C_RSTCON))|(0x1<4)|(0x1<3),
- S3C_RSTCON);
- __raw_writel(__raw_readl(S3C_RSTCON)&~(0x1<4)&~(0x1<3),
- S3C_RSTCON);
- /*"atleast10uS"forPHYresetelsewhere,20notenoughhere...*/
- udelay(50);
- clk_disable(otg_clk);
- clk_put(otg_clk);
- return0;
- }
- ints5p_usb_phy_exit(structplatform_device*pdev,inttype)
- {
- if(type!=S5P_USB_PHY_HOST)
- return-EINVAL;
- __raw_writel(__raw_readl(S3C_PHYPWR)|(0x1<7)|(0x1<6),
- S3C_PHYPWR);
- __raw_writel(__raw_readl(S5PV210_USB_PHY_CON)&~(1<1),
- S5PV210_USB_PHY_CON);
- return0;
- }
六 内核配置项修改
这时,执行make menuconfig配置,在Device Drivers --->USB support 下看不到OHCI HCD support,只能看到EHCI HCD support,这是因为内核配置存在关联关系,现在解决这个问题。
(1)切换到目录drivers/usb/,打开Kconfig,在USB_ARCH_HAS_OHCI模块下添加如下内容
- defaultyifPLAT_S5P
(2)切换到目录drivers/usb/host下,打开Kconfig,在USB_EHCI_S5P模块下添加如下内容:
- selectS5P_DEV_USB_EHCI
然后再USB_OHCI_S5P模块下添加如下内容:
- selectS5P_DEV_USB_OHCI
到这里,执行make menuconfig,到USB相关部分开始OHCI和EHCI中S5P相关,然后编译内核即可正式支持S5PV210内核了。
七 EHCI模块内核bug修改
到这里虽然已经编译 通过了,下载到开发板也可以看到OHCI和EHCI模块都被驱动起来了,插入U盘时也可以正常访问U盘里的数据了,但是,你会发现,如果你对内核U盘中的内容稍作修改然后卸载U盘的话就会发生错误,而且U盘中也没有存入任何数据,这说明,上面的配置仅支持了U盘的读取,还无法支持写操作。
由于芯片手册上对USB HOST部分,我对各寄存器的功能也不是很了解,另外,想了解各部分的功能还需要阅读USB1.0、USB1.1和USB2.0协议,如果想支持USB3.0,还需要阅读相关协议,我暂时还没有时间和精力来阅读这些资料,于是,我去三星的邮件列表中查找,找到了相关问题的解决方法。
打开ehci-s5p.c,然后找到注释
- /*DMAburstEnable*/
一共有两处,分别将其下的一行代码:
- writel(EHCI_INSNREG00_ENABLE_DMA_BURST,EHCI_INSNREG00(hcd->regs));
改为:
- writel(0x000E0000,hcd->regs+0x90);
- writel(0x00400040,hcd->regs+0x94);
这样,就解决了U盘卸载时出错的问题。
八 小结
经过上面一番大战,Linux-3.8.3或者Linux-3.8.6就可以正常驱动S5PV210的USB HOST模块了。
最后,发表一下个人意见,学习嵌入式这些东西,还是需要自己亲自动手做一下,拿官方的核去做一些简单的应用跟在PC上开发东西没什么两样,你是不会看到底层那些美妙的风景的,如果想踏踏实实的做好嵌入式,底层还是不能忽略的,最好从裸机开始。