Skip to content

Conversation

@josuah
Copy link
Contributor

@josuah josuah commented Sep 9, 2025

Dependencies:

Goals:

  • Keep nRF54LM20 working (see test method below) through the whole process.
  • Integrate more content from #94266 until this PR becomes only additions, no deletion/modifications
  • Propose the modifications back to #94266 when they are required.

Non-goals:

  • Improve #94266: propositions for improving this PR are to be done on a separate PR

To test:

west build -b nrf54lm20dk/nrf54lm20a/cpuapp samples/subsys/usb/shell/ -DEXTRA_CONF_FILE=host_prj.conf
west flash
# connect/disconnect a device from the USB port and observe IRQs being triggered

For now I am testing with externally provided power supply using an USB OTG adapter with external power supply.

@josuah
Copy link
Contributor Author

josuah commented Sep 9, 2025

So far, only getting the IRQs upon connection/disconnection are working, and almost none of the content of uhc_dwc2.c is present.

@josuah josuah added the DNM This PR should not be merged (Do Not Merge) label Sep 9, 2025
@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch 3 times, most recently from c6292fb to c7b19bc Compare September 9, 2025 13:11
@josuah
Copy link
Contributor Author

josuah commented Sep 9, 2025

This PR is now having all the content of # in addition to the nRF54LM20, and it will now be possible to progressively review what is present, to keep only what makes sense and what follows the databook/programmer manual.

uart:~$ usbh init 
host: USB host initialized
[00:00:04.193,752] <inf> uhc_dwc2: Skip pinctrl configuration
uart:~$ usbh enable 
host: USB host enabled
[00:00:06.338,259] <dbg> uhc_dwc2: dwc2_hal_load_config: GSNPSID=4F54500Bh, GHWCFG1=00000000h, GHWCFG2=22AFFC52h, GHWCFG3=0BE0C0E8h, GHWCFG4=3E10AA60h
[00:00:06.338,274] <dbg> uhc_dwc2: uhc_dwc2_init_controller: DWC2 Core parameters
[00:00:06.338,280] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 	FIFO:
[00:00:06.338,287] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 		Depth 3040
[00:00:06.338,303] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 		Dedicated: YES
[00:00:06.338,325] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 		Dynamic sizing: YES
[00:00:06.338,332] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 	Number of channels: 16
[00:00:06.338,338] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 	HS PHY type: 0x00000001
[00:00:06.338,345] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 	FS PHY type: 0x00000000
[00:00:06.338,358] <dbg> uhc_dwc2: uhc_dwc2_init_controller: 	DMA supported: YES
[00:00:06.338,368] <wrn> uhc_dwc2: HS PHY config not implemented yet
[00:00:06.338,375] <dbg> uhc_dwc2: uhc_dwc2_config_fifo_fixed_dma: Configuring FIFO sizes
[00:00:06.338,382] <dbg> uhc_dwc2: uhc_dwc2_config_fifo_fixed_dma: FIFO sizes calculated
[00:00:06.338,389] <dbg> uhc_dwc2: uhc_dwc2_config_fifo_fixed_dma: 	top=12096, nptx=128, rx=592, ptx=11376
[00:00:06.363,491] <wrn> uhc_dwc2: Experimental DMA enabled
[00:00:06.363,504] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Dynamic FIFO Sizing is enabled
[00:00:06.363,511] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Number of endpoints (NUMDEVEPS + 1) 16
[00:00:06.363,518] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Number of IN endpoints (INEPS + 1) 16
[00:00:06.363,524] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Number of periodic IN endpoints (NUMDEVPERIOEPS) 0
[00:00:06.363,531] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Number of additional control endpoints (NUMCTLEPS) 0
[00:00:06.363,538] <dbg> uhc_dwc2: uhc_dwc2_init_controller: OTG architecture (OTGARCH) 2, mode (OTGMODE) 2
[00:00:06.363,545] <dbg> uhc_dwc2: uhc_dwc2_init_controller: DFIFO depth (DFIFODEPTH) 12160 bytes
[00:00:06.363,552] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Max packet count 1023, Max transfer size 524287
[00:00:06.363,573] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Vendor Control interface support enabled: false
[00:00:06.363,585] <dbg> uhc_dwc2: uhc_dwc2_init_controller: PHY interface type: FSPHYTYPE 0, HSPHYTYPE 1, DATAWIDTH 2
[00:00:06.363,597] <dbg> uhc_dwc2: uhc_dwc2_init_controller: LPM mode is enabled
[00:00:06.363,606] <dbg> uhc_dwc2: uhc_dwc2_init_controller: Number of OUT endpoints 0
[00:00:06.363,669] <dbg> uhc_dwc2: uhc_dwc2_enable: Enable device 0x50020000
[00:00:06.364,184] <dbg> uhc_dwc2: uhc_dwc2_decode_intr: GINTSTS=04001026h, HPRT=00000000h
uart:~$ 

