ARM: renesas: Drop unused mmc.h
[pandora-u-boot.git] / common / usb_hub.c
index 024dadb..2e054eb 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Most of this source has been derived from the Linux USB
  * project:
@@ -13,8 +14,6 @@
  *
  * Adapted for U-Boot:
  * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /****************************************************************************
 #include <common.h>
 #include <command.h>
 #include <dm.h>
+#include <env.h>
 #include <errno.h>
+#include <log.h>
+#include <malloc.h>
 #include <memalign.h>
 #include <asm/processor.h>
 #include <asm/unaligned.h>
 #include <linux/ctype.h>
+#include <linux/delay.h>
 #include <linux/list.h>
 #include <asm/byteorder.h>
 #ifdef CONFIG_SANDBOX
@@ -37,8 +40,6 @@
 #endif
 #include <asm/unaligned.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 #include <usb.h>
 
 #define USB_BUFSIZ     512
@@ -46,6 +47,8 @@ DECLARE_GLOBAL_DATA_PTR;
 #define HUB_SHORT_RESET_TIME   20
 #define HUB_LONG_RESET_TIME    200
 
+#define HUB_DEBOUNCE_TIMEOUT   CONFIG_USB_HUB_DEBOUNCE_TIMEOUT
+
 #define PORT_OVERCURRENT_MAX_SCAN_COUNT                3
 
 struct usb_device_scan {
@@ -67,7 +70,7 @@ static inline bool usb_hub_is_superspeed(struct usb_device *hdev)
        return hdev->descriptor.bDeviceProtocol == 3;
 }
 
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
 bool usb_hub_is_root_hub(struct udevice *hub)
 {
        if (device_get_uclass_id(hub->parent) != UCLASS_USB_HUB)
@@ -128,7 +131,7 @@ int usb_get_port_status(struct usb_device *dev, int port, void *data)
                        USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
                        data, sizeof(struct usb_port_status), USB_CNTL_TIMEOUT);
 
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
        if (ret < 0)
                return ret;
 
@@ -143,7 +146,8 @@ int usb_get_port_status(struct usb_device *dev, int port, void *data)
 
        if (!usb_hub_is_root_hub(dev->dev) && usb_hub_is_superspeed(dev)) {
                struct usb_port_status *status = (struct usb_port_status *)data;
-               u16 tmp = (status->wPortStatus) & USB_SS_PORT_STAT_MASK;
+               u16 tmp = le16_to_cpu(status->wPortStatus) &
+                       USB_SS_PORT_STAT_MASK;
 
                if (status->wPortStatus & USB_SS_PORT_STAT_POWER)
                        tmp |= USB_PORT_STAT_POWER;
@@ -151,7 +155,7 @@ int usb_get_port_status(struct usb_device *dev, int port, void *data)
                    USB_SS_PORT_STAT_SPEED_5GBPS)
                        tmp |= USB_PORT_STAT_SUPER_SPEED;
 
-               status->wPortStatus = tmp;
+               status->wPortStatus = cpu_to_le16(tmp);
        }
 #endif
 
@@ -164,14 +168,18 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
        int i;
        struct usb_device *dev;
        unsigned pgood_delay = hub->desc.bPwrOn2PwrGood * 2;
-       const char *env;
+       const char __maybe_unused *env;
 
        dev = hub->pusb_dev;
 
        debug("enabling power on all ports\n");
        for (i = 0; i < dev->maxchild; i++) {
+               if (usb_hub_is_superspeed(dev)) {
+                       usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_RESET);
+                       debug("Reset : port %d returns %lX\n", i + 1, dev->status);
+               }
                usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
-               debug("port %d returns %lX\n", i + 1, dev->status);
+               debug("PowerOn : port %d returns %lX\n", i + 1, dev->status);
        }
 
 #ifdef CONFIG_SANDBOX
@@ -189,10 +197,12 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
         * but allow this time to be increased via env variable as some
         * devices break the spec and require longer warm-up times
         */
+#if CONFIG_IS_ENABLED(ENV_SUPPORT)
        env = env_get("usb_pgood_delay");
        if (env)
                pgood_delay = max(pgood_delay,
                                  (unsigned)simple_strtol(env, NULL, 0));
+#endif
        debug("pgood_delay=%dms\n", pgood_delay);
 
        /*
@@ -206,13 +216,13 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
         * will be done based on this value in the USB port loop in
         * usb_hub_configure() later.
         */
-       hub->connect_timeout = hub->query_delay + 1000;
+       hub->connect_timeout = hub->query_delay + HUB_DEBOUNCE_TIMEOUT;
        debug("devnum=%d poweron: query_delay=%d connect_timeout=%d\n",
              dev->devnum, max(100, (int)pgood_delay),
-             max(100, (int)pgood_delay) + 1000);
+             max(100, (int)pgood_delay) + HUB_DEBOUNCE_TIMEOUT);
 }
 
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
 static struct usb_hub_device hub_dev[USB_MAX_HUB];
 static int usb_hub_index;
 
