]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - common/usb.c
dm: usb: Drop the legacy USB init sequence
[people/ms/u-boot.git] / common / usb.c
index 1288ca059260475cf2b34762fde01da3f14e6d25..df4e172ff806779a9c071199e6e016a51df9562d 100644 (file)
@@ -94,19 +94,25 @@ int usb_init(void)
                controllers_initialized++;
                start_index = dev_index;
                printf("scanning bus %d for devices... ", i);
-               dev = usb_alloc_new_device(ctrl);
+               ret = usb_alloc_new_device(ctrl, &dev);
+               if (ret)
+                       break;
+
                /*
                 * device 0 is always present
                 * (root hub, so let it analyze)
                 */
-               if (dev)
-                       usb_new_device(dev);
+               ret = usb_new_device(dev);
+               if (ret)
+                       usb_free_device(dev->controller);
 
-               if (start_index == dev_index)
+               if (start_index == dev_index) {
                        puts("No USB Device found\n");
-               else
+                       continue;
+               } else {
                        printf("%d USB Device(s) found\n",
                                dev_index - start_index);
+               }
 
                usb_started = 1;
        }
@@ -827,16 +833,13 @@ struct usb_device *usb_get_dev_index(int index)
                return &usb_dev[index];
 }
 
-/* returns a pointer of a new device structure or NULL, if
- * no device struct is available
- */
-struct usb_device *usb_alloc_new_device(void *controller)
+int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp)
 {
        int i;
        debug("New Device %d\n", dev_index);
        if (dev_index == USB_MAX_DEVICE) {
                printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
-               return NULL;
+               return -ENOSPC;
        }
        /* default Address is 0, real addresses start with 1 */
        usb_dev[dev_index].devnum = dev_index + 1;
@@ -846,7 +849,9 @@ struct usb_device *usb_alloc_new_device(void *controller)
        usb_dev[dev_index].parent = NULL;
        usb_dev[dev_index].controller = controller;
        dev_index++;
-       return &usb_dev[dev_index - 1];
+       *devp = &usb_dev[dev_index - 1];
+
+       return 0;
 }
 
 /*
@@ -854,7 +859,7 @@ struct usb_device *usb_alloc_new_device(void *controller)
  * Called in error cases where configuring a newly attached
  * device fails for some reason.
  */
-void usb_free_device(void)
+void usb_free_device(struct udevice *controller)
 {
        dev_index--;
        debug("Freeing device node: %d\n", dev_index);
@@ -900,26 +905,8 @@ int usb_new_device(struct usb_device *dev)
        addr = dev->devnum;
        dev->devnum = 0;
 
-#ifdef CONFIG_LEGACY_USB_INIT_SEQ
-       /* this is the old and known way of initializing devices, it is
-        * different than what Windows and Linux are doing. Windows and Linux
-        * both retrieve 64 bytes while reading the device descriptor
-        * Several USB stick devices report ERR: CTL_TIMEOUT, caused by an
-        * invalid header while reading 8 bytes as device descriptor. */
-       dev->descriptor.bMaxPacketSize0 = 8;        /* Start off at 8 bytes  */
-       dev->maxpacketsize = PACKET_SIZE_8;
-       dev->epmaxpacketin[0] = 8;
-       dev->epmaxpacketout[0] = 8;
-
-       err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, tmpbuf, 8);
-       if (err < 8) {
-               printf("\n      USB device not responding, " \
-                      "giving up (status=%lX)\n", dev->status);
-               return -EIO;
-       }
-       memcpy(&dev->descriptor, tmpbuf, 8);
-#else
-       /* This is a Windows scheme of initialization sequence, with double
+       /*
+        * This is a Windows scheme of initialization sequence, with double
         * reset of the device (Linux uses the same sequence)
         * Some equipment is said to work only with such init sequence; this
         * patch is based on the work by Alan Stern:
@@ -930,7 +917,8 @@ int usb_new_device(struct usb_device *dev)
        struct usb_device *parent = dev->parent;
        unsigned short portstatus;
 
-       /* send 64-byte GET-DEVICE-DESCRIPTOR request.  Since the descriptor is
+       /*
+        * send 64-byte GET-DEVICE-DESCRIPTOR request.  Since the descriptor is
         * only 18 bytes long, this will terminate with a short packet.  But if
         * the maxpacket size is 8 or 16 the device may be waiting to transmit
         * some more, or keeps on retransmitting the 8 byte header. */
@@ -950,7 +938,22 @@ int usb_new_device(struct usb_device *dev)
         */
 #ifndef CONFIG_USB_XHCI
        err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64);
-       if (err < 0) {
+       /*
+        * Validate we've received only at least 8 bytes, not that we've
+        * received the entire descriptor. The reasoning is:
+        * - The code only uses fields in the first 8 bytes, so that's all we
+        *   need to have fetched at this stage.
+        * - The smallest maxpacket size is 8 bytes. Before we know the actual
+        *   maxpacket the device uses, the USB controller may only accept a
+        *   single packet. Consequently we are only guaranteed to receive 1
+        *   packet (at least 8 bytes) even in a non-error case.
+        *
+        * At least the DWC2 controller needs to be programmed with the number
+        * of packets in addition to the number of bytes. A request for 64
+        * bytes of data with the maxpacket guessed as 64 (above) yields a
+        * request for 1 packet.
+        */
+       if (err < 8) {
                debug("usb_new_device: usb_get_descriptor() failed\n");
                return -EIO;
        }
@@ -973,7 +976,6 @@ int usb_new_device(struct usb_device *dev)
        } else {
                usb_reset_root_port();
        }
-#endif
 
        dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
        dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
@@ -990,6 +992,9 @@ int usb_new_device(struct usb_device *dev)
        case 64:
                dev->maxpacketsize = PACKET_SIZE_64;
                break;
+       default:
+               printf("usb_new_device: invalid max packet size\n");
+               return -EIO;
        }
        dev->devnum = addr;
 
@@ -1066,4 +1071,10 @@ int board_usb_init(int index, enum usb_init_type init)
 {
        return 0;
 }
+
+__weak
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+       return 0;
+}
 /* EOF */