Linux USB
 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-09 17:43 ` sashiko-bot
  2026-11-10 13:28 ` Ingo Rohloff
  0 siblings, 2 replies; 5+ 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 related	[flat|nested] 5+ messages in thread
* Re: [PATCH] usb: dwc3: apply XCVRDLY after PHY init
@ 2026-11-11 15:00 Brian Ellis (US)
  0 siblings, 0 replies; 5+ messages in thread
From: Brian Ellis (US) @ 2026-11-11 15:00 UTC (permalink / raw)
  To: Ingo Rohloff, Brian Ellis via B4 Relay
  Cc: Thinh Nguyen, Greg Kroah-Hartman, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org

[ resending as plain text ]

Greg, please don't apply this patch; I withdraw it.

On Tue, 10 Nov 2026 14:28:06 +0100, Ingo Rohloff wrote:
I have a hypothesis what the problem is:
USB 2.0 LPM (Low Power Management).
Hello Ingo,

You were right, thank you. We tested XCVRDLY written early (where
a28de6335657 writes it) and late (this patch), with the host using
USB 2.0 LPM on the link or not. With LPM in use, the link died at
the first traffic every time, whichever way XCVRDLY was written. With
LPM off, it stayed up for the full 300 s every time, again either way.
We switched LPM off from the host side rather than running your
composite patch.

So it is LPM, and where XCVRDLY is written makes no difference.

Where did the 60 re-enumeration cycles came from?
If the link "stays up", then why do you get a re-enumeration?
They were deliberate: a soak that disconnected and reconnected the
gadget through soft_connect, to check enumeration itself. They were
not link losses. But that build already had LPM disabled in our
device tree, and the 1000 s run went through a hub, where the host
doesn't use LPM. That is why both looked like evidence for the
Reordering.

On the circuit: our board powers the USB3340's VBAT from the
connector's VBUS, so with no cable attached the PHY gives no ULPI
clock. That was a bad design choice, and the next board spin fixes
it. So the DT property I mentioned isn't needed upstream either.

An LLM assistant (Claude) helped run these tests and draft this reply.

Thanks,
Brian Ellis
Senior Firmware Engineer
goTenna
________________________________________
From: Ingo Rohloff <ingo.rohloff@lauterbach.com>
Sent: Tuesday, November 10, 2026 6:32 AM
To: Brian Ellis via B4 Relay <devnull+brianellis.gotenna.com@kernel.org>
Cc: Brian Ellis (US) <brianellis@gotenna.com>; Thinh Nguyen <Thinh.Nguyen@synopsys.com>; Greg Kroah-Hartman <gregkh@linuxfoundation.org>; linux-usb@vger.kernel.org <linux-usb@vger.kernel.org>; linux-kernel@vger.kernel.org <linux-kernel@vger.kernel.org>; stable@vger.kernel.org <stable@vger.kernel.org>
Subject: Re: [PATCH] usb: dwc3: apply XCVRDLY after PHY init

