]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/usb_hub.c
Merge branch 'master' of git://git.denx.de/u-boot-i2c
[karo-tx-uboot.git] / common / usb_hub.c
index 1e225e6b3722986e11fe42891eb583480d4d9f63..754d436ad4ec69380033dde2725c9ba5032e3595 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *
  * Most of this source has been derived from the Linux USB
  * project:
  * (C) Copyright Linus Torvalds 1999
  * Adapted for U-Boot:
  * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /****************************************************************************
 #include <asm/4xx_pci.h>
 #endif
 
+#ifndef CONFIG_USB_HUB_MIN_POWER_ON_DELAY
+#define CONFIG_USB_HUB_MIN_POWER_ON_DELAY      100
+#endif
+
 #define USB_BUFSIZ     512
 
 static struct usb_hub_device hub_dev[USB_MAX_HUB];
@@ -105,19 +91,22 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
        int ret;
 
        dev = hub->pusb_dev;
-       /* Enable power to the ports */
+
+       /*
+        * Enable power to the ports:
+        * Here we Power-cycle the ports: aka,
+        * turning them off and turning on again.
+        */
        debug("enabling power on all ports\n");
        for (i = 0; i < dev->maxchild; i++) {
-               /*
-                * Power-cycle the ports here: aka,
-                * turning them off and turning on again.
-                */
                usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
                debug("port %d returns %lX\n", i + 1, dev->status);
+       }
 
-               /* Wait at least 2*bPwrOn2PwrGood for PP to change */
-               mdelay(pgood_delay);
+       /* Wait at least 2*bPwrOn2PwrGood for PP to change */
+       mdelay(pgood_delay);
 
+       for (i = 0; i < dev->maxchild; i++) {
                ret = usb_get_port_status(dev, i + 1, portsts);
                if (ret < 0) {
                        debug("port %d: get_port_status failed\n", i + 1);
@@ -138,13 +127,15 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
                        debug("port %d: Port power change failed\n", i + 1);
                        return;
                }
+       }
 
+       for (i = 0; i < dev->maxchild; i++) {
                usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
                debug("port %d returns %lX\n", i + 1, dev->status);
        }
 
-       /* Wait at least 100 msec for power to become stable */
-       mdelay(max(pgood_delay, (unsigned)100));
+       /* Wait for power to become stable */
+       mdelay(max(pgood_delay, CONFIG_USB_HUB_MIN_POWER_ON_DELAY));
 }
 
 void usb_hub_reset(void)
@@ -165,14 +156,24 @@ static struct usb_hub_device *usb_hub_allocate(void)
 
 static inline char *portspeed(int portstatus)
 {
-       if (portstatus & (1 << USB_PORT_FEAT_SUPERSPEED))
-               return "5 Gb/s";
-       else if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
-               return "480 Mb/s";
-       else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
-               return "1.5 Mb/s";
-       else
-               return "12 Mb/s";
+       char *speed_str;
+
+       switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
+       case USB_PORT_STAT_SUPER_SPEED:
+               speed_str = "5 Gb/s";
+               break;
+       case USB_PORT_STAT_HIGH_SPEED:
+               speed_str = "480 Mb/s";
+               break;
+       case USB_PORT_STAT_LOW_SPEED:
+               speed_str = "1.5 Mb/s";
+               break;
+       default:
+               speed_str = "12 Mb/s";
+               break;
+       }
+
+       return speed_str;
 }
 
 int hub_port_reset(struct usb_device *dev, int port,
@@ -270,14 +271,20 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
        /* Allocate a new device struct for it */
        usb = usb_alloc_new_device(dev->controller);
 
-       if (portstatus & USB_PORT_STAT_SUPER_SPEED)
+       switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
+       case USB_PORT_STAT_SUPER_SPEED:
                usb->speed = USB_SPEED_SUPER;
-       else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+               break;
+       case USB_PORT_STAT_HIGH_SPEED:
                usb->speed = USB_SPEED_HIGH;
-       else if (portstatus & USB_PORT_STAT_LOW_SPEED)
+               break;
+       case USB_PORT_STAT_LOW_SPEED:
                usb->speed = USB_SPEED_LOW;
-       else
+               break;
+       default:
                usb->speed = USB_SPEED_FULL;
+               break;
+       }
 
        dev->children[port] = usb;
        usb->parent = dev;
@@ -464,7 +471,11 @@ static int usb_hub_configure(struct usb_device *dev)
                              i + 1, portstatus);
                        usb_clear_port_feature(dev, i + 1,
                                                USB_PORT_FEAT_C_ENABLE);
-
+                       /*
+                        * The following hack causes a ghost device problem
+                        * to Faraday EHCI
+                        */
+#ifndef CONFIG_USB_EHCI_FARADAY
                        /* EM interference sometimes causes bad shielded USB
                         * devices to be shutdown by the hub, this hack enables
                         * them again. Works at least with mouse driver */
@@ -476,6 +487,7 @@ static int usb_hub_configure(struct usb_device *dev)
                                      "re-enabling...\n", i + 1);
                                      usb_hub_port_connect_change(dev, i);
                        }
+#endif
                }
                if (portstatus & USB_PORT_STAT_SUSPEND) {
                        debug("port %d suspend change\n", i + 1);