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

From: Chen Yu
Date: Fri Dec 09 2016 - 02:13:29 EST




On 2016/12/9 7:29, John Youn wrote:
> On 12/8/2016 2:43 PM, John Stultz wrote:
>> On Tue, Dec 6, 2016 at 7:52 PM, John Youn <John.Youn@xxxxxxxxxxxx> wrote:
>>> 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.
>>>>
>>>>
>>>> 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.
>>
>> Hrm... So normally, when I plug in the gadget cable into the OTG port,
>> I see the change_status irq comes in and the function sees:
>>
>> dwc2 f72c0000.usb: gotgctl=4010000
>> dwc2 f72c0000.usb: gotgctl.b.conidsts=1
>> dwc2 f72c0000.usb: Do port resume before switching to device mode
>> dwc2 f72c0000.usb: dwc2_hsotg_enqueue_setup: failed queue (-11)
>> dwc2 f72c0000.usb: new device is high-speed
>> dwc2 f72c0000.usb: new device is high-speed
>> dwc2 f72c0000.usb: new device is high-speed
>> dwc2 f72c0000.usb: new address 37
>> configfs-gadget gadget: high-speed config #1: b
>>
>> Then when I unplug the cable:
>>
>> dwc2 f72c0000.usb: gotgctl=2200000
>> dwc2 f72c0000.usb: gotgctl.b.conidsts=0
>> usb 1-1: reset high-speed USB device number 13 using dwc2
>>
>>
>>
>> When I plug in the OTG to USB-A adapter cable w/ a mouse plugged in
>> (note I see no change interrupt):
>>
>> usb 1-1: USB disconnect, device number 13
>> usb 1-1: new low-speed USB device number 14 using dwc2
>> input: Logitech USB Optical Mouse as
>> /devices/platform/soc/f72c0000.usb/usb1/1-1/1-1:1.0/0003:046D:C058.0003/input/input3
>> hid-generic 0003:046D:C058.0003: input,hidraw0: USB HID v1.11 Mouse
>> [Logitech USB Optical Mouse] on usb-f72c0000.usb-1/input0
>>
>>
>> Then unplugging the OTG to USB-A adapter cable w/ mouse:
>>
>> dwc2 f72c0000.usb: gotgctl=4010000
>> dwc2 f72c0000.usb: gotgctl.b.conidsts=1
>> dwc2 f72c0000.usb: Do port resume before switching to device mode
>> dwc2 f72c0000.usb: Waiting for Peripheral Mode, Mode=Host
>>
>> <here we get stuck in the loop until it finishes, unless using the
>> patch from this thread>
>>
>> usb 1-1: USB disconnect, device number 14
>> dwc2 f72c0000.usb: gotgctl=2200000
>> dwc2 f72c0000.usb: gotgctl.b.conidsts=0
>> usb 1-1: new high-speed USB device number 15 using dwc2
>> hub 1-1:1.0: USB hub found
>> hub 1-1:1.0: 3 ports detected
>>
>>
>> So I only get the change irq when:
>> * I plug in a micro-usb-B cable for gadget mode
>> * I remove the micro-usb-B cable being used for gadget mode
>> * I remove a OTG to USB-A adapter
>>
>
> That's very strange. It's opposite of how it's supposed to work.
>
>> One slight quirk, is that I don't always see the change irq when
>> removing the OTG to USB, as if I plug in a highspeed mass-storage
>> device, instead of the low-speed mouse, I don't see the change
>> interrupt and the device shows up and disappears the same as when I
>> plug into the normal USB-A host ports on the board.
>>
>>
>>>> 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.
>>
>> So I suspect this has something to do with the way the USB-A host
>> ports on the board are wired up. As removing the usb-b plug seems to
>> switch the device back into A mode.
>>
>> One quirk with this board is that the USB-A ports on the board do not
>> function if anything is in the OTG/B plug (which is frustrating to use
>> at times).
>>
>
> Do you mean there are multiple A-ports on the board hooked up to the
> same controller?
>
> If so, that would go a long way towards explaining things. Because the
> hsotg is a single-port OTG controller. If there are multiple A-ports,
> that means a hub has to be hard-wired internally to the port. But if
> that's the case the OTG function won't work because OTG doesn't work
> through a hub. It must go directly to the otg port. So there must be
> some external logic kicking-in to switch routing to the OTG port or to
> the HUB.
>
> This would explain this behavior with the ID pin status. Since hooking
> up the HUB would make the controller an A-device whereas normally it
> would be a B-device.
>
>> Guodong or Chen Yu understand the hardware details a bit better, and
>> might be able to explain more if you need more information.
>>
>
> Yeah it would be good to get some insight into this from a hardware
> point of view.
>

Actually, I'm not very clear about the hardware details.

In simple terms, there are two Type A USB 2.0 host ports and one microUSB OTG port on the front edge of the board.
The two Type A USB 2.0 host ports connect to a high-speed hub and the hub connect to a USB Switch to which the microUSB OTG port
also connect.
If the Vbus of the microUSB OTG port was high or the ID of the microUSB OTG port was low, the Switch will switch the DP and DM of the SOC
to microUSB OTG port. If no cable was inserted to microUSB OTG port, the Switch will switch the DP and DM of the SOC to the high-speed hub.
There is another import point, the ID pin of soc will be pulled high in both cases:
1.no cable is inserted to microUSB OTG port
2.cable is inserted to microUSB OTG port and ID of microUSB OTG port is low.

If my explanation confuse you, maybe these documents can be helpful.

https://github.com/96boards/documentation/blob/master/ConsumerEdition/HiKey/HardwareDocs/HardwareNotes.md

USB Ports

There are multiple USB ports on the HiKey board:

One microUSB OTG port on the front edge of the board
Two Type A USB 2.0 host ports on the front edge of the board
One USB 2.0 host port on the high-speed expansion bus

https://github.com/96boards/documentation/tree/master/ConsumerEdition/HiKey/AdditionalDocs
Hardware User Guide

https://github.com/96boards/documentation/tree/master/ConsumerEdition/HiKey/HardwareDocs
schematics of the Hikey board

thanks
- Chen Yu