diff options
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index d5eab3a615..0582a9be40 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)); } } @@ -840,6 +850,12 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); + /* + * xHCI spec 6.2.3: + * software shall set 'Average TRB Length' to 8 for control endpoints. + */ + ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(8)); + /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ xhci_flush_cache((uintptr_t)ep0_ctx, sizeof(struct xhci_ep_ctx)); |