diff mbox series

[U-Boot,03/14] usb: xhci: Don't assume LS/FS devices are always behind a HS hub

Message ID 1505742050-5697-4-git-send-email-bmeng.cn@gmail.com
State Accepted
Commit 8a0e6d83070a977442aaba2c5a74cbe34e157012
Delegated to: Marek Vasut
Headers show
Series usb: xhci: Add interrupt transfer support and full speed device support | expand

Commit Message

Bin Meng Sept. 18, 2017, 1:40 p.m. UTC
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>
---

 drivers/usb/host/xhci-mem.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

Comments

Stefan Roese Sept. 22, 2017, 4:58 a.m. UTC | #1
On 18.09.2017 15:40, Bin Meng wrote:
> 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>
> ---
> 
>   drivers/usb/host/xhci-mem.c | 18 ++++++++++++++----
>   1 file 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));
>   		}
>   	}
> 

Reviewed-by: Stefan Roese <sr@denx.de>
Tested-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan
diff mbox series

Patch

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));
 		}
 	}