@@ -236,26 +246,18 @@ static struct usb_hub_device *usb_hub_allocate(void)
 
 #define MAX_TRIES 5
 
-static inline char *portspeed(int portstatus)
+static inline const char *portspeed(int portstatus)
 {
-       char *speed_str;
-
        switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
        case USB_PORT_STAT_SUPER_SPEED:
-               speed_str = "5 Gb/s";
-               break;
+               return "5 Gb/s";
        case USB_PORT_STAT_HIGH_SPEED:
-               speed_str = "480 Mb/s";
-               break;
+               return "480 Mb/s";
        case USB_PORT_STAT_LOW_SPEED:
-               speed_str = "1.5 Mb/s";
-               break;
+               return "1.5 Mb/s";
        default:
-               speed_str = "12 Mb/s";
-               break;
+               return "12 Mb/s";
        }
-
-       return speed_str;
 }
 
 /**
@@ -276,7 +278,7 @@ static int usb_hub_port_reset(struct usb_device *dev, int port,
        unsigned short portstatus, portchange;
        int delay = HUB_SHORT_RESET_TIME; /* start with short reset delay */
 
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
        debug("%s: resetting '%s' port %d...\n", __func__, dev->dev->name,
              port + 1);
 #else
@@ -397,7 +399,14 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port)
                break;
        }
 
-#ifdef CONFIG_DM_USB
+       /*
+        * USB 2.0 7.1.7.5: devices must be able to accept a SetAddress()
+        * request (refer to Section 11.24.2 and Section 9.4 respectively)
+        * after the reset recovery time 10 ms
+        */
+       mdelay(10);
+
+#if CONFIG_IS_ENABLED(DM_USB)
        struct udevice *child;
 
        ret = usb_scan_device(dev->dev, port + 1, speed, &child);
@@ -508,11 +517,6 @@ static int usb_scan_port(struct usb_device_scan *usb_scan)
        if (portchange & USB_PORT_STAT_C_ENABLE) {
                debug("port %d enable change, status %x\n", 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
@@ -525,7 +529,6 @@ static int usb_scan_port(struct usb_device_scan *usb_scan)
                              i + 1);
                        usb_hub_port_connect_change(dev, i);
                }
-#endif
        }
 
        if (portstatus & USB_PORT_STAT_SUSPEND) {
@@ -607,7 +610,7 @@ static struct usb_hub_device *usb_get_hub_device(struct usb_device *dev)
 {
        struct usb_hub_device *hub;
 
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
        /* "allocate" Hub device */
        hub = usb_hub_allocate();
 #else
@@ -625,7 +628,7 @@ static int usb_hub_configure(struct usb_device *dev)
        short hubCharacteristics;
        struct usb_hub_descriptor *descriptor;
        struct usb_hub_device *hub;
-       __maybe_unused struct usb_hub_status *hubsts;
+       struct usb_hub_status *hubsts;
        int ret;
 
        hub = usb_get_hub_device(dev);
@@ -779,9 +782,7 @@ static int usb_hub_configure(struct usb_device *dev)
                return ret;
        }
 
-#ifdef DEBUG
        hubsts = (struct usb_hub_status *)buffer;
-#endif
 
        debug("get_hub_status returned status %X, change %X\n",
              le16_to_cpu(hubsts->wHubStatus),
@@ -793,7 +794,7 @@ static int usb_hub_configure(struct usb_device *dev)
              (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \
              "" : "no ");
 
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
        /*
         * Update USB host controller's internal representation of this hub
         * after the hub descriptor is fetched.
@@ -935,7 +936,7 @@ int usb_hub_probe(struct usb_device *dev, int ifnum)
        return ret;
 }
 
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
 int usb_hub_scan(struct udevice *hub)
 {
        struct usb_device *udev = dev_get_parent_priv(hub);
@@ -967,9 +968,9 @@ UCLASS_DRIVER(usb_hub) = {
        .post_bind      = dm_scan_fdt_dev,
        .post_probe     = usb_hub_post_probe,
        .child_pre_probe        = usb_child_pre_probe,
-       .per_child_auto_alloc_size = sizeof(struct usb_device),
-       .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
-       .per_device_auto_alloc_size = sizeof(struct usb_hub_device),
+       .per_child_auto = sizeof(struct usb_device),
+       .per_child_plat_auto    = sizeof(struct usb_dev_plat),
+       .per_device_auto        = sizeof(struct usb_hub_device),
 };
 
 static const struct usb_device_id hub_id_table[] = {