This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM335x driving USBx_ID with a GPIO

Hello,

in our application we are using a type A 4-pin USB connector connected to the USB0 PHY to allow the connection of USB Mass Storage Devices or other devices in normal usage.

But we'd also like to use the "USB boot" feature embedded in the Sitara boot rom by allowing the communication of our product with a PC (which behaves as a host) so that in production the operators can flash our Product already assembled in its box.

To do this, we are looking for a way of manually turning the USB0_ID pin low once in Linux.

Note: not using Ethernet because of Advisory 1.0.25.

Please, check if this procedure is logically correct:

1. On the PCB, SYSBOOT[...] always selects the order 0.USB, 1.NAND

2. USB0_DRVVBUS is connected to the enable pin of an USB-specific current source driving the VBUS rail for the Sitara host mode. That same VBUS is fed back to USB0_VBUS for level sensing.

3. A GPIO controls the USB0_ID pin: the buffer enable pin (OE) is connected to a ball that is held LOW in the RESET and AFTER RESET state (as per AM335x datasheet), so that USB0_ID is floating (Hi-Z buffer output) at boot. The A (input) pin of the buffer is grounded. To sum up, when OE is high, Y (USB0_ID) is low. When OE is low, Y (USB0_ID) is Hi-Z.

Now, here is what should happen at boot:

CASE 1: EMPTY NAND - PC CONNECTED TO USB0

The boot rom boots up, the GPIO connected to the tri-state buffer - thus to USB0_ID - is held low as stated in the datasheet, the USB0_DRVVBUS is driven low, the USB-specific current source connected to it gets disabled and the AM335x behaves like a device, allowing programming via PC.

CASE 2: PROGRAMMED NAND - PC NOT ATTACHED OR USB KEY CONNECTED TO USB0

The bootrom boots up, like in CASE 1, but can't boot via USB. The boot rom gives control to SPL=>U-Boot. U-Boot (or Linux) brings that GPIO high, USB0_ID goes low, AM335x behaves like a host and USB0_DRVVBUS goes high, enabling the USB-specific current source.

Is the above correct? Are there any logical fallacies?

We have no need of switching roles while in Linux, the only moment in which we need device functionality on the Sitara side is while programming the board for the first time (or subsequent times).

Thank you.

  • I have a few concerns about your plans.

    The first concern is related to VBUS capacitance. You need to read and understand the various USB specifications. The requirements for VBUS capacitance is different for USB host and USB peripheral. The USB specification defines the following capacitors on VBUS.

    A standard USB host must have a minimum of 120uF on VBUS.

    A USB peripheral must have less than 10uF on VBUS.

    Note: The original USB specification did not define a minimum VBUS capacitance for a USB peripheral but they published a recommendation several years ago to use at least a 1uF capacitor on VBUS to prevent transient events on the peripheral VBUS signal when the cable is hot plugged/unplugged.

    The USB VBUS capacitor requirements defined in the USB specification allow a USB peripheral to be hot plugged with a uncharged 10uf VBUS capacitor and the 120uF host capacitor provides enough charge sharing capacity to prevent VBUS from dropping below the specified voltage. This voltage drop is tested during USB certification.

    Note: To meet the requirements of the USB voltage drop test when operating as host, the 120uF capacitor is normally connected to VBUS near the USB host connector. This places the capacitor on the VBUS signal between the VBUS power switch and connector which means it will always be connected to VBUS, even when operating as peripheral.

    When operating your host port as a peripheral, the PC may detect an over-current condition and shut down power to the port connected to your product. This could occur because your host port is required to have a VBUS capacitor greater than 120uF for host operation, but this value of VBUS capacitance is much larger than expected for a peripheral and causes a much high inrush current from the PC when the cable is connected.

    I would recommend using a simple N-channel FET to pull the ID pin low when a GPIO connected to the gate is driven high. Connect the Drain to the ID pin, Source to VSS, and Gate to a GPIO. This circuit does not have any chance of sourcing a potential to the ID pin and it is cheaper than a 3-state buffer.

    You will also need to purchase a Type-A to Type-A cable which is not a standard cable defined by the USB specification.

    Having USB boot first in the boot sequence may add more delay than you want in the normal NAND boot time.

    I only provide hardware support and cannot comment how software supports this use case.

    You should prototype this and verify it works as expected before building your product since it is not a normal use case.

    Regards,
    Paul
  • I highly recommend to use both MUSB ports in your application - musb0 port for device-only mode and musb1 port for host-only mode if you want any *ordinary* USB device to work with your product, mainly due to the VBUS capacitance requirement Paul described above.

    If you have to use a single musb port, you don't have to use the GPIO logic to control the ID pin. Please look at the information about USBx_MODE register in the TRM, which override the ID pin. So you leave ID pin float on the board, the port will work in device-only mode in ROM and uboot. Then you set the register to 0x80 in kernel musb driver, so the port will work in host-only mode when kernel musb driver is loaded.

  • Thank you Paul and Bin for your prompt replies.

    Unfortunately I need to use one port as device/host because the other one is connected to a USB hub with two devices attached.

    Then I will leave the USB_ID totally floating and override the MUSB driver via Linux.

    @Bin: Is it possible to do that with the dr_mode field in the Device Tree or I have to modify the kernel driver?

    About the capacitance, @Paul: have you got any hints on how to mitigate the risk or some particular circuit topology? As of now I am for putting a capacitor and do some trial and error...

    Thank you.

  • primaenoctis said:
    Unfortunately I need to use one port as device/host because the other one is connected to a USB hub with two devices attached.

    Is this a 2-port hub? If you use a 4-port hub, you can bring out an extra port.

    primaenoctis said:
    @Bin: Is it possible to do that with the dr_mode field in the Device Tree or I have to modify the kernel driver?

    No, dr_mode will not solve the issue. USBx_MODE is the only software workaround.

    Regarding the VBUS cap, unless you have full control on the USB devices and ensure only validated dongles will be plugged in, otherwise you design will fail, we know many thumb drives on the market will not work with VBUS cap <10uF.

  • I realize this may not be a valid option for your product, but we provide a jumper option on our EVMs that allow the USB ports to operate as host or peripheral.  We permanently connect a 4.7uF to VBUS with the option of attaching a 150uF to VBUS via two-pin header and shunt.

    Regards,
    Paul