之前的开发,要在2440上使用两个usb host口,一个接摄像头,一个接无线网卡。但友善之臂mini2440板子只有一个usb host口,曾想通过外接一个usb hub来解决,无线网卡接hub没有问题,但是摄像头插到hub上总是有错误:
usb 1-1: reset full speed USB device using s3c2410-ohci and address 3 本来想试着修改内核中关于hub.c和ohci-s3c2410中的代码,看看能不能好使,但后来在PC机上的hub下使用摄像头也不好使,看来是我使用的zc301摄像头对hub不支持吧。(估计一般的摄像头都对hub不支持,我又试了另一款也是这样的)。 所以放弃了在usb hub上使用摄像头的想法。记得以前看过关于s3c2410的手册,它应该是支持2个usb host通道的啊,2440应该也是如此。所以仔细看了下s3c2440的手册,发现第二个usb hos通道的管脚和usb device的管脚是复用的。所以感觉将usb device改成host应该是可行的,深入研究研究。(好像一些板子已经设计出来可以跳线选择,友善之臂的没这么设计) 要将usb device改成host,不只是硬件上需要改动,软件驱动上肯定也需要改动,所以分为硬件和软件两个部分。 硬件上:仔细看了mini2440的手册中的关于usb电路图,其实硬件电路上host和device没什么本质区别,一些外拉电阻不一样,VBUS的提供者不一样。将device改成host感觉外拉电阻不一样应该也不会影响使用,所以就没有改变,避免在板子上做手脚。其它的就是要给VBUS一个5v的电源,而不是像device一样电脑供电了。其它的就没什么改动了。自己动手做了一个usb host口。 软件上:本质就是对寄存器MISCCR的设置改变一下,为了以后改动方便,我参考了网上的一些《关于阳初2440 超值版只能使用一个 USB Host 问题的解决》的方法。以下主要参照了一些关于这个方法的帖子博客之类的。(转载一些) 第一篇: 修改linux-2.6.20.3/drivers/usb/host/Kconfig,添加: config MAX_ROOT_PORTS int "Maximum port(s) of RootHub" depends on USB_OHCI_HCD && ARCH_S3C2410 default 1 ---help--- pls select usb host number,default one host and one device.so We select one normally 修改/linux-2.6.20.3/drivers/usb/host/ohci-s3c2410.c static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, struct platform_device *dev) { struct usb_hcd *hcd = NULL; int retval; //add by hiboy unsigned long tmp; #if CONFIG_MAX_ROOT_PORTS < 2 /* 1 host port, 1 slave port*/ tmp = __raw_readl(S3C2410_MISCCR); tmp &= ~S3C2410_MISCCR_USBHOST; __raw_writel(tmp, S3C2410_MISCCR); s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); #else /* 2 host port */ tmp = __raw_readl(S3C2410_MISCCR); tmp |= S3C2410_MISCCR_USBHOST; __raw_writel(tmp, S3C2410_MISCCR); s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); s3c2410_usb_set_power(dev->dev.platform_data, 2, 1); #endif //s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); //s3c2410_usb_set_power(dev->dev.platform_data, 2, 1); ...... 修改/linux-2.6.20.3/drivers/usb/core/hub.c static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { struct usb_device *hdev = hub->hdev; struct device *hub_dev = hub->intfdev; u16 hubstatus, hubchange; u16 wHubCharacteristics; unsigned int pipe; int maxp, ret; char *message; hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL, &hub->buffer_dma); if (!hub->buffer) { message = "can't allocate hub irq buffer"; ret = -ENOMEM; goto fail; } hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL); if (!hub->status) { message = "can't kmalloc hub status buffer"; ret = -ENOMEM; goto fail; } mutex_init(&hub->status_mutex); hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { message = "can't kmalloc hub descriptor"; ret = -ENOMEM; goto fail; } /* Request the entire hub descriptor. * hub->descriptor can handle USB_MAXCHILDREN ports, * but the hub can/will return fewer bytes here. */ ret = get_hub_descriptor(hdev, hub->descriptor, sizeof(*hub->descriptor)); if (ret < 0) { message = "can't read hub descriptor"; goto fail; } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { message = "hub has too many ports!"; ret = -ENODEV; goto fail; } /********************************************/ /*add by hiboy */ #ifdef CONFIG_ARCH_S3C2410 if ((hdev->devnum == 1) // Root Hub && hub->descriptor->bNbrPorts > CONFIG_MAX_ROOT_PORTS) { int j; for (j=hub->descriptor->bNbrPorts-1; j>=0; j--) { printk("port #%d ", j); if (j > CONFIG_MAX_ROOT_PORTS-1) { printk("suspened!\n"); } else { printk("alived!\n"); } } hub->descriptor->bNbrPorts = CONFIG_MAX_ROOT_PORTS; } #endif /*********************************************/ 第二篇: 是由于MISCCR寄存器没有正确设置的缘故,我在mach-2410.c中增加了设置MISCCR寄存器的内容,HOST0就可以正常使用了 /*add by seigpao*/ int usb_seigpao_init(void) { unsigned long upllvalue; unsigned long misccr; //设置UPLLCON upllvalue = (0x78<<12)|(0x02<<4)|(0x03); __raw_writel(upllvalue,S3C2410_UPLLCON); //设置MISCCR misccr = __raw_readl(S3C2410_MISCCR); misccr |= S3C2410_MISCCR_USBHOST; misccr &= ~(S3C2410_MISCCR_USBSUSPND0 | S3C2410_MISCCR_USBSUSPND1); __raw_writel(misccr,S3C2410_MISCCR); return 1; } /* end by seigpao */ static void __init smdk2410_map_io(void) { s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); s3c24xx_init_clocks(0); s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); s3c24xx_set_board(&smdk2410_board); /*add by seigpao*/ //设置2410触摸屏 set_s3c2410ts_info(&sbc2410_ts_cfg); //设置USB相关寄存器 usb_seigpao_init(); /* end by seigpao */ } 不知道为什么会有第二篇,感觉不适合,所以又重网上找了另一篇文章。 修改ohci-s3c2440.c文件(含头文件):
/*add here*/
#include <asm/arch/regs-gpio.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
} misccr = __raw_readl(S3C2410_MISCCR); //MISCCR
dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
if (info != NULL) {
if (info->enable_oc != NULL) {
}
使用了这篇文章的改动。头文件位置可能根据内核不同做相应改动。我的2.6.29内核中的regs-clock.h和regs-gpio.h是在arch\arm\mach-s3c2410\include\mach中。我拷贝两个头文件到本地drivers/usb/host/,include 变成""。 然后make zImage,之后Kconfig会重新选择, USB support (USB_SUPPORT) [Y/n/?] y Support for Host-side USB (USB) [Y/n/m/?] y USB verbose debug messages (USB_DEBUG) [N/y/?] n USB announce new devices (USB_ANNOUNCE_NEW_DEVICES) [Y/n/?] y * * Miscellaneous USB options * USB device filesystem (USB_DEVICEFS) [Y/n/?] y USB device class-devices (DEPRECATED) (USB_DEVICE_CLASS) [N/y/?] n Dynamic USB minor allocation (USB_DYNAMIC_MINORS) [N/y/?] n USB Monitor (USB_MON) [N/m/y/?] n Enable Wireless USB extensions (EXPERIMENTAL) (USB_WUSB) [N/m/y/?] n Support WUSB Cable Based Association (CBA) (USB_WUSB_CBAF) [N/m/y/?] n * * USB Host Controller Drivers * Cypress C67x00 HCD support (USB_C67X00_HCD) [N/m/y/?] n OXU210HP HCD support (USB_OXU210HP_HCD) [N/m/y/?] n ISP116X HCD support (USB_ISP116X_HCD) [N/m/y/?] n OHCI HCD support (USB_OHCI_HCD) [Y/n/m/?] y SL811HS HCD support (USB_SL811_HCD) [N/m/y/?] n R8A66597 HCD support (USB_R8A66597_HCD) [N/m/y/?] n Host Wire Adapter (HWA) driver (EXPERIMENTAL) (USB_HWA_HCD) [N/m/y/?] n Maximum port(s) of RootHub (MAX_ROOT_PORTS) [2] (NEW) 最后一项选的时候选成2就行了,因为config MAX_ROOT_PORTS为2代表使用两个host。 烧写生成的内核,结果大失所望,启动后在自己焊出的usb host口上插上设备没反应。不过郁闷重启之时,发现先在这之上插上设备启动时,设备就能识别出来了。而且插入无线网卡可以配置使用。不过使用摄像头确出现错误: gspca: ISOC data error: [1] len=318, status=-84 gspca: ISOC data error: [4] len=274, status=-84 gspca: ISOC data error: [25] len=144, status=-84 gspca: ISOC data error: [1] len=240, status=-84 等等。这是又回到对内核的改动上,当改动内核时就感觉帖子文章中第二篇没什么用,跟第一篇有些重复之嫌,后来替代的在static void s3c2410_start_hc中的改动也是,感觉有些重复static int usb_hcd_s3c2410_probe中的内容,所以重新编译内核,将对static void s3c2410_start_hc的改动去掉,即不改s3c2410_start_hc,重新编译内核烧写,结果使用摄像头正常。 也就是说,usb device已经改成了usb host,可以当成usb host使用了,只不过,必需先插入设备再启动板子,分析这种情况的原因可能是因为bootloader中肯定有对usb部分的设置驱动之类的,(Nor Flash的时候可以使用usb device进行下载传输,说明肯定已经驱上了usb device),vivi的设置跟重新编译的内核对usb设置不一样,可能就导致了这种情况,我也不确定是不是这个原因。不插设备的时候启动信息改的usb 1-2提示: usb 1-2: new full speed USB device using s3c2410-ohci and address 3 usb 1-2: device descriptor read/64, error -62 usb 1-2: device descriptor read/64, error -62 usb 1-2: new full speed USB device using s3c2410-ohci and address 4 usb 1-2: device descriptor read/64, error -62 usb 1-2: device descriptor read/64, error -62 usb 1-2: new full speed US. device using s3c2410-ohci and address 5 usb 1-2: device not accepting addre髎 5, error -62 usb 1-2: new full speed USB device using s3c2410-ohci and address 6 usb 1-2: device not accepting address 6, error -62 hub 1-0:1.0: unable to enumerate USB device on port 2 但是,插上设备比如无线网卡,就能找到设备,提示: usb 1-2: new full speed USB device using s3c2410-o鑓i and address 3 usb 1-2: New USB device found, idVen鋙r=0ace, idProduct=1215 usb 1-2: New USB device strings: Mfr=16, Product=32, SerialNumber=0 usb 1-2: Product: USB2.0 WLAN usb 1-2: Manufacturer: ZyDAS usb 1-2: configuration #1 chosen from 1 choice usb 1-2: reset full speed USB device using s3c2410-ohci and address 3 wmaster0 (zd1211rw): not using net_device_ops yet wlan0 (zd1211rw): not using net_device_ops yet zd1211rw 1-2:1.0: phy0 对于这种情况,上网搜了一下,好像修改vivi中的upll设置,在main中添加了ChangeUPllValue(56,2,2)一句后,问题可以解决。具体没有再试,先如此的用着吧。 转载自 http://hi.baidu.com/weili8607/blog/item/301f2550eed26110367abebe.html |