On Mon Aug 10, 2026 at 1:52 PM IST, Anders Roxell wrote:
> On 2026-08-06 18:47, Anshul Dalal wrote:
>> On Thu, 16 Jul 2026 15:41:30 +0200, Anders Roxell <[email protected]>
>> wrote:
>> > [...]
>> > This is compile-tested only.
>> >
>> > The series needs the dwc2 endpoint fixes from Mattijs [3]. They are
>> > already on the list and should go in first.
>> >
>> > The branch is also available at [4].
>>
>> Hi Andres,
>
> Hi Anshul,
>
> Thanks for testing on real hardware.
>
>>
>> I was unable to get DFU boot to work on TI devices with this patch series. I
>> tested on AM62p EVM where I don't see any error logs on the console but the
>> DFU device never shows up on the host side (verified with dfu-util and
>> lsusb).
>>
>> I'm not that familiar with dwc3 but the issue seems to be that dwc3_interrupt
>> doesn't report any interrupts.
>
>
> The event path is broken in three places. The main one: in the kernel
> dwc3_check_event_buf() copies the event ring into evt->cache and
> dwc3_process_event_buf() reads from evt->cache. We took the reader but not
> the copy, so it walks a buffer nothing fills. Before the resync we read
> evt->buf directly, so it worked. I think this is what you are hitting, but
> you have the board.
>
> We also never write the count back to GEVNTCOUNT, and dwc3_thread_interrupt()
> gets the controller where it wants the event buffer.
>
> Fix below, it follows the kernel dwc3_invalidate_cache() is ours, it was in
> io.h before the resync and got lost.
>
> --- a/drivers/usb/dwc3/io.h
> +++ b/drivers/usb/dwc3/io.h
> @@ -48,4 +48,12 @@ static inline void dwc3_flush_cache(uintptr_t addr, int
> length)
> flush_dcache_range((unsigned long)start_addr, (unsigned long)end_addr);
> }
>
> +static inline void dwc3_invalidate_cache(uintptr_t addr, int length)
> +{
> + uintptr_t start_addr = (uintptr_t)addr & ~(CACHELINE_SIZE - 1);
> + uintptr_t end_addr = ALIGN((uintptr_t)addr + length, CACHELINE_SIZE);
> +
> + invalidate_dcache_range((unsigned long)start_addr, (unsigned
> long)end_addr);
> +}
> +
> #endif /* __DRIVERS_USB_DWC3_IO_H */
>
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -4201,23 +4201,46 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3
> *dwc)
> {
> struct dwc3_event_buffer *evt;
> + u32 amount;
> u32 count;
> - u32 reg;
>
> evt = dwc->ev_buf;
>
> + if (evt->flags & DWC3_EVENT_PENDING)
> + return IRQ_HANDLED;
> +
> count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
> count &= DWC3_GEVNTCOUNT_MASK;
> if (!count)
> return IRQ_NONE;
>
> + if (count > evt->length) {
> + dev_err(dwc->dev, "invalid count(%u) > evt->length(%u)\n",
> + count, evt->length);
> + return IRQ_NONE;
> + }
> +
> evt->count = count;
> evt->flags |= DWC3_EVENT_PENDING;
>
> /* Mask interrupt */
> - reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0));
> - reg |= DWC3_GEVNTSIZ_INTMASK;
> - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
> + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
> + DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length));
> +
> + /* The controller filled the buffer over DMA, drop our stale lines */
> + dwc3_invalidate_cache((uintptr_t)evt->buf, evt->length);
> +
> + amount = min(count, evt->length - evt->lpos);
> + memcpy(evt->cache + evt->lpos, evt->buf + evt->lpos, amount);
> +
> + if (amount < count)
> + memcpy(evt->cache, evt->buf, count - amount);
> +
> + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
>
> return IRQ_WAKE_THREAD;
> }
>
> And in dwc3_gadget_uboot_handle_interrupt(), same file:
>
> - struct dwc3_event_buffer *evt;
> - dwc3_thread_interrupt(0, dwc);
> + struct dwc3_event_buffer *evt = dwc->ev_buf;
> + dwc3_thread_interrupt(0, evt);
Thanks for the pointers Anders but I encounter a similar failure even
with the diff you suggested. I enabled some logging for the SPL by
defining the DEBUG macro in the following files (dfu.c spl.c spl_ram.c
dwc3-am62.c composite.c g_dnl.c).
Failure logs:
U-Boot SPL 2026.07-00860-g5a9b7a715be2 (Aug 10 2026 - 15:06:27 +0530)
SYSFW ABI: 4.0 (firmware rev 0x000c '12.1.0--v12.01.00 (Clever Cat)')
Set clock rates for '/a53@0', CPU: 1250MHz at Speed Grade 'V'
SPL initial stack usage: 17104 bytes
SPL malloc() before relocation used 0x64d0 bytes (25 KB)
>>SPL: board_init_r()
spl_init
Trying to boot from DFU
g_dnl_register: g_dnl_driver.name = usb_dnl_dfu
g_dnl_bind: gadget: 0x81c44a98 cdev: 0x81c66bc0
usb_add_config: adding config #1 'usb_dnload'/81c67cc0
g_dnl_do_config: configuration: 0x81c67cc0 composite dev: 0x81c66bc0
adding 'dfu'/81c67d34 to config 'usb_dnload'/81c67cc0
cfg 1/81c67cc0 speeds: high full
usb_add_config: interface 0 = dfu/81c67d34
g_dnl_bind: calling usb_gadget_connect for controller 'dwc3-gadget'
usb_dnl_dfu: ready
<CTRL-C> from user
unbind function 'dfu'/81c67d34
g_dnl_unbind: calling usb_gadget_disconnect for controller 'dwc3-gadget'
Legacy image
u_boot_pos = ffffffff
Raw boot image support not enabled, proceeding to other boot methods
Error: -22
SPL: Unsupported Boot Device!
SPL: failed to boot from all boot devices
### ERROR ### Please RESET the board ###
Succes logs (same debug symbols ontop of main branch):
U-Boot SPL 2026.10-rc1-00209-g0bdd5e5daf95 (Aug 10 2026 - 14:58:28
+0530)
SYSFW ABI: 4.0 (firmware rev 0x000c '12.1.0--v12.01.00 (Clever Cat)')
Set clock rates for '/a53@0', CPU: 1250MHz at Speed Grade 'V'
SPL initial stack usage: 17104 bytes
SPL malloc() before relocation used 0x64d0 bytes (25 KB)
>>SPL: board_init_r()
spl_init
Trying to boot from DFU
g_dnl_register: g_dnl_driver.name = usb_dnl_dfu
g_dnl_bind: gadget: 0x81c44aa4 cdev: 0x81c4af40
usb_add_config: adding config #1 'usb_dnload'/81c4c040
g_dnl_do_config: configuration: 0x81c4c040 composite dev: 0x81c4af40
adding 'dfu'/81c4c0b4 to config 'usb_dnload'/81c4c040
cfg 1/81c4c040 speeds: high full
usb_add_config: interface 0 = dfu/81c4c0b4
g_dnl_bind: calling usb_gadget_connect for controller 'dwc3-gadget'
usb_dnl_dfu: ready
composite_suspend: suspend
set_config: high speed config #1: usb_dnload
non-core control reqa1.03 v0000 i0000 l6
non-core control req21.01 v0000 i0000 l4096
...(repeated)
#non-core control reqa1.03 v0000 i0000 l6
non-core control reqa1.03 v0000 i0000 l6
DOWNLOAD ... OK
Ctrl+C to exit ...
I'm not that familiar with the DW3 driver, let me know if you need me to
test with any further changes.
>
> evt was used there without being set as well.
>
> All of this is in v6 that I plan to send out. I have no AM62p and it is
> only compile tested, so please try it on your board so we know if it
> solves your issue before I send out v6.
I was able to reproduce the issue on beagleplay since it uses the same
DWC3. You can try it locally if you have that board with you by
resetting to DFU mode from U-Boot prompt:
=> mw.w 43000030 53; res
Regards,
Anshul