mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
usb: dwc3: core: fix duplicate phy init when switch device
According to the programming guide, it needs to reset the
device with DCTL.CSftRst when switching from host to device.
The current code use dwc3_core_soft_reset() to do DCTL.CSftRst,
it will also duplicate phy init which has been done in runtime
resume routine, this cause the phy init/exit operations are
unbalanced.
Without this patch, the dwc3 gadget resume fail on RK3568 EVB1
with the following log:
dwc3 fcc00000.dwc3: failed to enable ep0out
It's because that the init_count of usb3 phy is not 0 when
resume, so the dwc3 fail to call usb3 phy init, and the 3.0
pipe clock is not be running.
Fixes: b48bcb27ae ("FROMGIT: usb: dwc3: core: Do core softreset when switch mode")
Signed-off-by: William Wu <william.wu@rock-chips.com>
Change-Id: I58ec26f9f007c94f8979eeeb9a9d683c6db9548f
This commit is contained in:
@@ -114,13 +114,12 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
|
||||
dwc->current_dr_role = mode;
|
||||
}
|
||||
|
||||
static int dwc3_core_soft_reset(struct dwc3 *dwc);
|
||||
|
||||
static void __dwc3_set_mode(struct work_struct *work)
|
||||
{
|
||||
struct dwc3 *dwc = work_to_dwc(work);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
int retries = 1000;
|
||||
u32 reg;
|
||||
|
||||
mutex_lock(&dwc->mutex);
|
||||
@@ -201,7 +200,26 @@ static void __dwc3_set_mode(struct work_struct *work)
|
||||
}
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_DEVICE:
|
||||
dwc3_core_soft_reset(dwc);
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
reg |= DWC3_DCTL_CSFTRST;
|
||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
||||
|
||||
if (DWC3_VER_IS_WITHIN(DWC31, 190A, ANY) || DWC3_IP_IS(DWC32))
|
||||
retries = 10;
|
||||
|
||||
do {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
if (!(reg & DWC3_DCTL_CSFTRST))
|
||||
goto done;
|
||||
|
||||
if (DWC3_VER_IS_WITHIN(DWC31, 190A, ANY) || DWC3_IP_IS(DWC32))
|
||||
msleep(20);
|
||||
else
|
||||
udelay(1);
|
||||
} while (--retries);
|
||||
done:
|
||||
if (DWC3_VER_IS_WITHIN(DWC31, ANY, 180A))
|
||||
msleep(50);
|
||||
|
||||
dwc3_event_buffers_setup(dwc);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user