11-21-2019 06:24 AM
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
and also certain errata is mentioned in USB334x datasheet for TI OMAP4 EHCI controller
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.
01-14-2020 06:22 AM
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
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.
01-14-2020 06:27 AM
@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.
01-16-2020 11:05 AM
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.
02-09-2021 03:57 AM
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.
- 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.
02-09-2021 04:10 AM
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?
02-09-2021 04:21 AM
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)
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;
reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
reg |= DWC3_GUSB3PIPECTL_REQP1P2P3;
reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN;
reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE;
reg |= DWC3_GUSB3PIPECTL_LFPSFILT;
reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL;
reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
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;
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
// Hardcoded for now, fixes High-speed negotiation
// issue with USB3340, see:
// 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);
02-19-2021 08:29 AM
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.
05-20-2021 02:18 AM
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.