summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2017-07-19 13:51:12 (GMT)
committerMarek Vasut <marex@denx.de>2017-07-28 21:34:31 (GMT)
commit74ffc7cbb1d2d1f218b1bd67d1bd3cc1cba8aa79 (patch)
tree31be16dbd8ebb77b4197dcff6c55e7bb76798302 /common
parent46c1d49330fe21b3f9d2f7577ee4268248e7b666 (diff)
downloadu-boot-fsl-qoriq-74ffc7cbb1d2d1f218b1bd67d1bd3cc1cba8aa79.tar.xz
usb: hub: Translate USB 3.0 hub port status into old version
USB 3.0 hub port status field has different bit positions from 2.0 hubs. Since U-Boot only understands the old version, translate the new one into the old one. Since we are going to add USB 3.0 hub support, this feature is only available with driver model USB. Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common')
-rw-r--r--common/usb_hub.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/common/usb_hub.c b/common/usb_hub.c
index a8c2f56..b0ff159 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -112,9 +112,40 @@ static int usb_get_hub_status(struct usb_device *dev, void *data)
int usb_get_port_status(struct usb_device *dev, int port, void *data)
{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ int ret;
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
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 (ret < 0)
+ return ret;
+
+ /*
+ * Translate the USB 3.0 hub port status field into the old version
+ * that U-Boot understands. Do this only when the hub is not root hub.
+ * For root hub, the port status field has already been translated
+ * in the host controller driver (see xhci_submit_root() in xhci.c).
+ *
+ * Note: this only supports driver model.
+ */
+
+ 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;
+
+ if (status->wPortStatus & USB_SS_PORT_STAT_POWER)
+ tmp |= USB_PORT_STAT_POWER;
+ if ((status->wPortStatus & USB_SS_PORT_STAT_SPEED) ==
+ USB_SS_PORT_STAT_SPEED_5GBPS)
+ tmp |= USB_PORT_STAT_SUPER_SPEED;
+
+ status->wPortStatus = tmp;
+ }
+#endif
+
+ return ret;
}