]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - common/usb_hub.c
usb: legacy_hub_port_reset(): Speedup hub reset handling
[people/ms/u-boot.git] / common / usb_hub.c
index f621ddb9ab5debe7c6b65514f2b04ee408167bfc..2089e20fd5032152eef6672e016f1dba4211cc5d 100644 (file)
 #include <command.h>
 #include <dm.h>
 #include <errno.h>
+#include <memalign.h>
 #include <asm/processor.h>
 #include <asm/unaligned.h>
 #include <linux/ctype.h>
 #include <asm/byteorder.h>
+#ifdef CONFIG_SANDBOX
+#include <asm/state.h>
+#endif
 #include <asm/unaligned.h>
 #include <dm/root.h>
 
@@ -42,6 +46,9 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define USB_BUFSIZ     512
 
+#define HUB_SHORT_RESET_TIME   20
+#define HUB_LONG_RESET_TIME    200
+
 /* TODO(sjg@chromium.org): Remove this when CONFIG_DM_USB is defined */
 static struct usb_hub_device hub_dev[USB_MAX_HUB];
 static int usb_hub_index;
@@ -160,6 +167,7 @@ int legacy_hub_port_reset(struct usb_device *dev, int port,
        int err, tries;
        ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
        unsigned short portstatus, portchange;
+       int delay = HUB_SHORT_RESET_TIME; /* start with short reset delay */
 
 #ifdef CONFIG_DM_USB
        debug("%s: resetting '%s' port %d...\n", __func__, dev->dev->name,
@@ -172,7 +180,7 @@ int legacy_hub_port_reset(struct usb_device *dev, int port,
                if (err < 0)
                        return err;
 
-               mdelay(200);
+               mdelay(delay);
 
                if (usb_get_port_status(dev, port + 1, portsts) < 0) {
                        debug("get_port_status failed status %lX\n",
@@ -211,7 +219,8 @@ int legacy_hub_port_reset(struct usb_device *dev, int port,
                if (portstatus & USB_PORT_STAT_ENABLE)
                        break;
 
-               mdelay(200);
+               /* Switch to long reset delay for the next round */
+               delay = HUB_LONG_RESET_TIME;
        }
 
        if (tries == MAX_TRIES) {
@@ -229,7 +238,7 @@ int legacy_hub_port_reset(struct usb_device *dev, int port,
 #ifdef CONFIG_DM_USB
 int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat)
 {
-       struct usb_device *udev = dev_get_parentdata(dev);
+       struct usb_device *udev = dev_get_parent_priv(dev);
 
        return legacy_hub_port_reset(udev, port, portstat);
 }
@@ -465,7 +474,12 @@ static int usb_hub_configure(struct usb_device *dev)
                unsigned short portstatus, portchange;
                int ret;
                ulong start = get_timer(0);
+               uint delay = CONFIG_SYS_HZ;
 
+#ifdef CONFIG_SANDBOX
+               if (state_get_skip_delays())
+                       delay = 0;
+#endif
 #ifdef CONFIG_DM_USB
                debug("\n\nScanning '%s' port %d\n", dev->dev->name, i + 1);
 #else
@@ -489,11 +503,15 @@ static int usb_hub_configure(struct usb_device *dev)
                        portstatus = le16_to_cpu(portsts->wPortStatus);
                        portchange = le16_to_cpu(portsts->wPortChange);
 
-                       if ((portchange & USB_PORT_STAT_C_CONNECTION) ==
-                               (portstatus & USB_PORT_STAT_CONNECTION))
+                       /* No connection change happened, wait a bit more. */
+                       if (!(portchange & USB_PORT_STAT_C_CONNECTION))
+                               continue;
+
+                       /* Test if the connection came up, and if so, exit. */
+                       if (portstatus & USB_PORT_STAT_CONNECTION)
                                break;
 
-               } while (get_timer(start) < CONFIG_SYS_HZ * 10);
+               } while (get_timer(start) < delay);
 
                if (ret < 0)
                        continue;
@@ -605,7 +623,7 @@ int usb_hub_probe(struct usb_device *dev, int ifnum)
 #ifdef CONFIG_DM_USB
 int usb_hub_scan(struct udevice *hub)
 {
-       struct usb_device *udev = dev_get_parentdata(hub);
+       struct usb_device *udev = dev_get_parent_priv(hub);
 
        return usb_hub_configure(udev);
 }