summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-02-23 19:33:29 +0700
committerhathach <[email protected]>2026-02-23 21:08:06 +0700
commitf179b2957dbe00ad937eb50ada42dc32233a7a93 (patch)
tree9fa7865ed224ad8658dbfd405ebdd930217127e4 /src
parent1eef6f4f4f7a26a5be3c4b774992aadcc8660820 (diff)
refactor: streamline high-speed PHY detection and configuration in DWC2 driver
Diffstat (limited to 'src')
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c2
-rw-r--r--src/portable/synopsys/dwc2/dwc2_common.c35
-rw-r--r--src/portable/synopsys/dwc2/dwc2_common.h1
-rw-r--r--src/portable/synopsys/dwc2/hcd_dwc2.c27
4 files changed, 29 insertions, 36 deletions
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index d1d4b080e..2e2b050bc 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -479,7 +479,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
#ifdef TUP_USBIP_DWC2_STM32
dwc2_stm32_gccfg_cfg(dwc2, _tud_cfg.vbus_sensing, false);
-#endif
+ #endif
// Enable required interrupts
dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c
index 98ef22d03..27dda44ee 100644
--- a/src/portable/synopsys/dwc2/dwc2_common.c
+++ b/src/portable/synopsys/dwc2/dwc2_common.c
@@ -60,6 +60,7 @@ static void reset_core(dwc2_regs_t* dwc2) {
while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {} // wait for AHB master IDLE
}
+// Dedicated FS PHY is internal with a clock 48Mhz.
static void phy_fs_init(dwc2_regs_t* dwc2) {
TU_LOG(DWC2_COMMON_DEBUG, "Fullspeed PHY init\r\n");
@@ -86,6 +87,13 @@ static void phy_fs_init(dwc2_regs_t* dwc2) {
dwc2_phy_update(dwc2, GHWCFG2_HSPHY_NOT_SUPPORTED);
}
+/* dwc2 has 2 highspeed PHYs options
+ * - UTMI+ is internal highspeed PHY, can be clocked at 30/60 Mhz for fullspeed or 60 Mhz for highspeed. Can be either
+ * 8 or 16-bit interface.
+ * - ULPI is external highspeed PHY, clocked at 60Mhz with 8-bit interface.
+ *
+ * In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz
+ */
static void phy_hs_init(dwc2_regs_t* dwc2) {
uint32_t gusbcfg = dwc2->gusbcfg;
const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
@@ -180,29 +188,18 @@ static bool check_dwc2(dwc2_regs_t* dwc2) {
//
//--------------------------------------------------------------------
bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy) {
-#ifdef TUP_USBIP_DWC2_STM32
- if (dwc2->guid >= 0x5000) {
- // femtoPHY UTMI+ PHY
- return true;
- }
-#endif
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ const bool has_hs_phy = (ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED);
- if (!prefer_hs_phy) {
- return false;
+ if (prefer_hs_phy) {
+ return has_hs_phy;
+ } else {
+ const bool has_fs_phy = (ghwcfg2.fs_phy_type != GHWCFG2_FSPHY_NOT_SUPPORTED);
+ // false if has fs phy, otherwise true since hs phy is the only available phy
+ return !has_fs_phy && has_hs_phy;
}
-
- const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
- return ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED;
}
-/* dwc2 has several PHYs option
- * - UTMI+ is internal highspeed PHY, clock can be 30 Mhz (8-bit) or 60 Mhz (16-bit)
- * - ULPI is external highspeed PHY, clock is 60Mhz with only 8-bit interface
- * - Dedicated FS PHY is internal with clock 48Mhz.
- *
- * In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz
- *
-*/
bool dwc2_core_init(uint8_t rhport, bool is_hs_phy, bool is_dma) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h
index 6ee351ab5..1947173b2 100644
--- a/src/portable/synopsys/dwc2/dwc2_common.h
+++ b/src/portable/synopsys/dwc2/dwc2_common.h
@@ -84,6 +84,7 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) {
return (dwc2_regs_t*)_dwc2_controller[rhport].reg_base;
}
+// check if highspeed phy should be used
bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy);
bool dwc2_core_init(uint8_t rhport, bool is_hs_phy, bool is_dma);
void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr);
diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c
index cc11c82d7..0fd60b35d 100644
--- a/src/portable/synopsys/dwc2/hcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/hcd_dwc2.c
@@ -351,7 +351,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t pa
* TX periodic (PTX)
* - At least largest-EPsize*MulCount/4 (MulCount up to 3 for high-bandwidth ISO/interrupt)
*/
-static void dfifo_host_init(uint8_t rhport, bool is_highspeed) {
+static void dfifo_host_init(uint8_t rhport, bool is_hs_phy) {
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
@@ -365,8 +365,8 @@ static void dfifo_host_init(uint8_t rhport, bool is_highspeed) {
// fixed allocation for now, improve later:
// - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total
- uint32_t nptx_largest = is_highspeed ? TUSB_EPSIZE_BULK_HS / 4 : TUSB_EPSIZE_BULK_FS / 4;
- uint32_t ptx_largest = is_highspeed ? TUSB_EPSIZE_ISO_HS_MAX / 4 : 256 / 4;
+ uint32_t nptx_largest = is_hs_phy ? TUSB_EPSIZE_BULK_HS / 4 : TUSB_EPSIZE_BULK_FS / 4;
+ uint32_t ptx_largest = is_hs_phy ? TUSB_EPSIZE_ISO_HS_MAX / 4 : 256 / 4;
uint16_t nptxfsiz = 2 * nptx_largest;
uint16_t rxfsiz = 2 * (ptx_largest + 2) + ghwcfg2.num_host_ch;
@@ -416,30 +416,25 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
// force host mode and wait for mode switch
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FDMOD) | GUSBCFG_FHMOD;
-#if CFG_TUSB_MCU == OPT_MCU_STM32N6
+ #if CFG_TUSB_MCU == OPT_MCU_STM32N6
// No hardware detection of Vbus B-session is available on the STM32N6
dwc2->stm32_gccfg &= ~STM32_GCCFG_VBVALOVAL;
-#endif
+ #endif
+
while ((dwc2->gintsts & GINTSTS_CMOD) != GINTSTS_CMODE_HOST) {}
#ifdef TUP_USBIP_DWC2_STM32
dwc2_stm32_gccfg_cfg(dwc2, false, true);
#endif
- bool is_highspeed;
- if (!TUH_OPT_HIGH_SPEED || rh_init->speed < TUSB_SPEED_HIGH) {
- dwc2->hcfg |= HCFG_FSLS_ONLY; // disable high speed mode
- is_highspeed = false;
- }
- #if TUH_OPT_HIGH_SPEED
- else {
- dwc2->hcfg &= ~HCFG_FSLS_ONLY; // work at max supported speed
- is_highspeed = true;
+ if (is_hs_phy && (rh_init->speed == TUSB_SPEED_HIGH || rh_init->speed == TUSB_SPEED_AUTO)) {
+ dwc2->hcfg &= ~HCFG_FSLS_ONLY; // max speed
+ } else {
+ dwc2->hcfg |= HCFG_FSLS_ONLY; // disable high speed mode
}
- #endif
// configure a fixed-allocated fifo scheme
- dfifo_host_init(rhport, is_highspeed);
+ dfifo_host_init(rhport, is_hs_phy);
dwc2->hprt = HPRT_W1_MASK; // clear all write-1-clear bits
dwc2->hprt = HPRT_POWER; // turn on VBUS