mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] usb: dwc3: apply XCVRDLY after PHY init
@ 2026-11-09 17:22 Brian Ellis via B4 Relay
  2026-11-10 13:28 ` Ingo Rohloff
  0 siblings, 1 reply; 3+ messages in thread
From: Brian Ellis via B4 Relay @ 2026-11-09 17:22 UTC (permalink / raw)
  To: Thinh Nguyen, Greg Kroah-Hartman, Ingo Rohloff
  Cc: linux-usb, linux-kernel, stable, Brian Ellis

From: Brian Ellis <brianellis@gotenna.com>

Commit a28de6335657 ("usb: dwc3: Support USB3340x ULPI PHY high-speed
negotiation.") sets GUSB2PHYCFG.XCVRDLY in dwc3_ulpi_setup(), which
dwc3_core_init() calls straight after ULPI init.  That is before
dwc3_core_get_phy(), dwc3_phy_init(), dwc3_core_soft_reset() and
dwc3_phy_power_on(), so the bit is already asserted while the PHY is
brought up.

On a ZynqMP board (DWC3 2.90a, peripheral mode) with a USB3340, that
ordering breaks high-speed links.  Each link enumerates at 480 Mbps and
passes traffic, then drops 2.20-2.23 s after enumeration, and the host's
attempts to re-enumerate the device fail.  We measured 12 such links on
two host root ports; every one died in that window.

What matters is when the bit is written, not its value.  Written at the
end of dwc3_core_init() instead, GUSB2PHYCFG holds the same value
(0x00022710 on this board), and high-speed links on the same board stay
up: one ran continuously for over 1000 s with no receive errors, and 60
re-enumeration cycles completed without a failure.

Move the dwc3_ulpi_setup() call to the end of dwc3_core_init().  The bit
is still set well before any high-speed chirp, which only happens when a
host enumerates the device.

Fixes: a28de6335657 ("usb: dwc3: Support USB3340x ULPI PHY high-speed negotiation.")
Cc: stable@vger.kernel.org
Signed-off-by: Brian Ellis <brianellis@gotenna.com>
---
How this was tested: not on mainline.  The failure and the fix were both
measured on our board running AMD's 6.6-based vendor kernel (through
ADI's tree), with a28de6335657 backported.  The backport calls
dwc3_ulpi_setup() from the same place and differs only in handling a
single USB2 port.  The 12 failing links were attached directly to two
host root ports.  The 1000 s run was through a hub, on a kernel carrying
this change plus five other local dwc3, ULPI and extcon patches.  The 60
re-enumeration cycles were direct to two root ports, on a later build
with more of our local USB fixes.  On mainline the change is
compile-tested only (x86_64 allmodconfig, W=1, no new warnings).

Not established: why the ordering matters.  The outcome follows whether
XCVRDLY is asserted before dwc3_phy_init(), not the value written, but
we have not identified which step of PHY bring-up is sensitive to it.

Ingo, if your USB3340 board is still to hand, it would help to know
whether its high-speed links stay up for more than a few seconds, with
and without this change.

Not addressed here: on our board the ULPI ID read that a28de6335657 uses
to detect the USB3340 fails when no cable is attached at boot, because
this PHY only clocks ULPI with VBUS present, so the bit is never set and
the port runs at full speed.  Fixing that needs a DT property and a
binding update, so it is not part of this fix.

Tool use: an LLM coding assistant (Claude) helped run the investigation
and keep its record, wrote the code change, and drafted this changelog
and these notes from that record.  The measurements were taken on our
hardware.
---
 drivers/usb/dwc3/core.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index fd5c2cd36c..9b37ceda9a 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1371,8 +1371,6 @@ int dwc3_core_init(struct dwc3 *dwc)
 		dwc->ulpi_ready = true;
 	}
 
-	dwc3_ulpi_setup(dwc);
-
 	if (!dwc->phys_ready) {
 		ret = dwc3_core_get_phy(dwc);
 		if (ret)
@@ -1534,6 +1532,9 @@ int dwc3_core_init(struct dwc3 *dwc)
 		dwc3_writel(dwc, DWC3_GUCTL3, reg);
 	}
 
+	/* XCVRDLY must not be asserted across PHY init, so set it last. */
+	dwc3_ulpi_setup(dwc);
+
 	return 0;
 
 err_power_off_phy:

---
base-commit: 3149e8b3237f58d4dd440fc64c45c93404c4b064
change-id: 20261109-dwc3-xcvrdly-after-phy-init-509803f4b0c8

Best regards,
-- 
Brian Ellis <brianellis@gotenna.com>



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-10 13:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-09 17:22 [PATCH] usb: dwc3: apply XCVRDLY after PHY init Brian Ellis via B4 Relay
2026-11-10 13:28 ` Ingo Rohloff
2026-11-10 13:32   ` Ingo Rohloff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®