It is not yet possible to enumerate devices:

uart:~$ usbh device list
uart:~$ 

But connection/disconnection events are still detected:

uart:~$ 
[00:02:31.191,897] <dbg> uhc_dwc2: uhc_dwc2_decode_intr: GINTSTS=04801024h, HPRT=00000000h
[00:02:32.360,993] <dbg> uhc_dwc2: uhc_dwc2_decode_intr: GINTSTS=04002024h, HPRT=00000000h
[00:02:32.367,113] <dbg> uhc_dwc2: uhc_dwc2_decode_intr: GINTSTS=04008C24h, HPRT=00000000h
uart:~$ 

@roma-jam
Copy link

roma-jam commented Sep 9, 2025

Hi @josuah,
oh, good to see that it works somehow for you.

But please, wait for a moment, I will remove the LL-layer completely and make everything udc_dwc2-alike soon.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Sep 9, 2025

@josuah
Copy link
Contributor Author

josuah commented Sep 9, 2025

But please, wait for a moment, I will remove the LL-layer completely and make everything udc_dwc2-alike soon.

No problem. I am now pursuing with the host class API.
Thanks for chiming in and for the DWC2 implementation!

@roma-jam
Copy link

Hi @josuah,

I have removed the LL-layer, so please, feel free to rebase.

Also, I can see that the log is from uhc and then in the end - the udc: uhc_dwc2_enable: Enable device 0x50020000.

Just in case - is that intentional? Because I didn't check the possibility to run udc after uhc, so there could be some moments, that need to be fixed.

@josuah
Copy link
Contributor Author

josuah commented Sep 11, 2025

Thanks! I will do this soon.

uhc_dwc2_enable: Enable device 0x50020000 is just leftover from code imported to initialize DWC2 from the nRF54LM20.

https://github.com/zephyrproject-rtos/zephyr/pull/95723/files#diff-a5c1ac2b1e9f1d28cb96d97ecee24e3b15ab543cf1f0d4cfbe650471bae2c02aR2546

No problem with you refactoring in the meantime, please feel free to keep doing so.

@josuah
Copy link
Contributor Author

josuah commented Nov 6, 2025

Some script showing the difference in hardware configuration registers of ESP32-S3 and nRF54LM20.

dwc2_decode_regs.py

output
GHWCFG1 (ESP32): 0x00000000
 EpDir:32 = 0
32 bits

GHWCFG1 (nRF54): 0x00000000
 EpDir:32 = 0
32 bits

GHWCFG2 (ESP32): 0x224dd930
 OtgMode:3 = 0
 OtgArch:2 = 2
 SingPnt:1 = 1
 HsPhyType:2 = 0
 FsPhyType:2 = 1
 NumDevEps:4 = 6
 NumHstChnl:4 = 7
 PerioSupport:1 = 1
 DynFifoSizing:1 = 1
 MultiProcIntrpt:1 = 0
 Reserved:1 = 0
 NPTxQDepth:2 = 1
 PTxQDepth:2 = 2
 TknQDepth:5 = 8
 OTG_ENABLE_IC_USB:1 = 0
32 bits

GHWCFG2 (nRF54): 0x22affc52
 OtgMode:3 = 2
 OtgArch:2 = 2
 SingPnt:1 = 0
 HsPhyType:2 = 1
 FsPhyType:2 = 0
 NumDevEps:4 = 15
 NumHstChnl:4 = 15
 PerioSupport:1 = 1
 DynFifoSizing:1 = 1
 MultiProcIntrpt:1 = 0
 Reserved:1 = 1
 NPTxQDepth:2 = 2
 PTxQDepth:2 = 2
 TknQDepth:5 = 8
 OTG_ENABLE_IC_USB:1 = 0
32 bits

GHWCFG3 (ESP32): 0x00c804b5
 XferSizeWidth:4 = 5
 PktSizeWidth:3 = 3
 OtgEn:1 = 1
 I2CIntSel:1 = 0
 VndctlSupt:1 = 0
 OptFeature:1 = 1
 RstType:1 = 0
 ADPSupport:1 = 0
 HSICMode:1 = 0
 BCSupport:1 = 0
 LPMMode:1 = 0
 DfifoDepth:16 = 200
