Skip to content

Commit 5a29238

Browse files
Selvarasu Ganesanjfvogel
authored andcommitted
usb: dwc3: Fix timeout issue during controller enter/exit from halt state
commit d3a8c28 upstream. There is a frequent timeout during controller enter/exit from halt state after toggling the run_stop bit by SW. This timeout occurs when performing frequent role switches between host and device, causing device enumeration issues due to the timeout. This issue was not present when USB2 suspend PHY was disabled by passing the SNPS quirks (snps,dis_u2_susphy_quirk and snps,dis_enblslpm_quirk) from the DTS. However, there is a requirement to enable USB2 suspend PHY by setting of GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY bits when controller starts in gadget or host mode results in the timeout issue. This commit addresses this timeout issue by ensuring that the bits GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY are cleared before starting the dwc3_gadget_run_stop sequence and restoring them after the dwc3_gadget_run_stop sequence is completed. Fixes: 72246da ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable <stable@kernel.org> Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com> Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/20250201163903.459-1-selvarasu.g@samsung.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 5fead36e095fbcb1bfd921c54159de7c11d42e0c) Signed-off-by: Jack Vogel <jack.vogel@oracle.com>
1 parent 7a873ff commit 5a29238

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

drivers/usb/dwc3/gadget.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,10 +2618,38 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
26182618
{
26192619
u32 reg;
26202620
u32 timeout = 2000;
2621+
u32 saved_config = 0;
26212622

26222623
if (pm_runtime_suspended(dwc->dev))
26232624
return 0;
26242625

2626+
/*
2627+
* When operating in USB 2.0 speeds (HS/FS), ensure that
2628+
* GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY are cleared before starting
2629+
* or stopping the controller. This resolves timeout issues that occur
2630+
* during frequent role switches between host and device modes.
2631+
*
2632+
* Save and clear these settings, then restore them after completing the
2633+
* controller start or stop sequence.
2634+
*
2635+
* This solution was discovered through experimentation as it is not
2636+
* mentioned in the dwc3 programming guide. It has been tested on an
2637+
* Exynos platforms.
2638+
*/
2639+
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
2640+
if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
2641+
saved_config |= DWC3_GUSB2PHYCFG_SUSPHY;
2642+
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
2643+
}
2644+
2645+
if (reg & DWC3_GUSB2PHYCFG_ENBLSLPM) {
2646+
saved_config |= DWC3_GUSB2PHYCFG_ENBLSLPM;
2647+
reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
2648+
}
2649+
2650+
if (saved_config)
2651+
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
2652+
26252653
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
26262654
if (is_on) {
26272655
if (DWC3_VER_IS_WITHIN(DWC3, ANY, 187A)) {
@@ -2649,6 +2677,12 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
26492677
reg &= DWC3_DSTS_DEVCTRLHLT;
26502678
} while (--timeout && !(!is_on ^ !reg));
26512679

2680+
if (saved_config) {
2681+
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
2682+
reg |= saved_config;
2683+
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
2684+
}
2685+
26522686
if (!timeout)
26532687
return -ETIMEDOUT;
26542688

0 commit comments

Comments
 (0)