Skip to content

Supports full-speed host with an high-speed PHY (DWC2)#3494

Closed
ceedriic wants to merge 1 commit intohathach:masterfrom
Precidata:fs-host-with-hs-phy-v2
Closed

Supports full-speed host with an high-speed PHY (DWC2)#3494
ceedriic wants to merge 1 commit intohathach:masterfrom
Precidata:fs-host-with-hs-phy-v2

Conversation

@ceedriic
Copy link
Contributor

Describe the PR
This patch allows configuring a Full-Speed USB host with DWC2 on a board wired with a High-Speed ULPI PHY

Additional context
This implements #3450 proof-of-concept in a proper way (I hope).

It introduces an optional CFG_TUH_PHY_SPEED configuration option, which specify the PHY configuration and can be different (higher than) CFG_TUH_MAX_SPEED

For example, this works on a stm32h747 board with external ULPI:

#define CFG_TUH_MAX_SPEED		OPT_MODE_FULL_SPEED
#define CFG_TUH_PHY_SPEED		OPT_MODE_HIGH_SPEED

The effect of this configuration is to set the HCFG_FSLS_ONLY bit on the DWC2 controller at the right place.

@ceedriic ceedriic changed the title Supports full-speed host with on high-speed PHY (DWC2) Supports full-speed host with an high-speed PHY (DWC2) Feb 11, 2026
@HiFiPhile
Copy link
Collaborator

HiFiPhile commented Feb 11, 2026

I think it's better to add a forced speed tuh_configure dynamic config.

bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);

} tuh_configure_param_t;

You need to leave dwc2_core_is_highspeed unchanged otherwise it will try to initialize internal FS phy instead of ULPI in dwc2_core_init

@ceedriic
Copy link
Contributor Author

I think it's better to add a forced speed tuh_configure dynamic config.

bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);

Ok, I would prefer a dynamic config too.

But I tried to do it the other way around. The problem with

  1. speed = high
  2. forced_speed = full

Is that all buffers sizes will be based on "high speed" settings (big)

Or do we need something like PR #3487 for the host side too?

I was trying to tackle the problem with:

  1. speed = full
  2. phy_speed = high

To have the stack settings based on full speed.

} tuh_configure_param_t;

You need to leave dwc2_core_is_highspeed unchanged otherwise it will try to initialize internal FS phy instead of ULPI in dwc2_core_init

I think you misread the patch: the new CFG_TUH_PHY_SPEED is the "hardware" speed, so dwc2_core_is_highspeed() need to use that.

I've tested the 3 following configs:

  1. HS PHY, HS speed (ULPI)
  2. HS PHY, FS speed (ULPI)
  3. FS PHY, FS speed (internal)

and it all works.

@HiFiPhile
Copy link
Collaborator

The problem with
speed = high
forced_speed = full
Is that all buffers sizes will be based on "high speed" settings (big)

You mean which buffer, FIFO in dfifo_host_init ?

@github-actions
Copy link

Size Difference Report

Because TinyUSB code size varies by port and configuration, the metrics below represent the averaged totals across all example builds.

Note: If there is no change, only one value is shown.

Changes >1% in size

file .text .rodata .bss size % diff
hcd_dwc2.c 4893 ➙ 4950 (+57) 30 512 5434 ➙ 5491 (+57) +1.0%
TOTAL 4893 ➙ 4950 (+57) 30 512 5434 ➙ 5491 (+57) +1.0%

Changes <1% in size

No entries.