32 bits

GHWCFG3 (nRF54): 0x0be0c0e8
 XferSizeWidth:4 = 8
 PktSizeWidth:3 = 6
 OtgEn:1 = 1
 I2CIntSel:1 = 0
 VndctlSupt:1 = 0
 OptFeature:1 = 0
 RstType:1 = 0
 ADPSupport:1 = 0
 HSICMode:1 = 0
 BCSupport:1 = 1
 LPMMode:1 = 1
 DfifoDepth:16 = 3040
32 bits

GHWCFG4 (ESP32): 0xd3f0a030
 NumDevPerioEps:4 = 0
 PartialPwrDn:1 = 1
 AhbFreq:1 = 1
 Hibernation:1 = 0
 ExtendedHibernation:1 = 0
 Reserved_8:1 = 0
 EnhancedLPMSupt1:1 = 0
 ServIntFlow:1 = 0
 ipgisocSupt:1 = 0
 ACGSupt:1 = 0
 EnhancedLPMSupt:1 = 1
 PhyDataWidth:2 = 2
 NumCtlEps:4 = 0
 IddgFltr:1 = 1
 VBusValidFltr:1 = 1
 AValidFltr:1 = 1
 BValidFltr:1 = 1
 SessEndFltr:1 = 1
 DedFifoMode:1 = 1
 INEps:4 = 4
 DescDMAEnabled:1 = 1
 DescDMA:1 = 1
32 bits

GHWCFG4 (nRF54): 0x3e10aa60
 NumDevPerioEps:4 = 0
 PartialPwrDn:1 = 0
 AhbFreq:1 = 1
 Hibernation:1 = 1
 ExtendedHibernation:1 = 0
 Reserved_8:1 = 0
 EnhancedLPMSupt1:1 = 1
 ServIntFlow:1 = 0
 ipgisocSupt:1 = 1
 ACGSupt:1 = 0
 EnhancedLPMSupt:1 = 1
 PhyDataWidth:2 = 2
 NumCtlEps:4 = 0
 IddgFltr:1 = 1
 VBusValidFltr:1 = 0
 AValidFltr:1 = 0
 BValidFltr:1 = 0
 SessEndFltr:1 = 0
 DedFifoMode:1 = 1
 INEps:4 = 15
 DescDMAEnabled:1 = 0
 DescDMA:1 = 0
32 bits

GOTGCTL (ESP32): 0x00240000
 SesReqScs:1 = 0
 SesReq:1 = 0
 VBValidOvEn:1 = 0
 VBValidOvVal:1 = 0
 AValidOvEn:1 = 0
 AValidOvVal:1 = 0
 BValidOvEn:1 = 0
 BValidOvVal:1 = 0
 HstNegScs:1 = 0
 HnpReq:1 = 0
 HstSetHnpEn:1 = 0
 DevHnpEn:1 = 0
 EhEn:1 = 0
 RSVD:2 = 0
 DbnceFltrBypass:1 = 0
 ConIdSts:1 = 0
 DbncTime:1 = 0
 ASesVld:1 = 1
 BSesVld:1 = 0
 OtgVer:1 = 0
 CurMod:1 = 1
 MultValidBc:5 = 0
 ChirpEn:1 = 0
 eUSB2_Phy_Disc_Supp:1 = 0
 Reserved_30_29:2 = 0
 TestMode_Corr_eUSB2:1 = 0
32 bits

GOTGCTL (nRF54): 0x03050070
 SesReqScs:1 = 0
 SesReq:1 = 0
 VBValidOvEn:1 = 0
 VBValidOvVal:1 = 0
 AValidOvEn:1 = 1
 AValidOvVal:1 = 1
 BValidOvEn:1 = 1
 BValidOvVal:1 = 0
 HstNegScs:1 = 0
 HnpReq:1 = 0
 HstSetHnpEn:1 = 0
 DevHnpEn:1 = 0
 EhEn:1 = 0
 RSVD:2 = 0
 DbnceFltrBypass:1 = 0
 ConIdSts:1 = 1
 DbncTime:1 = 0
 ASesVld:1 = 1
 BSesVld:1 = 0
 OtgVer:1 = 0
 CurMod:1 = 0
 MultValidBc:5 = 12
 ChirpEn:1 = 0
 eUSB2_Phy_Disc_Supp:1 = 0
 Reserved_30_29:2 = 0
 TestMode_Corr_eUSB2:1 = 0
