summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBin Meng <bmeng.cn@gmail.com>2017-09-18 13:40:39 (GMT)
committerMarek Vasut <marex@denx.de>2017-10-01 14:32:52 (GMT)
commit8a0e6d83070a977442aaba2c5a74cbe34e157012 (patch)
treebb0d2d593d27022758b387515b893bae6fe8854d /drivers
parentf4d4f7d41cec8c8bfe0fc60d13da059839a56671 (diff)
downloadu-boot-8a0e6d83070a977442aaba2c5a74cbe34e157012.tar.xz
usb: xhci: Don't assume LS/FS devices are always behind a HS hub
At present xHCI driver assumes LS/FS devices are attached directly to a HS hub. If they are connected to a LS/FS hub, the driver will fail to perform the USB enumeration process on such devices. This is fixed by looking from the device itself all the way up to the HS hub where the TT that serves the device is located. Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-mem.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d5eab3a..84982a9 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -786,12 +786,22 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
#ifdef CONFIG_DM_USB
/* Set up TT fields to support FS/LS devices */
if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) {
- dev = dev_get_parent_priv(udev->dev);
- if (dev->speed == USB_SPEED_HIGH) {
- hub = dev_get_uclass_priv(udev->dev);
+ struct udevice *parent = udev->dev;
+
+ dev = udev;
+ do {
+ port_num = dev->portnr;
+ dev = dev_get_parent_priv(parent);
+ if (usb_hub_is_root_hub(dev->dev))
+ break;
+ parent = dev->dev->parent;
+ } while (dev->speed != USB_SPEED_HIGH);
+
+ if (!usb_hub_is_root_hub(dev->dev)) {
+ hub = dev_get_uclass_priv(dev->dev);
if (hub->tt.multi)
slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
- slot_ctx->tt_info |= cpu_to_le32(TT_PORT(udev->portnr));
+ slot_ctx->tt_info |= cpu_to_le32(TT_PORT(port_num));
slot_ctx->tt_info |= cpu_to_le32(TT_SLOT(dev->slot_id));
}
}