No changes
file .text .rodata .data .bss size % diff
audio_device.c 2849 0 1248 1673 4518 +0.0%
cdc_device.c 1328 16 19 661 1988 +0.0%
cdc_host.c 6596 487 15 1539 8357 +0.0%
dcd_ch32_usbfs.c 1472 0 0 2444 3916 +0.0%
dcd_ch32_usbhs.c 1648 0 0 448 2096 +0.0%
dcd_ci_fs.c 1925 0 0 1290 3215 +0.0%
dcd_ci_hs.c 1762 0 0 1280 2530 +0.0%
dcd_da146xx.c 3067 0 0 144 3211 +0.0%
dcd_dwc2.c 4101 24 0 263 4387 +0.0%
dcd_eptri.c 2270 0 0 259 2529 +0.0%
dcd_khci.c 1953 0 0 1290 3243 +0.0%
dcd_lpc17_40.c 1470 0 0 648 1794 +0.0%
dcd_lpc_ip3511.c 1463 0 0 264 1639 +0.0%
dcd_mm32f327x_otg.c 1478 0 0 1290 2768 +0.0%
dcd_msp430x5xx.c 1796 0 0 176 1972 +0.0%
dcd_musb.c 2446 0 0 160 2606 +0.0%
dcd_nrf5x.c 2919 0 0 292 3211 +0.0%
dcd_nuc120.c 1093 0 0 78 1171 +0.0%
dcd_nuc121.c 1167 0 0 101 1268 +0.0%
dcd_nuc505.c 0 0 1529 157 1686 +0.0%
dcd_rp2040.c 859 20 604 655 2138 +0.0%
dcd_rusb2.c 2917 0 0 156 3073 +0.0%
dcd_samd.c 1032 0 0 266 1298 +0.0%
dcd_samg.c 1319 0 0 72 1391 +0.0%
dcd_stm32_fsdev.c 2557 0 0 291 2848 +0.0%
dfu_device.c 744 28 712 183 926 +0.0%
dfu_rt_device.c 156 0 134 0 156 +0.0%
dwc2_common.c 582 29 0 0 597 +0.0%
ecm_rndis_device.c 1037 0 1 2272 3310 +0.0%
ehci.c 2761 0 0 5970 7537 +0.0%
fsdev_common.c 180 0 0 0 180 +0.0%
hcd_ch32_usbfs.c 2484 0 0 498 2982 +0.0%
hcd_ci_hs.c 190 0 0 0 190 +0.0%
hcd_khci.c 2442 0 0 449 2891 +0.0%
hcd_musb.c 3073 0 0 157 3230 +0.0%
hcd_pio_usb.c 262 0 240 0 502 +0.0%
hcd_rp2040.c 976 73 416 384 1849 +0.0%
hcd_rusb2.c 2923 0 0 245 3168 +0.0%
hcd_samd.c 2220 0 0 324 2544 +0.0%
hcd_stm32_fsdev.c 3282 0 1 420 3703 +0.0%
hid_device.c 1118 44 997 115 1233 +0.0%
hid_host.c 1206 0 0 1250 2456 +0.0%
hub.c 1235 8 8 29 1268 +0.0%
midi_device.c 1127 0 991 589 1714 +0.0%
midi_host.c 1353 7 7 3740 5097 +0.0%
msc_device.c 2503 108 2274 538 3041 +0.0%
msc_host.c 1589 0 0 394 1984 +0.0%
mtp_device.c 1689 22 1449 579 2275 +0.0%
ncm_device.c 1514 28 1408 5830 7358 +0.0%
ohci.c 1942 0 0 2414 4356 +0.0%
rp2040_usb.c 172 75 718 4 969 +0.0%
rusb2_common.c 160 0 16 0 176 +0.0%
tusb.c 429 0 368 3 430 +0.0%
tusb_fifo.c 843 0 477 0 838 +0.0%
typec_stm32.c 820 8 2 12 842 +0.0%
usbc.c 420 2 20 166 608 +0.0%
usbd.c 3190 57 89 276 3531 +0.0%
usbd_control.c 523 0 474 78 600 +0.0%
usbh.c 4395 60 63 954 5436 +0.0%
usbtmc_device.c 2176 24 69 291 2500 +0.0%
vendor_device.c 624 0 530 464 1087 +0.0%
video_device.c 4391 5 1851 472 4855 +0.0%
TOTAL 108218 1125 16730 44997 155272 +0.0%

#endif
while ((dwc2->gintsts & GINTSTS_CMOD) != GINTSTS_CMODE_HOST) {}

if (hprt_speed_get(dwc2) != TUSB_SPEED_HIGH) {
Copy link
Owner

Choose a reason for hiding this comment

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

hmm, what if there is no device connected, it would be full speed ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, yeah, I don't remember why exactly I used that function here. I will look for a better way.

hcfg |= HCFG_FSLS_PHYCLK_SEL_30_60MHZ;
}

if (speed != TUSB_SPEED_HIGH) {
Copy link
Owner

@hathach hathach Feb 12, 2026

Choose a reason for hiding this comment

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

manual say we don't change this bit after intiial programming

Image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I was trying to keep it the same, but I'm not sure what I was thinking when I wrote part of that patch. I will redo that patch from scratch.

@hathach
Copy link
Owner

hathach commented Feb 12, 2026

We should use tuh_configure() to force the phy selection e.g CFG_TUH_MAX_SPEED = FULL, but tuh_configure(use_hs_phy=1). The function dwc2_core_is_highspeed() should be rename to dwc2_core_is_highspeed_phy() and return true if we force phy selection. HCFG_FSLS_ONLY should only be set ONCE in init per manual since I think it involves HS PLL phy on/off.

@ceedriic
Copy link
Contributor Author

The problem with
speed = high
forced_speed = full
Is that all buffers sizes will be based on "high speed" settings (big)

You mean which buffer, FIFO in dfifo_host_init ?

No, you're right, I made a mistake.

I was thinking about code like:

#define CFG_TUD_NET_ENDPOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)

But I now see that this only in the device side, and not in the host side.

@ceedriic
Copy link
Contributor Author

We should use tuh_configure() to force the phy selection e.g CFG_TUH_MAX_SPEED = FULL, but tuh_configure(use_hs_phy=1). The function dwc2_core_is_highspeed() should be rename to dwc2_core_is_highspeed_phy() and return true if we force phy selection. HCFG_FSLS_ONLY should only be set ONCE in init per manual since I think it involves HS PLL phy on/off.

Ok, that makes a lot of sense, time for a v3 patch

@ceedriic
Copy link
Contributor Author

Bye Bye, welcome #3506

@ceedriic ceedriic closed this Feb 19, 2026
@ceedriic ceedriic deleted the fs-host-with-hs-phy-v2 branch February 23, 2026 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants