Hello Experts,
To flash our AM69 modules, we enter recovery mode and use DFU provided by the boot ROM to flash the U-Boot SPL on the R5 core of the SoC (tiboot3.bin built by U-Boot).
This part consistently works.
Then, the SPL runs on the R5 core and in turn starts a USB gadget providing DFU. This works most of the time, but not always. Sometimes, we observe that our gadget is never detected by the attached PC.
Debugging shows that in these cases the D+ line is never pulled up by the SoC, and therefore an attached PC will never see the gadget come up and will never try to enumerate this new USB device.
To me, it smells like a bug in cdns3 that is only triggered in certain conditions, but I have not yet figured out which conditions. This form post reports a bug that sounds like it might have a similar root cause: https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1503411/am6442-usb-device-configure-cause-linux-system-hang-2
Because of the similarities, I have tried some of the same patches to the cdns3 driver.
- Removed `writel(PUSB_PWR_FST_REG_ACCESS, &priv_dev->regs->usb_pwr);` from `cdns3_gadget_config`. Bug still occurred.
- Changed USB config in device tree to super-speed and usb3 IP instead of usb2 IP. Bu still occurred.
I have also written to the USB Config register (0x6020000) from `armv7/start.S` to test the behaviour of activating the D+ pullup as the first thing we do after reset. In this case, the pullup is always set correctly and the bug does not occur.
Further debugging showed the sporadic failure of setting the pullup occurs only after the following lines in `drivers/usb/cdns3/gadget.c:cdns3_gadget_udc_start()`:
```
cdns3_gadget_udc_set_speed(gadget, gadget->max_speed);
cdns3_gadget_config(priv_dev);
```
The call to `cdns3_gadget_config` includes setting the pullup at the end, which fails sometimes. It seems that the configuration that happened in these steps can bring the cdns3 IP into a state where sometimes, writing USB_CONF_DEVEN (bit 14) to the USB Config register, has no effect.
When in this broken condition and we attach GDB at that point, I cannot manually write to the USB config register to try and activate the pullup either. I've tried to write USB_CONF_DEVDS (device disable) and then write device enable, but no luck there.
Interestingly, I see that each time the gadget comes up successfully (i.e.: pullup on D+ was asserted), the status register of USB0 reads out `0x10124630`. When it failed, the register reads `0x101e4640`.
I added the following infinite loop right after `cdns3_gadget_config` in `cdns3_gadget_udc_start`:
```
static u32 prev_status_reg;
```
```
U-Boot SPL 2024.04-00807-gd7915930c05d-dirty (Nov 12 2025 - 09:48:22 +0100)
SYSFW ABI: 4.0 (firmware rev 0x000a '10.1.6--v10.01.06 (Fiery Fox)')
HW CFG: 0x00
Initialized 4 DRAM controllers
SPL initial stack usage: 13456 bytes
Trying to boot from DFU
spl_ram_load_image called
run_usb_dnl_gadget called
status_reg: 101c4640
status_reg: 101e4640
status_reg: 10124620
status_reg: 101a4620
status_reg: 10124620
status_reg: 10124630
U-Boot SPL 2024.04-00807-gd7915930c05d-dirty (Nov 12 2025 - 09:48:22 +0100)
SYSFW ABI: 4.0 (firmware rev 0x000a '10.1.6--v10.01.06 (Fiery Fox)')
HW CFG: 0x00
Initialized 4 DRAM controllers
SPL initial stack usage: 13456 bytes
Trying to boot from DFU
spl_ram_load_image called
run_usb_dnl_gadget called
status_reg: 101c4640
status_reg: 101e4640
```
So according to this status register (0x6020004), this USB always starts of in SuperSpeed mode (I have verified that changing the settings in the Device Tree to high-speed or full-speed does not affect this) and then changes to Full-Speed/High-Speed afterwards.
Since that change does not happen in the broken case, it seems to me that there is some bug in the hardware there or in the software support.
My debugging took place on U-Boot v2024.04 but I have looked at and tested the changes in cdns3 upstream, there don't seem to be many.
Any guidance on this issue?
Kind regards and thanks for reading,
Ernest Van Hoecke - Toradex



