usb: dwc2: Workaround case where GOTGCTL state is wrong
When removing a USB-A to USB-otg adapter cable, we get a change status irq, and then in dwc2_conn_id_status_change, we erroneously see the GOTGCTL_CONID_B flag set. This causes us to get stuck in the "while (!dwc2_is_device_mode(hsotg))" loop, spitting out "Waiting for Peripheral Mode, Mode=Host" warnings until it fails out many seconds later. This patch works around the issue by re-reading the GOTGCTL state to check if the GOTGCTL_CONID_B is still set and if not restarting the change status logic. Cc: Wei Xu <xuwei5@hisilicon.com> Cc: Guodong Xu <guodong.xu@linaro.org> Cc: Amit Pundir <amit.pundir@linaro.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: John Youn <johnyoun@synopsys.com> Cc: Douglas Anderson <dianders@chromium.org> Cc: Chen Yu <chenyu56@huawei.com> Cc: Vardan Mikayelyan <mvardan@synopsys.com> Cc: Kishon Vijay Abraham I <kishon@ti.com> Cc: Felipe Balbi <felipe.balbi@linux.intel.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: linux-usb@vger.kernel.org Reviewed-by: Vardan Mikayelyan <mvardan@synopsys.com> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
parent
6e6360b67d
commit
fc30c4bb44
|
@ -3237,6 +3237,14 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
|
|||
dwc2_is_host_mode(hsotg) ? "Host" :
|
||||
"Peripheral");
|
||||
msleep(20);
|
||||
/*
|
||||
* Sometimes the initial GOTGCTRL read is wrong, so
|
||||
* check it again and jump to host mode if that was
|
||||
* the case.
|
||||
*/
|
||||
gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
|
||||
if (!(gotgctl & GOTGCTL_CONID_B))
|
||||
goto host;
|
||||
if (++count > 250)
|
||||
break;
|
||||
}
|
||||
|
@ -3251,6 +3259,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
|
|||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
dwc2_hsotg_core_connect(hsotg);
|
||||
} else {
|
||||
host:
|
||||
/* A-Device connector (Host Mode) */
|
||||
dev_dbg(hsotg->dev, "connId A\n");
|
||||
while (!dwc2_is_host_mode(hsotg)) {
|
||||
|
|
Loading…
Reference in New Issue