diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index a4d57597..c840db89 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -125,7 +125,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_RP2040 #include "pico.h" -#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG || CFG_TUSB_MCU == OPT_MCU_EFM32GG11 || CFG_TUSB_MCU == OPT_MCU_EFM32GG12 +#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG #include "em_device.h" #elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X diff --git a/hw/bsp/sltb009a/board.mk b/hw/bsp/sltb009a/board.mk index e8a24d1b..7a046b34 100644 --- a/hw/bsp/sltb009a/board.mk +++ b/hw/bsp/sltb009a/board.mk @@ -8,7 +8,7 @@ CFLAGS += \ -D__STARTUP_CLEAR_BSS \ -D__START=main \ -DEFM32GG12B810F1024GM64 \ - -DCFG_TUSB_MCU=OPT_MCU_EFM32GG12 + -DCFG_TUSB_MCU=OPT_MCU_EFM32GG # mcu driver cause following warnings #CFLAGS += -Wno-error=unused-parameter @@ -24,7 +24,7 @@ LD_FILE = $(SILABS_CMSIS)/Source/GCC/$(SILABS_FAMILY).ld SRC_C += \ $(SILABS_CMSIS)/Source/system_$(SILABS_FAMILY).c \ - src/portable/silabs/efm32/dcd_efm32.c + src/portable/synopsys/dwc2/dcd_dwc2.c SRC_S += \ $(SILABS_CMSIS)/Source/GCC/startup_$(SILABS_FAMILY).S diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index 31f27fa3..82d4957e 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -36,6 +36,11 @@ void OTG_FS_IRQHandler(void) tud_int_handler(0); } +void OTG_HS_IRQHandler(void) +{ + tud_int_handler(1); +} + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ @@ -134,6 +139,8 @@ void board_init(void) // Enable USB OTG clock __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); +// __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + board_vbus_sense_init(); } diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/board.mk b/hw/bsp/stm32h7/boards/stm32h743eval/board.mk index 96d14a79..b768a0ee 100644 --- a/hw/bsp/stm32h7/boards/stm32h743eval/board.mk +++ b/hw/bsp/stm32h7/boards/stm32h743eval/board.mk @@ -2,6 +2,7 @@ CFLAGS += -DSTM32H743xx -DHSE_VALUE=25000000 # Default is Highspeed port PORT ?= 1 +SPEED ?= high SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32h743xx.s LD_FILE = $(BOARD_PATH)/stm32h743xx_flash.ld diff --git a/hw/bsp/stm32h7/family.mk b/hw/bsp/stm32h7/family.mk index 6a257e22..096d04d0 100644 --- a/hw/bsp/stm32h7/family.mk +++ b/hw/bsp/stm32h7/family.mk @@ -19,16 +19,22 @@ CFLAGS += \ -DBOARD_DEVICE_RHPORT_NUM=$(PORT) ifeq ($(PORT), 1) - CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED - $(info "PORT1 High Speed") + ifeq ($(SPEED), high) + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_HIGH_SPEED + $(info "Using OTG_HS in HighSpeed mode") + else + CFLAGS += -DBOARD_DEVICE_RHPORT_SPEED=OPT_MODE_FULL_SPEED + $(info "Using OTG_HS in FullSpeed mode") + endif else - $(info "PORT0 Full Speed") + $(info "Using OTG_FS") endif # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align # All source paths should be relative to the top level. + SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 90f3a526..70854f9c 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -169,7 +169,7 @@ #define DCD_ATTR_ENDPOINT_MAX 16 //------------- Silabs -------------// -#elif TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_EFM32GG11, OPT_MCU_EFM32GG12) +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) #define DCD_ATTR_ENDPOINT_MAX 7 //------------- Renesas -------------// diff --git a/src/host/hcd_attr.h b/src/host/hcd_attr.h index a9bc242d..06011c63 100644 --- a/src/host/hcd_attr.h +++ b/src/host/hcd_attr.h @@ -82,7 +82,7 @@ #elif TU_CHECK_MCU(OPT_MCU_RP2040) //------------- Silabs -------------// -#elif TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_EFM32GG11, OPT_MCU_EFM32GG12) +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) //------------- Renesas -------------// #elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index aad7e45c..16780cba 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -31,7 +31,9 @@ #include "device/dcd_attr.h" #if TUSB_OPT_DEVICE_ENABLED && \ - ( defined(DCD_ATTR_DWC2_STM32) || TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_GD32VF103, OPT_MCU_BCM2711) ) + ( defined(DCD_ATTR_DWC2_STM32) || \ + TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_GD32VF103) || \ + TU_CHECK_MCU(OPT_MCU_EFM32GG, OPT_MCU_BCM2711) ) #include "device/dcd.h" #include "dwc2_type.h" @@ -44,6 +46,8 @@ #include "dwc2_gd32.h" #elif TU_CHECK_MCU(OPT_MCU_BCM2711) #include "dwc2_bcm.h" +#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) + #include "dwc2_efm32.h" #else #error "Unsupported MCUs" #endif @@ -260,6 +264,9 @@ void print_dwc2_info(dwc2_regs_t * dwc2) dwc2_ghwcfg3_t const * hw_cfg3 = &dwc2->ghwcfg3_bm; dwc2_ghwcfg4_t const * hw_cfg4 = &dwc2->ghwcfg4_bm; + TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl); + TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); + TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg); TU_LOG_HEX(DWC2_DEBUG, dwc2->guid); TU_LOG_HEX(DWC2_DEBUG, dwc2->gsnpsid); TU_LOG_HEX(DWC2_DEBUG, dwc2->ghwcfg1); @@ -349,23 +356,22 @@ static void phy_fs_init(dwc2_regs_t * dwc2) // Select FS PHY dwc2->gusbcfg |= GUSBCFG_PHYSEL; + // MCU specific PHY init before reset + dwc2_phy_init(dwc2, HS_PHY_TYPE_NONE); + // Reset core after selecting PHY reset_core(dwc2); - // set turn around // USB turnaround time is critical for certification where long cables and 5-Hubs are used. // So if you need the AHB to run at less than 30 MHz, and if USB turnaround time is not critical, - // these bits can be programmed to a larger value. - //TU_LOG_INT(DWC2_DEBUG, (dwc2->gusbcfg & GUSBCFG_TRDT_Msk) >> GUSBCFG_TRDT_Pos ); - dwc2_phyfs_set_turnaround(dwc2); + // these bits can be programmed to a larger value. Default is 5 + dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (5u << GUSBCFG_TRDT_Pos); + + // MCU specific PHY update post reset + dwc2_phy_update(dwc2, HS_PHY_TYPE_NONE); // set max speed dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_FS << DCFG_DSPD_Pos); - - #if defined(DCD_ATTR_DWC2_STM32) - // activate FS PHY on stm32 - dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN; - #endif } static void phy_hs_init(dwc2_regs_t * dwc2) @@ -399,19 +405,13 @@ static void phy_hs_init(dwc2_regs_t * dwc2) // Set 16-bit interface if supported if (dwc2->ghwcfg4_bm.utmi_phy_data_width) gusbcfg |= GUSBCFG_PHYIF16; - - #if defined(DCD_ATTR_DWC2_STM32) && defined(USB_HS_PHYC) - dwc2_stm32_utmi_phy_init(dwc2); - #endif } // Apply config dwc2->gusbcfg = gusbcfg; - #if defined(DCD_ATTR_DWC2_STM32) - // Disable STM32 FS PHY - dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; - #endif + // mcu specific phy init + dwc2_phy_init(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); // Reset core after selecting PHY reset_core(dwc2); @@ -421,7 +421,10 @@ static void phy_hs_init(dwc2_regs_t * dwc2) // - 5 if using 16-bit PHY interface gusbcfg &= ~GUSBCFG_TRDT_Msk; gusbcfg |= (dwc2->ghwcfg4_bm.utmi_phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; - dwc2->gusbcfg = gusbcfg; // Apply config + dwc2->gusbcfg = gusbcfg; + + // MCU specific PHY update post reset + dwc2_phy_update(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); // Set max speed dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_HS << DCFG_DSPD_Pos); @@ -429,16 +432,16 @@ static void phy_hs_init(dwc2_regs_t * dwc2) static bool check_dwc2(dwc2_regs_t * dwc2) { +#if CFG_TUSB_DEBUG >= DWC2_DEBUG + print_dwc2_info(dwc2); +#endif + // For some reasons: GD32VF103 snpsid and all hwcfg register are always zero (skip it) #if !TU_CHECK_MCU(OPT_MCU_GD32VF103) uint32_t const gsnpsid = dwc2->gsnpsid & GSNPSID_ID_MASK; TU_ASSERT(gsnpsid == DWC2_OTG_ID || gsnpsid == DWC2_FS_IOT_ID || gsnpsid == DWC2_HS_IOT_ID); #endif -#if CFG_TUSB_DEBUG >= DWC2_DEBUG - print_dwc2_info(dwc2); -#endif - return true; } @@ -451,8 +454,10 @@ void dcd_init (uint8_t rhport) // Check Synopsys ID register, failed if controller clock/power is not enabled TU_VERIFY(check_dwc2(dwc2), ); - // Force device mode - dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; + dcd_disconnect(rhport); + + // max number of endpoints & total_fifo_size are: + // hw_cfg2->num_dev_ep, hw_cfg2->total_fifo_size if( phy_hs_supported(dwc2) ) { @@ -464,7 +469,11 @@ void dcd_init (uint8_t rhport) phy_fs_init(dwc2); } - TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); + // Restart PHY clock + dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE); + + // Force device mode + dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; /* Set HS/FS Timeout Calibration to 7 (max available value). * The number of PHY clocks that the application programs in @@ -476,27 +485,34 @@ void dcd_init (uint8_t rhport) */ dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos); - // Restart PHY clock - dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE); - - // Clear all interrupts - dwc2->gintsts |= dwc2->gintsts; - - // Required as part of core initialization. - // TODO: How should mode mismatch be handled? It will cause - // the core to stop working/require reset. - dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_MMISM; - // If USB host misbehaves during status portion of control xfer // (non zero-length packet), send STALL back and discard. dwc2->dcfg |= DCFG_NZLSOHSK; - dwc2->gintmsk |= GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_USBSUSPM | - GINTMSK_WUIM | GINTMSK_RXFLVLM; + // Clear A,B, VBus valid override + dwc2->gotgctl &= ~(GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | GOTGCTL_VBVALOEN); + + // Clear all interrupts + dwc2->gintsts |= dwc2->gintsts; + dwc2->gotgint |= dwc2->gotgint; + + // Required as part of core initialization. + // TODO: How should mode mismatch be handled? It will cause + // the core to stop working/require reset. + dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_MMISM | GINTMSK_RXFLVLM | + GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; // Enable global interrupt dwc2->gahbcfg |= GAHBCFG_GINT; + // make sure we are in device mode +// TU_ASSERT(!(dwc2->gintsts & GINTSTS_CMOD), ); + +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg); +// TU_LOG_HEX(DWC2_DEBUG, dwc2->gahbcfg); + dcd_connect(rhport); } @@ -1096,6 +1112,8 @@ void dcd_int_handler(uint8_t rhport) uint32_t const int_status = dwc2->gintsts & dwc2->gintmsk; +// TU_LOG_HEX(DWC2_DEBUG, int_status); + if(int_status & GINTSTS_USBRST) { // USBRST is start of reset. diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index c064946c..38d10930 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -51,17 +51,28 @@ static inline void dwc2_dcd_int_disable (uint8_t rhport) BP_DisableIRQ(USB_IRQn); } -TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms // TODO implement later } -static inline void dwc2_phyfs_set_turnaround(dwc2_regs_t * dwc2) +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { (void) dwc2; - // do nothing since bcm alwyas use HS PHY + (void) hs_phy_type; + + // nothing to do +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do } #ifdef __cplusplus diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index af5d5f09..78da277d 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -50,12 +50,14 @@ static void dcd_int_handler_wrap(void* arg) dcd_int_handler(0); } +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable (uint8_t rhport) { (void) rhport; esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, dcd_int_handler_wrap, NULL, &usb_ih); } +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable (uint8_t rhport) { (void) rhport; @@ -67,10 +69,22 @@ static inline void dwc2_remote_wakeup_delay(void) vTaskDelay(pdMS_TO_TICKS(1)); } -static inline void dwc2_phyfs_set_turnaround(dwc2_regs_t * dwc2) +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { (void) dwc2; - // keep the reset value which is 5 on this port + (void) hs_phy_type; + + // nothing to do +} + +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do } #ifdef __cplusplus diff --git a/src/portable/synopsys/dwc2/dwc2_gd32.h b/src/portable/synopsys/dwc2/dwc2_gd32.h index 15e73ad1..f8fa01ee 100644 --- a/src/portable/synopsys/dwc2/dwc2_gd32.h +++ b/src/portable/synopsys/dwc2/dwc2_gd32.h @@ -68,7 +68,6 @@ static inline void dwc2_dcd_int_disable (uint8_t rhport) __eclic_disable_interrupt(RHPORT_IRQn); } -TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms @@ -76,12 +75,23 @@ static inline void dwc2_remote_wakeup_delay(void) while ( count-- ) __asm volatile ("nop"); } -static inline void dwc2_phyfs_set_turnaround(dwc2_regs_t * dwc2) +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { - // use recommeded value 6 by stm32 for mcu with AHB clock > 32Mhz - dwc2->gusbcfg = (dwc2->gusbcfg & GUSBCFG_TRDT_Msk) | (6u << GUSBCFG_TRDT_Pos); + (void) dwc2; + (void) hs_phy_type; + + // nothing to do } +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + (void) dwc2; + (void) hs_phy_type; + + // nothing to do +} #ifdef __cplusplus } diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 4d0ed3f0..469045ac 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -112,78 +112,91 @@ static inline void dwc2_remote_wakeup_delay(void) while ( count-- ) __NOP(); } -// Set turn-around timeout according to link speed -static inline void dwc2_phyfs_set_turnaround(dwc2_regs_t * dwc2) +// MCU specific PHY init, called BEFORE core reset +static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) { - // Turnaround timeout depends on the AHB clock dictated by STM32 Reference Manual - uint32_t turnaround; - - if ( SystemCoreClock >= 32000000U ) - turnaround = 0x6u; - else if ( SystemCoreClock >= 27500000U ) - turnaround = 0x7u; - else if ( SystemCoreClock >= 24000000U ) - turnaround = 0x8u; - else if ( SystemCoreClock >= 21800000U ) - turnaround = 0x9u; - else if ( SystemCoreClock >= 20000000U ) - turnaround = 0xAu; - else if ( SystemCoreClock >= 18500000U ) - turnaround = 0xBu; - else if ( SystemCoreClock >= 17200000U ) - turnaround = 0xCu; - else if ( SystemCoreClock >= 16000000U ) - turnaround = 0xDu; - else if ( SystemCoreClock >= 15000000U ) - turnaround = 0xEu; - else - turnaround = 0xFu; - - dwc2->gusbcfg = (dwc2->gusbcfg & GUSBCFG_TRDT_Msk) | (turnaround << GUSBCFG_TRDT_Pos); -} - -#if defined(USB_HS_PHYC) -static inline void dwc2_stm32_utmi_phy_init(dwc2_regs_t * dwc2) -{ - USB_HS_PHYC_GlobalTypeDef *usb_hs_phyc = (USB_HS_PHYC_GlobalTypeDef*) USB_HS_PHYC_CONTROLLER_BASE; - - // Enable UTMI HS PHY - dwc2->stm32_gccfg |= STM32_GCCFG_PHYHSEN; - - // Enable LDO - usb_hs_phyc->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; - - // Wait until LDO ready - while ( 0 == (usb_hs_phyc->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {} - - uint32_t phyc_pll = 0; - - // TODO Try to get HSE_VALUE from registers instead of depending CFLAGS - switch ( HSE_VALUE ) + if ( hs_phy_type == HS_PHY_TYPE_NONE ) { - case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break; - case 12500000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ ; break; - case 16000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ ; break; - case 24000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ ; break; - case 25000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ ; break; - case 32000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk ; break; // Value not defined in header - default: - TU_ASSERT(false, ); + // Enable on-chip FS PHY + dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN; + }else + { + // Disable FS PHY + dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; + + // Enable on-chip HS PHY + if (hs_phy_type == HS_PHY_TYPE_UTMI || hs_phy_type == HS_PHY_TYPE_UTMI_ULPI) + { +#ifdef USB_HS_PHYC + // Enable UTMI HS PHY + dwc2->stm32_gccfg |= STM32_GCCFG_PHYHSEN; + + // Enable LDO + USB_HS_PHYC->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE; + + // Wait until LDO ready + while ( 0 == (USB_HS_PHYC->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) ) {} + + uint32_t phyc_pll = 0; + + // TODO Try to get HSE_VALUE from registers instead of depending CFLAGS + switch ( HSE_VALUE ) + { + case 12000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12MHZ ; break; + case 12500000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_12_5MHZ ; break; + case 16000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_16MHZ ; break; + case 24000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_24MHZ ; break; + case 25000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_25MHZ ; break; + case 32000000: phyc_pll = USB_HS_PHYC_PLL1_PLLSEL_Msk ; break; // Value not defined in header + default: + TU_ASSERT(false, ); + } + USB_HS_PHYC->USB_HS_PHYC_PLL = phyc_pll; + + // Control the tuning interface of the High Speed PHY + // Use magic value (USB_HS_PHYC_TUNE_VALUE) from ST driver for F7 + USB_HS_PHYC->USB_HS_PHYC_TUNE |= 0x00000F13U; + + // Enable PLL internal PHY + USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; +#endif + } } - usb_hs_phyc->USB_HS_PHYC_PLL = phyc_pll; - - // Control the tuning interface of the High Speed PHY - // Use magic value (USB_HS_PHYC_TUNE_VALUE) from ST driver - usb_hs_phyc->USB_HS_PHYC_TUNE |= 0x00000F13U; - - // Enable PLL internal PHY - usb_hs_phyc->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; - - // Original ST code has 2 ms delay for PLL stabilization. - // Primitive test shows that more than 10 USB un/replug cycle showed no error with enumeration } -#endif +// MCU specific PHY update, it is called AFTER init() and core reset +static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) +{ + // used to set turnaround time for fullspeed, nothing to do in highspeed mode + if ( hs_phy_type == HS_PHY_TYPE_NONE ) + { + // Turnaround timeout depends on the AHB clock dictated by STM32 Reference Manual + uint32_t turnaround; + + if ( SystemCoreClock >= 32000000u ) + turnaround = 0x6u; + else if ( SystemCoreClock >= 27500000u ) + turnaround = 0x7u; + else if ( SystemCoreClock >= 24000000u ) + turnaround = 0x8u; + else if ( SystemCoreClock >= 21800000u ) + turnaround = 0x9u; + else if ( SystemCoreClock >= 20000000u ) + turnaround = 0xAu; + else if ( SystemCoreClock >= 18500000u ) + turnaround = 0xBu; + else if ( SystemCoreClock >= 17200000u ) + turnaround = 0xCu; + else if ( SystemCoreClock >= 16000000u ) + turnaround = 0xDu; + else if ( SystemCoreClock >= 15000000u ) + turnaround = 0xEu; + else + turnaround = 0xFu; + + dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (turnaround << GUSBCFG_TRDT_Pos); + } +} #ifdef __cplusplus } diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 7b3db4dd..583a7274 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -528,7 +528,7 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define GUSBCFG_PHYSEL_Pos (6U) #define GUSBCFG_PHYSEL_Msk (0x1UL << GUSBCFG_PHYSEL_Pos) // 0x00000040 */ #define GUSBCFG_PHYSEL GUSBCFG_PHYSEL_Msk // USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */ -#define GUSBCFG_DDRSEL TU_BIT(7) // Single Data Rate (SDR) or Double Data Rate (DDR) or ULPI interface. +#define GUSBCFG_DDRSEL TU_BIT(7) // Single Data Rate (SDR) or Double Data Rate (DDR) or ULPI interface. #define GUSBCFG_SRPCAP_Pos (8U) #define GUSBCFG_SRPCAP_Msk (0x1UL << GUSBCFG_SRPCAP_Pos) // 0x00000100 */ #define GUSBCFG_SRPCAP GUSBCFG_SRPCAP_Msk // SRP-capable */ diff --git a/src/tusb_option.h b/src/tusb_option.h index de0279dd..4da07e24 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -113,8 +113,6 @@ // Silabs #define OPT_MCU_EFM32GG 1300 ///< Silabs EFM32GG -#define OPT_MCU_EFM32GG11 1301 ///< Silabs EFM32GG11 -#define OPT_MCU_EFM32GG12 1302 ///< Silabs EFM32GG12 // Renesas RX #define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631