On 8/24/26 8:29 PM, Stefan Eichenberger wrote:
From: Stefan Eichenberger <[email protected]>
On Verdin iMX95, with a USB hub permanently attached to the DWC3 host
port the hub itself enumerates fine but a USB stick plugged into it
fails intermittently:
Verdin iMX95 # usb start
starting USB...
USB XHCI 1.10
Device not responding to set address.
USB device not accepting new address (error=80000000)
Bus usb@4c100000: 2 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Verdin iMX95 # usb reset
resetting USB...
USB XHCI 1.10
WARN endpoint is halted
WARN endpoint is halted
unable to get device descriptor (error=-22)
Commit c6583354b7c1 ("usb: dwc3: Look up reference clock DT phandle in
both controller DT nodes") added a fallback that searches the DWC3
child node's "clock-names" for "ref"/"ref_clk" when it isn't found on
the parent glue node, but always resolves the found index against
glue->clks, a clk_bulk populated only from the parent glue node's own
clock-names list. This is wrong since the child node's clock-names list
is not guaranteed to be in the same order as the parent's, and indeed on
Verdin iMX95 the child node has a different order than the parent node.
Fix it by resolving the index against the child node's clk and ensure to
enable the clock before using it.
Fixes: c6583354b7c1 ("usb: dwc3: Look up reference clock DT phandle in both
controller DT nodes")
Signed-off-by: Stefan Eichenberger <[email protected]>
---
drivers/usb/dwc3/dwc3-generic.c | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 2356b3bc0aa..e16d236bd9d 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -31,6 +31,7 @@ struct dwc3_generic_priv {
struct dwc3 dwc3;
struct phy_bulk phys;
struct gpio_desc *ulpi_reset;
+ struct clk ref_clk;
};
struct dwc3_generic_host_priv {
@@ -76,9 +77,28 @@ static int dwc3_generic_probe(struct udevice *dev,
index = ofnode_stringlist_search(node, "clock-names", "ref");
if (index < 0)
index = ofnode_stringlist_search(node, "clock-names",
"ref_clk");
- }
- if (index >= 0)
+ /*
+ * glue->clks was populated from the parent glue node's own
+ * clock-names list, which can differ in length/order from
+ * this child node's list (e.g. i.MX95: glue has "hsio",
+ * "suspend", the dwc3 child has "bus_early", "ref",
+ * "suspend"). Reusing this index against glue->clks would
+ * silently resolve to the wrong clock, so fetch it directly
+ * from this node instead.
+ */
+ if (index >= 0) {
+ if (!clk_get_by_index(dev, index, &priv->ref_clk)) {
Would it be possible to call clk_get_by_name(dev, ...) and
clk_get_by_name(dev->parent, ...) instead, until one of them succeeds ?
That could make the code simpler.
+ clk_enable(&priv->ref_clk);
+ dwc3->ref_clk = &priv->ref_clk;
+ } else {
+ debug("%s: failed to get ref_clk from DT\n",
dev->name);
dev_dbg()
+ }
+ } else {
+ debug("%s: no ref_clk found in DT\n", dev->name);
dev_dbg()
+ }
+ } else {
dwc3->ref_clk = &glue->clks.clks[index];
+ }
#endif
/*