[RFC PATCH] usb: dwc3: wait for USB2 PHY clock recovery during role switch

From: Uttkarsh Aggarwal

Date: Fri Oct 30 2026 - 02:25:33 EST


During a device-to-host role switch, the USB2 PHY may still be
suspended from the previous gadget session. After clearing SUSPHY,
the PHY requires up to 1.5 ms before the UTMI clock is stable.
This was observed during a device-to-host role switch with
a USB earphone attached. Traces showed that SUSPHY remained asserted
until __dwc3_set_mode() cleared it, after which host initialization
immediately started accessing the xHCI PORTSC registers.
The USB2 PHY specification requires up to 1.5 ms for clock recovery
after exiting suspend. Accessing the controller before the UTMI clock has
stabilized can therefore occur during this recovery interval.
Wait for the PHY clock recovery when SUSPHY was set before switching
to host mode. Avoid the delay when the PHY was already active.
This change is limited to the role-switch path. Runtime suspend
requires separate handling

Signed-off-by: Uttkarsh Aggarwal <uttkarsh.aggarwal@xxxxxxxxxxxxxxxx>
---
drivers/usb/dwc3/core.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index fd5c2cd36c59..885bb9301866 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -233,6 +233,20 @@ static void __dwc3_set_mode(struct work_struct *work)
dwc3_writel(dwc, DWC3_GCTL, reg);
}

+ /*
+ * If the USB2 PHY was left suspended (e.g. by
+ * dwc3_gadget_run_stop()/dwc3_gadget_exit() during a device->host
+ * switch), its UTMI clock needs time to become valid again before
+ * dwc3_set_prtcap() flips GCTL.PRTCAP and the new role starts
+ * driving further register accesses on it (e.g. host root hub
+ * PORTSC writes in dwc3_host_init()).
+ */
+ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
+ dwc3_enable_susphy(dwc, false);
+ usleep_range(1500, 2000);
+ }
+
spin_lock_irqsave(&dwc->lock, flags);

dwc3_set_prtcap(dwc, desired_dr_role, false);
--
2.34.1