X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fusb.c;h=32e15cd8ddb93320c5758635268daac68e7196f7;hb=51f4999bc5ad5f8430da0297d12c1abef9c05568;hp=c97f522beddd1745056c6f97fe3bdf01ed8fea94;hpb=e62d5fb0da76ef168e90cae9bbbda80349aaf137;p=u-boot diff --git a/common/usb.c b/common/usb.c index c97f522bed..32e15cd8dd 100644 --- a/common/usb.c +++ b/common/usb.c @@ -33,7 +33,7 @@ #include #include #include - +#include #include #ifdef CONFIG_4xx #include @@ -59,6 +59,8 @@ int usb_init(void) void *ctrl; struct usb_device *dev; int i, start_index = 0; + int controllers_initialized = 0; + int ret; dev_index = 0; asynch_allowed = 1; @@ -74,7 +76,14 @@ int usb_init(void) for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) { /* init low_level USB */ printf("USB%d: ", i); - if (usb_lowlevel_init(i, &ctrl)) { + ret = usb_lowlevel_init(i, USB_INIT_HOST, &ctrl); + if (ret == -ENODEV) { /* No such device. */ + puts("Port not available.\n"); + controllers_initialized++; + continue; + } + + if (ret) { /* Other error. */ puts("lowlevel init failed\n"); continue; } @@ -82,6 +91,7 @@ int usb_init(void) * lowlevel init is OK, now scan the bus for devices * i.e. search HUBs and configure them */ + controllers_initialized++; start_index = dev_index; printf("scanning bus %d for devices... ", i); dev = usb_alloc_new_device(ctrl); @@ -103,12 +113,10 @@ int usb_init(void) debug("scan end\n"); /* if we were not able to find at least one working bus, bail out */ - if (!usb_started) { + if (controllers_initialized == 0) puts("USB error: all controllers failed lowlevel init\n"); - return -1; - } - return 0; + return usb_started ? 0 : -1; } /****************************************************************************** @@ -854,6 +862,16 @@ void usb_free_device(void) usb_dev[dev_index].devnum = -1; } +/* + * XHCI issues Enable Slot command and thereafter + * allocates device contexts. Provide a weak alias + * function for the purpose, so that XHCI overrides it + * and EHCI/OHCI just work out of the box. + */ +__weak int usb_alloc_device(struct usb_device *udev) +{ + return 0; +} /* * By the time we get here, the device has gotten a new device ID * and is in the default state. We need to identify the thing and @@ -867,6 +885,17 @@ int usb_new_device(struct usb_device *dev) int tmp; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + /* + * Allocate usb 3.0 device context. + * USB 3.0 (xHCI) protocol tries to allocate device slot + * and related data structures first. This call does that. + * Refer to sec 4.3.2 in xHCI spec rev1.0 + */ + if (usb_alloc_device(dev)) { + printf("Cannot allocate device context to get SLOT_ID\n"); + return -1; + } + /* We still haven't set the Address yet */ addr = dev->devnum; dev->devnum = 0; @@ -897,8 +926,7 @@ int usb_new_device(struct usb_device *dev) * http://sourceforge.net/mailarchive/forum.php? * thread_id=5729457&forum_id=5398 */ - struct usb_device_descriptor *desc; - int port = -1; + __maybe_unused struct usb_device_descriptor *desc; struct usb_device *parent = dev->parent; unsigned short portstatus; @@ -914,6 +942,13 @@ int usb_new_device(struct usb_device *dev) dev->epmaxpacketin[0] = 64; dev->epmaxpacketout[0] = 64; + /* + * XHCI needs to issue a Address device command to setup + * proper device context structures, before it can interact + * with the device. So a get_descriptor will fail before any + * of that is done for XHCI unlike EHCI. + */ +#ifndef CONFIG_USB_XHCI err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); if (err < 0) { debug("usb_new_device: usb_get_descriptor() failed\n"); @@ -926,28 +961,17 @@ int usb_new_device(struct usb_device *dev) * to differentiate between HUB and DEVICE. */ dev->descriptor.bDeviceClass = desc->bDeviceClass; +#endif - /* find the port number we're at */ if (parent) { - int j; - - for (j = 0; j < parent->maxchild; j++) { - if (parent->children[j] == dev) { - port = j; - break; - } - } - if (port < 0) { - printf("usb_new_device:cannot locate device's port.\n"); - return 1; - } - /* reset the port for the second time */ - err = hub_port_reset(dev->parent, port, &portstatus); + err = hub_port_reset(dev->parent, dev->portnr - 1, &portstatus); if (err < 0) { - printf("\n Couldn't reset port %i\n", port); + printf("\n Couldn't reset port %i\n", dev->portnr); return 1; } + } else { + usb_reset_root_port(); } #endif @@ -1037,4 +1061,9 @@ int usb_new_device(struct usb_device *dev) return 0; } +__weak +int board_usb_init(int index, enum usb_init_type init) +{ + return 0; +} /* EOF */