Re: [RFC][PATCH] HACK: usb: dwc2: Workaround case where GOTGCTL state is wrong

From: John Youn
Date: Tue Dec 06 2016 - 22:52:40 EST


On 12/6/2016 5:48 PM, John Stultz wrote:
> Hey John,
> Just wanted to send this by you, as it seems something is
> slightly off with the GOTGCTL state when removing a otg adapter
> cable. The following seems to work around the issue I'm seeing.
>
> Let me know if you have any thoughts on this.
> thanks
> -john
>
>
> 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
> erroniously see the GOTGCTL_CONID_B flag set. This causes us to

This is the correct behavior for an OTG controller. When you unplug a
cable or plug in the B end of a cable, the ID pin floats, indicating
it is a B-Device.

When you plug in an A-cable, which is what your adapter is, it will
ground the pin, meaning A-device.

> 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 is weird. Once the ID pin goes to B, the core should become a
peripheral and this should be reflected in the status registers.

>
> 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.

This also seems weird. The connector id status shouldn't go back to A,
assuming you've left the cable unplugged.

Is the controller supposed to work in both peripheral and host modes?

>
> I suspect this isn't the best solution, but it seems to work
> well for me.
>

The workaround seems fine, but still, this indicates that something
wrong is going on somwhere.

You can add my ack:

Acked-by: John Youn <johnyoun@xxxxxxxxxxxx>

Regards,
John


> Feedback would be greatly appreciated!
>
> Cc: Wei Xu <xuwei5@xxxxxxxxxxxxx>
> Cc: Guodong Xu <guodong.xu@xxxxxxxxxx>
> Cc: Amit Pundir <amit.pundir@xxxxxxxxxx>
> Cc: Rob Herring <robh+dt@xxxxxxxxxx>
> Cc: John Youn <johnyoun@xxxxxxxxxxxx>
> Cc: Douglas Anderson <dianders@xxxxxxxxxxxx>
> Cc: Chen Yu <chenyu56@xxxxxxxxxx>
> Cc: Kishon Vijay Abraham I <kishon@xxxxxx>
> Cc: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>
> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> Cc: linux-usb@xxxxxxxxxxxxxxx
> Signed-off-by: John Stultz <john.stultz@xxxxxxxxxx>
> ---
> drivers/usb/dwc2/hcd.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 143da47..6d6802a 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -3203,7 +3203,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
> dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
> dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
> !!(gotgctl & GOTGCTL_CONID_B));
> -
> +again:
> /* B-Device connector (Device Mode) */
> if (gotgctl & GOTGCTL_CONID_B) {
> /* Wait for switch to device mode */
> @@ -3219,6 +3219,9 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
> dwc2_is_host_mode(hsotg) ? "Host" :
> "Peripheral");
> usleep_range(20000, 40000);
> + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
> + if (!(gotgctl & GOTGCTL_CONID_B))
> + goto again;
> if (++count > 250)
> break;
> }
>