32 bits

HCFG (nRF54): 0x00220000
 FSLSPclkSel:2 = 0
 FSLSSupp:1 = 0
 RESERVED2:4 = 0
 Ena32KHzS:1 = 0
 ResValid:8 = 0
 dis_tx_ipgap_dly_check:1 = 0
 RESERVED1:6 = 17
 DescDMA:1 = 0
 FrListEn:2 = 0
 PerSchedEna:1 = 0
 RESERVED:4 = 0
 ModeChTimEn:1 = 0
32 bits

HCFG (ESP32): 0x00100000
 FSLSPclkSel:2 = 0
 FSLSSupp:1 = 0
 RESERVED2:4 = 0
 Ena32KHzS:1 = 0
 ResValid:8 = 0
 dis_tx_ipgap_dly_check:1 = 0
 RESERVED1:6 = 8
 DescDMA:1 = 0
 FrListEn:2 = 0
 PerSchedEna:1 = 0
 RESERVED:4 = 0
 ModeChTimEn:1 = 0
32 bits

HFIR (nRF54): 0x000017d7
 FrInt:16 = 6103
 HFIRRldCtrl:1 = 0
 RESERVED:17 = 0
34 bits

HFIR (ESP32): 0x000017d7
 FrInt:16 = 6103
 HFIRRldCtrl:1 = 0
 RESERVED:17 = 0
34 bits

@github-actions
Copy link

github-actions bot commented Nov 6, 2025

The following west manifest projects have changed revision in this Pull Request:

Name Old Revision New Revision Diff
hal_espressif zephyrproject-rtos/hal_espressif@af6cfa2 zephyrproject-rtos/hal_espressif@b90f0ea (main) zephyrproject-rtos/[email protected]

All manifest checks OK

Note: This message is automatically posted and updated by the Manifest GitHub Action.

@github-actions github-actions bot added manifest manifest-hal_espressif DNM (manifest) This PR should not be merged (controlled by action-manifest) labels Nov 6, 2025
@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch from 8e1b61a to 89c6af5 Compare November 7, 2025 13:06
@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch 5 times, most recently from aa033fb to 85e6c06 Compare November 10, 2025 12:17
struct uhc_dwc2_data *priv = uhc_get_private(dev);
enum uhc_port_event port_event = UHC_PORT_EVENT_NONE;

/* TODO: enter critial section */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better to keep the TODOs regarding the critical section, as it is important.

Copy link
Contributor Author

@josuah josuah Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to reduce everything to the minimal and might have trimmed important pieces accidentally.
The hope is that it's easier to add them back after the conversion rather than keep them while trying as hard to know what was historical baggage from the ESP32 export, or an optimization encountered in a different platform, or needed part of the operation etc. Thanks for helping seeing clear!

Regarding the critical section, I wonder:

  • If we are in IRQs, it is not possible to lock IRQs or have blocking calls anyway
  • If we are not in the IRQs, we are in the main thread or in an API call, and there is a global lock already.

Is there extra locking required in addition to this?

@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch 2 times, most recently from b518cfd to 939baa9 Compare November 11, 2025 15:50
@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch 3 times, most recently from ee1cead to cc5a2a9 Compare November 13, 2025 00:07
@josuah
Copy link
Contributor Author

josuah commented Nov 13, 2025

commit 2a120d0

Everything above contains ~100 bissectable mini-commits that slowly transform the original work passed from hand to hand into a hopefully more minimal and workable following a single coding/naming style and uniform structure (git diff --stat 830c8b5ce71 says 1005 insertions(+), 1922 deletions(-)).

Hopefully all the logic was retained.

Test scripts:

test_esp32.sh:

n='
'
set -eux

west build -d build_esp32s3 -b esp32s3_devkitm/esp32s3/procpu samples/subsys/usb/shell/ \
 -DEXTRA_CONF_FILE=host_prj.conf \
 -DCONFIG_USB_DEVICE_STACK_NEXT=n \
 -DCONFIG_UHC_DRIVER_LOG_LEVEL_DBG=y \
 -DCONFIG_ASSERT=y \

west flash -d build_esp32s3 --esp-device "$1"

sleep 1
picocom --quiet --initstring "usbh init$n""usbh enable$n" --baud 115200 "$1"

test_nrf54lm20.sh:

n='
'
set -eux

