[U-Boot] [PATCH 3/6] usb: dwc2: determine TT hub address and port for split transactions

Stefan Brüns
2015-12-13T04:17:55Z

Start split and complete split tokens need the hub address and the
downstream port of the first HS hub (device view).
Code copied from host/ehci_hcd.c

Signed-off-by: Stefan Br?ns <stefan.bruens@rwth-aachen.de>
---
drivers/usb/host/dwc2.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)

diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index db3acd4..2d97546 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -404,6 +404,66 @@ static void dwc_otg_core_init(struct dwc2_core_regs *regs)
}

/*
+ * Searches for the first HS hub above the given device. If a
+ * HS hub is found, the hub address and the port the device is
+ * connected to is return, as required for SPLIT transactions
+ *
+ * @param: udev full speed or low speed device
+ */
+#ifdef CONFIG_DM_USB
+static void dwc_find_hub_address_port(struct usb_device *udev,
+ uint8_t *hub_address, uint8_t *hub_port)
+{
+ struct udevice *parent;
+ struct usb_device *uparent, *ttdev;
+
+ /*
+ * When called from usb-uclass.c: usb_scan_device() udev->dev points
+ * to the parent udevice, not the actual udevice belonging to the
+ * udev as the device is not instantiated yet. So when searching
+ * for the first usb-2 parent start with udev->dev not
+ * udev->dev->parent .
+ */
+ ttdev = udev;
+ parent = udev->dev;
+ uparent = dev_get_parent_priv(parent);
+
+ while (uparent->speed != USB_SPEED_HIGH) {
+ struct udevice *dev = parent;
+
+ if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
+ printf("dwc2: Error cannot find high speed parent of usb-1 device\n");
+ *hub_address = *hub_port = 0;
+ return;
+ }
+
+ ttdev = dev_get_parent_priv(dev);
+ parent = dev->parent;
+ uparent = dev_get_parent_priv(parent);
+ }
+ *hub_address = uparent->devnum;
+ *hub_port = ttdev->portnr;
+}
+#else
+static void dwc_find_hub_address_port(struct usb_device *udev,
+ uint8_t *hub_address, uint8_t *hub_port)
+{
+ /* Find out the nearest parent which is high speed */
+ while (udev->parent->parent != NULL)
+ if (udev->parent->speed != USB_SPEED_HIGH) {
+ udev = udev->parent;
+ } else {
+ *hub_address = udev->parent->devnum;
+ *hub_port = udev->portnr;
+ return;
+ }
+
+ printf("dwc2: Error cannot find high speed parent of usb-1 device\n");
+ *hub_address = *hub_port = 0;
+}
+#endif
+
+/*
* Prepares a host channel for transferring packets to/from a specific
* endpoint. The HCCHARn register is set up with the characteristics specified
* in _hc. Host channel interrupts that may need to be serviced while this
--
2.1.4