Skip to content

Commit 8bea147

Browse files
Thinh Nguyengregkh
authored andcommitted
usb: dwc3: Soft reset phy on probe for host
When there's phy initialization, we need to initiate a soft-reset sequence. That's done through USBCMD.HCRST in the xHCI driver and its initialization, However, the dwc3 driver may modify core configs before the soft-reset. This may result in some connection instability. So, ensure the phy is ready before the controller updates the GCTL.PRTCAPDIR or other settings by issuing phy soft-reset. Note that some host-mode configurations may not expose device registers to initiate the controller soft-reset (via DCTL.CoreSftRst). So we reset through GUSB3PIPECTL and GUSB2PHYCFG instead. Cc: stable@vger.kernel.org Fixes: e835c0a ("usb: dwc3: don't reset device side if dwc3 was configured as host-only") Reported-by: Kenta Sato <tosainu.maple@gmail.com> Closes: https://lore.kernel.org/linux-usb/ZPUciRLUcjDywMVS@debian.me/ Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Tested-by: Kenta Sato <tosainu.maple@gmail.com> Link: https://lore.kernel.org/r/70aea513215d273669152696cc02b20ddcdb6f1a.1694564261.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f74a7af commit 8bea147

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

drivers/usb/dwc3/core.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,46 @@ int dwc3_core_soft_reset(struct dwc3 *dwc)
279279
* XHCI driver will reset the host block. If dwc3 was configured for
280280
* host-only mode or current role is host, then we can return early.
281281
*/
282-
if (dwc->dr_mode == USB_DR_MODE_HOST || dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
282+
if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
283283
return 0;
284284

285+
/*
286+
* If the dr_mode is host and the dwc->current_dr_role is not the
287+
* corresponding DWC3_GCTL_PRTCAP_HOST, then the dwc3_core_init_mode
288+
* isn't executed yet. Ensure the phy is ready before the controller
289+
* updates the GCTL.PRTCAPDIR or other settings by soft-resetting
290+
* the phy.
291+
*
292+
* Note: GUSB3PIPECTL[n] and GUSB2PHYCFG[n] are port settings where n
293+
* is port index. If this is a multiport host, then we need to reset
294+
* all active ports.
295+
*/
296+
if (dwc->dr_mode == USB_DR_MODE_HOST) {
297+
u32 usb3_port;
298+
u32 usb2_port;
299+
300+
usb3_port = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
301+
usb3_port |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
302+
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), usb3_port);
303+
304+
usb2_port = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
305+
usb2_port |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
306+
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), usb2_port);
307+
308+
/* Small delay for phy reset assertion */
309+
usleep_range(1000, 2000);
310+
311+
usb3_port &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
312+
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), usb3_port);
313+
314+
usb2_port &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
315+
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), usb2_port);
316+
317+
/* Wait for clock synchronization */
318+
msleep(50);
319+
return 0;
320+
}
321+
285322
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
286323
reg |= DWC3_DCTL_CSFTRST;
287324
reg &= ~DWC3_DCTL_RUN_STOP;

0 commit comments

Comments
 (0)