west build -d build_nrf54lm20 -b nrf54lm20dk/nrf54lm20a/cpuapp samples/subsys/usb/shell/ \
 -DEXTRA_CONF_FILE=host_prj.conf \
 -DCONFIG_USB_DEVICE_STACK_NEXT=n \
 -DCONFIG_UHC_DRIVER_LOG_LEVEL_DBG=y \
 -DCONFIG_ASSERT=y \

west flash -d build_nrf54lm20

sleep 1
picocom --quiet --initstring "usbh init$n""usbh enable$n" --baud 115200 "$1"

I will now squash everything and modify the driver to make it pass CI, then edit coding style a bit.

@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch 6 times, most recently from 80cda8f to 8c3e2a3 Compare November 16, 2025 13:14
@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch 2 times, most recently from e5bc28d to 859825e Compare November 22, 2025 18:55
A new linting tool got introduced, and prior to submit new contributions
to .dtsi files, files need to be made compliant.

Signed-off-by: Josuah Demangeon <[email protected]>
@github-actions github-actions bot removed manifest manifest-hal_espressif DNM (manifest) This PR should not be merged (controlled by action-manifest) labels Nov 22, 2025
Josuah Demangeon and others added 3 commits November 22, 2025 19:22
Update the HAL to latest main version for support of USB Host Controller
uhc_dwc2.c, needed for the vendor quirsk.

Signed-off-by: Josuah Demangeon <[email protected]>
Add board support files needed to test the ESP32-S3 devkit
with host support, as well as host_prj.conf used to test the
USB shell with host support exclusively.

Example build command:

  west build -b esp32s3_devkitm/esp32s3/procpu samples/subsys/usb/shell/ \
   -DEXTRA_CONF_FILE=host_prj.conf -DCONFIG_USB_DEVICE_STACK_NEXT=n

Signed-off-by: Roman Leonov <[email protected]>
Added register bitmask description with low-level abstraction

Signed-off-by: Roman Leonov <[email protected]>
Introduce an USB host driver for Synopsys Designware USB OTG controller
(DWC2) with vendor quirks for nRF54LM20 and ESP32-S3, using the
nRF54LM20-DK and ESP32-S3 DevitC. Both need VBUS supplied with an
external +5V to power the USB device.

The driver currently only support control commands on the control endpoint
which is enough for the enumeration process.

Signed-off-by: Roman Leonov <[email protected]>
Co-authored-by: Josuah Demangeon <[email protected]>
@josuah josuah force-pushed the feature/usb_dwc2_host_support_nrf54lm20 branch from dd5d9a1 to 6d38acb Compare November 23, 2025 18:06
@sonarqubecloud
Copy link

@josuah
Copy link
Contributor Author

josuah commented Nov 23, 2025

@roma-jam it should be stable enough that it can be picked as a basis if you want, but if you notice that things are missing let me know. I don't really identify what came from the original driver and what you introduced on top.

@roma-jam
Copy link

@josuah wow, I briefly check the changes....looks more Zephyr-style :)

I also briefly checked the most critical parts and seems that that logic was kept (at least from the first glance).
I'll try to check it on a hardware asap. finish with other tasks and get back to this one.

@roma-jam
Copy link

Hi @josuah,

seems that I can return to this sooner than I expected.

I can't say what a great part of the job you did with refactoring...Honestly, I'm impressed.

Ok, back to the topic: would you mind if I cherry-pick your commits with refactoring to my branch and:

  • verify one more time the logic and check it on a hardware
  • proceed with the rest TODOs

@josuah
Copy link
Contributor Author

josuah commented Nov 27, 2025

Thank you.

Ok, back to the topic: would you mind if I cherry-pick your commits with refactoring to my branch and:

Please go ahead, this was the original intent of this PR: to let everyone working on DWC2 host keep going on a common ground.

  • verify one more time the logic and check it on a hardware

I observe there is some problem while starting Zephyr and USB init/enable first, and plugging the USB device after.

I can use the "bisectable commits" above to check which small change broke something if that helps.

  • proceed with the rest TODOs

I will have to switch to another project soon, hopefully this helps getting this branch stable as you start using it.

I will keep this one as draft just for adding the nRF54LM20 and will rebase it on top of your changes as you publish them.

@roma-jam
Copy link

@josuah ,

I observe there is some problem while starting Zephyr and USB init/enable first, and plugging the USB device after.

I remember I already had the same problem two times during the past time and both times I solved it.
I will take a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DNM This PR should not be merged (Do Not Merge) manifest manifest-hal_espressif

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants