cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
darko31
Observer
Observer
1,874 Views
Registered: ‎05-07-2018

USB stuck in full speed mode with USB3340 ULPI PHY, ZynqMP

Hello,

we have a custom board with xczu4eg-sfvc784-2-e part. On this board we'd like to use USB in peripheral mode as a gadget device either in USB 2.0 or USB 3.0 depending on which port the board is connected. USB3340 ULPI phy is used. Versions of SDK, Vivado and Yocto layers are 2018.3.

We used mass storage gadget as an example and got it working with USB 3.0. But if the board is connected to USB 2.0 it only works in Full Speed configuration

dmesg output for gadget - g_mass_storage gadget: full-speed config #1: Linux File-Backed Storage

After some googling and investigation, it seems ULPI phy and DWC3 controller related problem. 

People with STM32 MCUs have this problem with this USB3340

https://community.st.com/s/question/0D50X00009XkZUeSAN/stm32f2f4-problems-with-various-ulpi-usb-phys

and also certain errata is mentioned in USB334x datasheet for TI OMAP4 EHCI controller

http://ww1.microchip.com/downloads/en/DeviceDoc/80000645A.pdf

People over at ST forums point it out LPM (Link Power Managment) related problem, while in phy's errata, timings and order of Resume/Suspend commands are mentioned as a problem.

We replaced USB3340 with USB3320 phy (which doesn't have LPM feature) and the problem is gone, gadget works in high speed mode. We would like to use USB3340 because timings are better than USB3320.

We have read the USB3340 phy's Function Control register with command devmem 0xFE20C280 32 0x02040000 && devmem 0xFE20C280 which returns 0x01040045. 45 at the end indicates register data. Binary value is 01000101, bit 7 is 0 which indicates that LPM at phy is disabled.

Did anyone encounter similar problems with and could confirm how to fix the problem besides changing the phy? I would assume that certain patches in DWC3 driver are needed to fix this.

Thank you.

Darko

 

 

10 Replies
jdefields
Explorer
Explorer
1,735 Views
Registered: ‎12-02-2014

I am experiencing the same issue, and we have not found a solution yet unfortunately.  Have you had any success in resolving this yet?

0 Kudos
darko31
Observer
Observer
1,725 Views
Registered: ‎05-07-2018

Unfortunately not, we reverted back to USB3320 PHY. It seems that it's a problem related between DWC3 controller and USB3340 PHY ULPI communication.  

We believe it is Module 2 related in errata

http://ww1.microchip.com/downloads/en/DeviceDoc/80000645A.pdf

Quote from the errata

Device Enumeration Failure with Link IP Systems
Description
When the PHY is used in a Device application with certain link IP systems, it will not enumerate as a High Speed
device. During the high speed chirp sequence, the device will drive DP to 1.6V when it is should drive DM to
800mV.
To prevent an incorrect value from being written to the ULPI register, the USB334x includes an added feature
that checks the ULPI lines for collisions after every ULPI write. This check is performed in the clock cycle after
the ULPI write has completed. However, some link IP versions do not account for this behavior. In these cases,
a transmit command is sent immediately after a ULPI register write, without any delay, causing the behavior
detailed above.
End User Implications
Systems that include link IP will not be able to enumerate as High Speed devices. All other communication will
function properly.
Solution
If the user is provided the ability to control the link software, adding a 1 clock cycle delay between the ULPI register write and transmit command will ensure proper chirp execution. If the user cannot change the link software,
the USB332x and USB331x PHYs may be used in place of the USB334x PHY.

As you can see, possible solution is to add 1 clock cycle delay between the ULPI register write and transmit command.

Unfortunately, this seems to be modification on a hardware level of the DWC3 controller, and it looks like there isn't an option to control this from the Linux DWC3 driver.

Since DWC3 is Synopsys IP, it may be a better option to contact them regarding this problem, since there isn't much that Xilinx can do in this case.

Note that is is only speculation, we haven't confirmed that this is indeed the issue since we don't have resources to analyze this problem further by capturing ULPI communication between controller and PHY.


jdefields
Explorer
Explorer
1,719 Views
Registered: ‎12-02-2014

@darko31, thanks for your quick response!  That mirrors the thoughts that I've had about the situation, given the 2nd USB3340 errata.  I'm not sure if we will end up switching to the USB3320, but it's good to isolate the problem in this way.  We have other products that indeed use a USB3320 just fine.

0 Kudos
jdefields
Explorer
Explorer
1,650 Views
Registered: ‎12-02-2014

Just an update,

We had a board reworked to use a USB3320 instead, and now it's negotiating to high-speed as expected!

Thanks for all of your investigation into this issue!  Would be great if there was a better work-around, but it doesn't look like that is the case.

pedrob
Visitor
Visitor
850 Views
Registered: ‎02-09-2021

A little late to the game perhaps, but someone might find this useful. We hade the same setup with the same issue when trying to get a High-Speed link when acting as a peripheral. We found a workaround however. You can set the XCVRDLY bit in dcw3 register GUSB2PHYCFG. After patching in that change in u-boot everything worked as expected. Description of that bit:

XCVRDLY - Transceiver Delay:
Enables a delay between the assertion of the UTMI/ULPI Transceiver Select signal (for HS) and the assertion of the TxValid signal during a HS Chirp.
When this bit is set to 1, a delay (of approximately 2.5 us) is introduced from the time when the Transceiver Select is set to 2'b00 (HS) to the time the TxValid is driven to 0 for sending the chirp-K. This delay is required for some UTMI/ULPI PHYs.
Note:
- If you enable the hibernation feature when the device core comes out of power-off, you must re-initialize this bit with the appropriate value because the core does not save and restore this bit value during hibernation.
- This bit is valid only in device mode.

darko31
Observer
Observer
836 Views
Registered: ‎05-07-2018

Literally today we had some left over boards with 3340 reworked to 3320, so we won't be trying this out right away, but thanks for the tip.

Do you mind sharing the code snippet, and did you only change dwc3 driver in u-boot, Linux driver wasn't patched?

0 Kudos
pedrob
Visitor
Visitor
828 Views
Registered: ‎02-09-2021

So far I've only needed USB support in u-boot so I haven't come around to testing it in Linux yet. But it should be easy to add that patch in Linux as well as the drivers are very similar. I haven't taken hibernation into account though, as you have to re-set this bit after it goes out of hibernation. But we don't have hibernation enabled at the moment, so not an issue for us.

This is for u-boot xlnx v2019.1, you can see my one-line change and a massive comment. It should be easy enough to port to any other recent version of u-boot.

In file drivers/usb/dwc3/core.h

#define DWC3_GUSB2PHYCFG_XCVRDLY    (1 << 9)

In file drivers/usb/dwc3/core.c  (see bold text for change)
/**
 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
 * @dwc: Pointer to our controller context structure
 */
static void dwc3_phy_setup(struct dwc3 *dwc)
{
    u32 reg;

    reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));

    /*
     * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
     * to '0' during coreConsultant configuration. So default value
     * will be '0' when the core is reset. Application needs to set it
     * to '1' after the core initialization is completed.
     */
    if (dwc->revision > DWC3_REVISION_194A)
        reg |= DWC3_GUSB3PIPECTL_SUSPHY;

    if (dwc->u2ss_inp3_quirk)
        reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;

    if (dwc->req_p1p2p3_quirk)
        reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;

    if (dwc->del_p1p2p3_quirk)
        reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;

    if (dwc->del_phy_power_chg_quirk)
        reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;

    if (dwc->lfps_filter_quirk)
        reg |= DWC3_GUSB3PIPECTL_LFPSFILT;

    if (dwc->rx_detect_poll_quirk)
        reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;

    if (dwc->tx_de_emphasis_quirk)
        reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);

    if (dwc->dis_u3_susphy_quirk)
        reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;

    dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);

    mdelay(100);

    reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));

    /*
     * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
     * '0' during coreConsultant configuration. So default value will
     * be '0' when the core is reset. Application needs to set it to
     * '1' after the core initialization is completed.
     */
    if (dwc->revision > DWC3_REVISION_194A)
        reg |= DWC3_GUSB2PHYCFG_SUSPHY;

    if (dwc->dis_u2_susphy_quirk)
        reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;

    // Hardcoded for now, fixes High-speed negotiation
    // issue with USB3340, see:
    // http://ww1.microchip.com/downloads/en/DeviceDoc/80000645A.pdf
    // TODO:
    // Add as a device tree setting once we upgrade to u-boot v2020.1
    // since it has general support for dwc3 device tree settings.
    // Furthermore, this bit needs to be set again when the
    // device comes out of hibernation, this is currently not an issue
    // since hibernation is not enabled.
    reg |= DWC3_GUSB2PHYCFG_XCVRDLY;

    dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);

    mdelay(100);
}

darko31
Observer
Observer
715 Views
Registered: ‎05-07-2018

Just to confirm, phy_setup is a little bit different in linux-xlnx rel-v2019.1, but same line the 

reg |= DWC3_GUSB2PHYCFG_XCVRDLY;

fixes the issue and high speed USB negotiation works.

Thanks again!

pedrob
Visitor
Visitor
644 Views
Registered: ‎02-09-2021

Good to hear that it solved your issues as well and thanks for confirming the fix!

/P

0 Kudos
mariusmm
Visitor
Visitor
323 Views
Registered: ‎02-13-2020

I can confirm the problem is still present in petalinux 2020.2 and can be solved adding the line:

 

        if (dwc->dis_u2_freeclk_exists_quirk)
                reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS;

reg |= DWC3_GUSB2PHYCFG_XCVRDLY;

        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);

        return 0;

 

Thank you so much, you saved my day.