[PATCH] usb: ehci-vf: take the controller index from the device tree

Mehmet Fide <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
From: Mehmet Fide <[email protected]>

"usb start" dies with a data abort on a Colibri VF50 and on a Colibri
VF61, and the watchdog resets the board:

  Colibri VFxx # usb start
  starting USB...
  Bus usb@40034000: Port not available.
  data abort
  ...
  r4 : 00000003
  Resetting CPU ...

vf_usb_of_to_plat() takes the controller index from dev_seq(), but the
sequence numbers of the two controllers are 2 and 3:

  Class     Seq  Probed  Driver    Name
  usb         2  [   ]   ehci_vf   usb@40034000
  usb         3  [   ]   ehci_vf   usb@400b4000

uclass_find_next_free_seq() starts numbering above the highest alias of
the uclass, and fdtdec_get_alias_highest_id() matches an alias by its
name prefix plus trailing digits, so the usbphy0 and usbphy1 aliases of
the vf device tree count as "usb" aliases and reserve 0 and 1. The two
controllers have no aliases of their own and end up with 2 and 3, past
the two entries of phy_bases[] and nc_reg_bases[]. usb_oc_config() then
loads a base address from beyond the table and writes to it, which is
the abort above. The bounds check that would have caught this only
exists in the non-DM ehci_hcd_init().

Follow the fsl,usbphy phandle, as ehci-mx6 does, and map the PHY node
to the index of the driver's own table instead of trusting the sequence
number, since the alias numbering is what goes wrong here.

Tested on a Colibri VF50 V1.2A on an Iris carrier, U-Boot 2026.07 from
NAND: "usb start" now brings up the host controller and enumerates the
root hub instead of resetting the board.

Signed-off-by: Mehmet Fide <[email protected]>
---
 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.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.