On 8/18/26 5:12 PM, Mehmet Fide wrote:
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;
Would it be possible to eliminate the priv->portnr and index based PHY
handling in favor of parsing the PHY addresses from DT fully, possibly
in a follow up patch ?
This fix looks good.