From: Mehmet Fide <[email protected]>

"usb start" on a Colibri VF50 or VF61 ends in a data abort and a
watchdog reset.

vf_usb_of_to_plat() takes the controller index from dev_seq(), but the
usbphy0 and usbphy1 aliases count as "usb" aliases when the uclass
numbers its devices, so the two controllers get 2 and 3 and index past
the two entries of phy_bases[] and nc_reg_bases[]. usb_oc_config() then
writes through an address read from beyond the table.

Follow the fsl,usbphy phandle, as ehci-mx6 does, and map the PHY node to
the index of the table instead of trusting the sequence number.

Signed-off-by: Mehmet Fide <[email protected]>
---
Changes in v4:
- sent alone before, now patch 1 of the series
- reworded the commit message, no code change
- the test note moved here: on a Colibri VF50 V1.2A on an Iris carrier,
  "usb start" brings up the controller instead of resetting the board

 drivers/usb/host/ehci-vf.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c
index 96d1363a76e..32fe05920d0 100644
--- a/drivers/usb/host/ehci-vf.c
+++ b/drivers/usb/host/ehci-vf.c
@@ -221,8 +221,23 @@ static int vf_usb_of_to_plat(struct udevice *dev)
        const void *dt_blob = gd->fdt_blob;
        int node = dev_of_offset(dev);
        const char *mode;
+       fdt_addr_t phy_addr;
+       ofnode phy_node;
+       int i;
 
-       priv->portnr = dev_seq(dev);
+       phy_node = ofnode_parse_phandle(dev_ofnode(dev), "fsl,usbphy", 0);
+       if (!ofnode_valid(phy_node))
+               return -EINVAL;
+
+       phy_addr = ofnode_get_addr(phy_node);
+       for (i = 0; i < ARRAY_SIZE(phy_bases); i++) {
+               if (phy_addr == phy_bases[i])
+                       break;
+       }
+       if (i == ARRAY_SIZE(phy_bases))
+               return -EINVAL;
+
+       priv->portnr = i;
 
        priv->ehci = dev_read_addr_ptr(dev);
        mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
-- 
2.55.0

Reply via email to