[You don't often get email from ingo.rohloff@lauterbach.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]

CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.


Hello Brian,

> This very likely depends on how exactly you use the USB344x.
> On my board I am using a USB3346 with the circuit described in
>
> https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/00001880A.pdf
>
> Figure 8-1 USB333X DEVICE APPLICATION DIAGRAM
> (CONFIGURED FOR ULPI CLOCK OUTPUT MODE)
>
> What kind of circuit does your board use?

I am sorry that was the wrong PDF :-(

https://ww1.microchip.com/downloads/aemDocuments/documents/UNG/ProductDocuments/DataSheets/USB334x-Data-Sheet-DS00002646A.pdf

FIGURE 8-1: USB3341, USB3346, AND USB3347 APPLICATION DIAGRAM
(DEVICE CONFIGURED FOR ULPI CLOCK OUTPUT MODE)

with best regards
  Ingo

On Tue, 10 Nov 2026 14:28:06 +0100
Ingo Rohloff <ingo.rohloff@lauterbach.com> wrote:

> Hello Brian,
>
> > 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.
>
> I have a hypothesis what the problem is:
> USB 2.0 LPM (Low Power Management).
> Please try the attached patch.
> If this helps: That's the origin why you loose the link.
>
> It seems USB344x + DWC3 don't support USB 2.0 LPM in this combination.
>
> Note: This problem only appears when your HOST USB Controller also
> supports USB 2.0 LPM.
> Meaning: Depending on your exact Host PC you might not see this effect.
> Only recent PCs support USB 2.0 LPM; on my PC here only some specific
> USB ports support USB 2.0 LPM. So on my PC it depends to which USB port
> you connect the device to.
>
>
> > 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.
>
> Yes this board is very much on hand ;-)
> The high-speed link there stays up indefinitely.
>
> > 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.
>
> At least for my board this is not the case.
>
> I get a completely stable 60Mhz ULPI clock regardless of if
> VBUS is present or not.
>
> Which of course in turn means the ULPI ID can be read out without
> any problems.
>
> This very likely depends on how exactly you use the USB344x.
> On my board I am using a USB3346 with the circuit described in
>
> https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/00001880A.pdf
>
> Figure 8-1 USB333X DEVICE APPLICATION DIAGRAM
> (CONFIGURED FOR ULPI CLOCK OUTPUT MODE)
>
> What kind of circuit does your board use?
>
> > Fixing that needs a DT property and a binding update, so it is not part of this fix.
>
> That was my original patch proposal: Use a DT property.
> I got push-back on that idea.
> The auto-detection via using the ULPI ID is a lot nicer.
> Of course this doesn't work if you don't have a stable ULPI CLK signal.
>
> > 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.
>
> Where did the 60 re-enumeration cycles came from?
> If the link "stays up", then why do you get a re-enumeration?
>
> It might have something to do with what happens with the
> ULPI PHY when USB 2.0 LPM gets active.
> When the host looses the link (which should not happen in the first place)
> because of USB 2.0 LPM, then it re-enumerates.
> Depending on where you put the "dwc3_ulpi_setup(dwc);"
> this re-enumeration after link loss (because of USB 2.0 LPM)
> might then work.
>
> But again the link should not be lost in the first place.
>
> with best regards
>   Ingo
>
>
>
>
>
> On Mon, 09 Nov 2026 10:22:31 -0700
> Brian Ellis via B4 Relay <devnull+brianellis.gotenna.com@kernel.org> wrote:
>
> > 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,
>
>
>



--

-------------------------------------------------------------------------
Dipl.-Inform.
Ingo ROHLOFF
Senior Staff Engineer
phone +49 8102 9876-142 - ingo.rohloff@lauterbach.com

Lauterbach Engineering GmbH & Co. KG
Altlaufstrasse 40, 85635 Hoehenkirchen-Siegertsbrunn, GERMANY
http://www.lauterbach.com/

Registered Office: Hoehenkirchen-Siegertsbrunn, Germany,
Local Court: Munich, HRA 87406, VAT ID: DE246770537,
Managing Directors: Stephan Lauterbach, Dr. Thomas Ullmann

-------------------------------------------------------------------------
________________________________
The information contained in this e-mail and any attachments from Forterra may contain confidential and/or proprietary information, and is intended only for the named recipient to whom it was originally addressed. If you are not the intended recipient, any disclosure, distribution, or copying of this e-mail or its attachments is strictly prohibited. If you have received this e-mail in error, please notify the sender immediately by return e-mail and permanently delete the e-mail and any attachments.

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

end of thread, other threads:[~2026-11-11 15:00 UTC | newest]

Thread overview: 5+ 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-09 17:43 ` sashiko-bot
2026-11-10 13:28 ` Ingo Rohloff
2026-11-10 13:32   ` Ingo Rohloff
  -- strict thread matches above, loose matches on Subject: below --
2026-11-11 15:00 Brian Ellis (US)

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