usb: Move determination of TT hub address/port into separate function
authorStefan Brüns <stefan.bruens@rwth-aachen.de>
Tue, 22 Dec 2015 00:21:03 +0000 (01:21 +0100)
committerMarek Vasut <marex@denx.de>
Thu, 31 Dec 2015 15:16:29 +0000 (16:16 +0100)
Start split and complete split tokens need the hub address and the
downstream port of the first HS hub (device view).

The core of the function was duplicated in both host/ehci_hcd and
musb-new/usb-compat.h.

Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
Reviewed-by: Marek Vasut <marex@denx.de>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
common/usb.c
drivers/usb/host/ehci-hcd.c
drivers/usb/musb-new/musb_host.c
drivers/usb/musb-new/usb-compat.h
include/usb.h

index b1773914cf082e2e8300e97b21d221d381753c3b..9f67cc1e8e8c7af62489b440f85151a9c841965d 100644 (file)
@@ -1214,4 +1214,60 @@ bool usb_device_has_child_on_port(struct usb_device *parent, int port)
 #endif
 }
 
+#ifdef CONFIG_DM_USB
+void usb_find_usb2_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("Error: Cannot find high speed parent of usb-1 device\n");
+                       *hub_address = 0;
+                       *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
+void usb_find_usb2_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("Error: Cannot find high speed parent of usb-1 device\n");
+       *hub_address = 0;
+       *hub_port = 0;
+}
+#endif
+
+
 /* EOF */
index c85dbcecfa739fb2b43a3e162ac5ed441c29cfca..c664b1629e090cc68975cb9d392aa2846fa3cd2e 100644 (file)
@@ -279,56 +279,16 @@ static inline u8 ehci_encode_speed(enum usb_device_speed speed)
 static void ehci_update_endpt2_dev_n_port(struct usb_device *udev,
                                          struct QH *qh)
 {
-       struct usb_device *ttdev;
-       int parent_devnum;
+       uint8_t portnr = 0;
+       uint8_t hubaddr = 0;
 
        if (udev->speed != USB_SPEED_LOW && udev->speed != USB_SPEED_FULL)
                return;
 
-       /*
-        * For full / low speed devices we need to get the devnum and portnr of
-        * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs
-        * in the tree before that one!
-        */
-#ifdef CONFIG_DM_USB
-       /*
-        * 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 .
-        */
-       struct udevice *parent;
-       struct usb_device *uparent;
-
-       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("ehci: Error cannot find high-speed parent of usb-1 device\n");
-                       return;
-               }
-
-               ttdev = dev_get_parent_priv(dev);
-               parent = dev->parent;
-               uparent = dev_get_parent_priv(parent);
-       }
-       parent_devnum = uparent->devnum;
-#else
-       ttdev = udev;
-       while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH)
-               ttdev = ttdev->parent;
-       if (!ttdev->parent)
-               return;
-       parent_devnum = ttdev->parent->devnum;
-#endif
+       usb_find_usb2_hub_address_port(udev, &hubaddr, &portnr);
 
-       qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) |
-                                    QH_ENDPT2_HUBADDR(parent_devnum));
+       qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(portnr) |
+                                    QH_ENDPT2_HUBADDR(hubaddr));
 }
 
 static int
index 40b9c66af89bfea4be21ddffec5b6af2f0a445d2..70f8a994d17dcc308cfa703b6a634de69388e6e1 100644 (file)
@@ -2092,9 +2092,13 @@ int musb_urb_enqueue(
                        }
 #else
                        if (tt_needed(musb, urb->dev)) {
-                               u16 hub_port = find_tt(urb->dev);
-                               qh->h_addr_reg = (u8) (hub_port >> 8);
-                               qh->h_port_reg = (u8) (hub_port & 0xff);
+                               uint8_t portnr = 0;
+                               uint8_t hubaddr = 0;
+                               usb_find_usb2_hub_address_port(urb->dev,
+                                                              &hubaddr,
+                                                              &portnr);
+                               qh->h_addr_reg = hubaddr;
+                               qh->h_port_reg = portnr - 1;
                        }
 #endif
                }
index 1c41e2aadeb60a583ae0687103b3e813ac772002..760bd787bc0beabdfac2355f3495e1919626e5cb 100644 (file)
@@ -68,38 +68,6 @@ static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
 }
 
 #ifdef CONFIG_DM_USB
-static inline u16 find_tt(struct usb_device *udev)
-{
-       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("musb: Error cannot find high speed parent of usb-1 device\n");
-                       return 0;
-               }
-
-               ttdev = dev_get_parent_priv(dev);
-               parent = dev->parent;
-               uparent = dev_get_parent_priv(parent);
-       }
-
-       return (uparent->devnum << 8) | (ttdev->portnr - 1);
-}
-
 static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
 {
        struct udevice *parent = udev->dev->parent;
@@ -129,27 +97,6 @@ static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
        return NULL;
 }
 #else
-static inline u16 find_tt(struct usb_device *dev)
-{
-       u8 chid;
-       u8 hub;
-
-       /* Find out the nearest parent which is high speed */
-       while (dev->parent->parent != NULL)
-               if (dev->parent->speed != USB_SPEED_HIGH)
-                       dev = dev->parent;
-               else
-                       break;
-
-       /* determine the port address at that hub */
-       hub = dev->parent->devnum;
-       for (chid = 0; chid < USB_MAXCHILDREN; chid++)
-               if (dev->parent->children[chid] == dev)
-                       break;
-
-       return (hub << 8) | chid;
-}
-
 static inline struct usb_device *usb_dev_get_parent(struct usb_device *dev)
 {
        return dev->parent;
index 198ecbcbe32a07d1a96927673eb461da3b76c0dc..253936456595b18e0cb477a0c999f96cf4e2004a 100644 (file)
@@ -875,6 +875,18 @@ int legacy_hub_port_reset(struct usb_device *dev, int port,
 
 int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat);
 
+/*
+ * usb_find_usb2_hub_address_port() - Get hub address and port for TT setting
+ *
+ * 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
+ */
+void usb_find_usb2_hub_address_port(struct usb_device *udev,
+                                   uint8_t *hub_address, uint8_t *hub_port);
+
 /**
  * usb_alloc_new_device() - Allocate a new device
  *