diff options
| author | hathach <[email protected]> | 2026-04-10 16:52:15 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-04-10 16:52:15 +0700 |
| commit | c96ff6b6d978bdcacc7cd49ad66ef00438cfb9f6 (patch) | |
| tree | 598f2488731826c2d85ff7ebe261b7dcc29dac02 | |
| parent | 8849515a0e1d1179d20a42b7b92c0e0a4d1aa131 (diff) | |
add dwc2_clock_init() to have nrf54 initial sequence. currently stub for other ports.
add board_uart_read() for nrf
| -rw-r--r-- | hw/bsp/nrf/family.c | 131 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dcd_dwc2.c | 4 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_at32.h | 6 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_bcm.h | 6 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_common.h | 16 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_efm32.h | 6 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_esp32.h | 6 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_gd32.h | 6 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_nrf.h | 52 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_stm32.h | 6 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_xmc.h | 6 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/hcd_dwc2.c | 4 |
12 files changed, 172 insertions, 77 deletions
diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 10f0fc460..31a6bac9e 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -81,39 +81,67 @@ enum { // Forward USB interrupt events to TinyUSB IRQ Handler #if defined(NRF54H20_XXAA) || defined(NRF54LM20A_ENGA_XXAA) -#define USBD_IRQn USBHS_IRQn + #define USBD_IRQn USBHS_IRQn void USBHS_IRQHandler(void) { tusb_int_handler(0, true); } -#if defined(NRF54LM20A_ENGA_XXAA) + #if defined(NRF54LM20A_ENGA_XXAA) static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(20); -#else + #else static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(120); -#endif - -#else + #endif -#ifdef NRF5340_XXAA -#define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC -#define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk -#define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk -#define GPIOTE_IRQn GPIOTE1_IRQn #else -#define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC -#define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk -#define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk -#endif + #ifdef NRF5340_XXAA + #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC + #define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk + #define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk + #define GPIOTE_IRQn GPIOTE1_IRQn + #else + #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC + #define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk + #define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk + #endif -#if CFG_TUSB_OS != OPT_OS_ZEPHYR + #if CFG_TUSB_OS != OPT_OS_ZEPHYR static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); -#endif + #endif void USBD_IRQHandler(void) { - tud_int_handler(0); + tusb_int_handler(0, true); } #endif +//--------------------------------------------------------------------+ +// UART RX ring buffer and event handler +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS != OPT_OS_ZEPHYR + +#define UART_RX_BUFSIZE 64 + +static uint8_t rx_fifo[UART_RX_BUFSIZE]; +static volatile uint16_t rx_fifo_head = 0; +static volatile uint16_t rx_fifo_tail = 0; + +static uint8_t rx_dma_buf[1]; // 1-byte DMA target for continuous RX + +static void uart_event_handler(nrfx_uarte_event_t const* p_event, void* p_context) { + (void) p_context; + if (p_event->type == NRFX_UARTE_EVT_RX_DONE) { + for (size_t i = 0; i < p_event->data.rx.length; i++) { + uint16_t next_head = (rx_fifo_head + 1) & (UART_RX_BUFSIZE - 1); + if (next_head != rx_fifo_tail) { + rx_fifo[rx_fifo_head] = p_event->data.rx.p_buffer[i]; + rx_fifo_head = next_head; + } + } + // re-arm 1-byte RX + nrfx_uarte_rx(&_uart_id, rx_dma_buf, sizeof(rx_dma_buf)); + } +} + +#endif // tinyusb function that handles power event (detected, ready, removed) // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. @@ -136,7 +164,6 @@ static nrfx_gpiote_t _gpiote = NRFX_GPIOTE_INSTANCE(0); //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ - void board_init(void) { #if !defined(NRF54H20_XXAA) && !defined(NRF54LM20A_ENGA_XXAA) // stop LF clock just in case we jump from application without reset @@ -172,12 +199,14 @@ void board_init(void) { #if CFG_TUSB_OS != OPT_OS_ZEPHYR // UART + static uint8_t uart_tx_cache[64]; nrfx_uarte_config_t uart_cfg = { .txd_pin = UART_TX_PIN, .rxd_pin = UART_RX_PIN, .rts_pin = NRF_UARTE_PSEL_DISCONNECTED, .cts_pin = NRF_UARTE_PSEL_DISCONNECTED, .p_context = NULL, + .tx_cache = { .p_buffer = uart_tx_cache, .length = sizeof(uart_tx_cache) }, .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE .interrupt_priority = 7, .config = { @@ -186,63 +215,21 @@ void board_init(void) { } }; - nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); + nrfx_uarte_init(&_uart_id, &uart_cfg, uart_event_handler); + // start continuous 1-byte RX + nrfx_uarte_rx(&_uart_id, rx_dma_buf, sizeof(rx_dma_buf)); #endif //------------- USB -------------// #if CFG_TUD_ENABLED #if defined(NRF54LM20A_ENGA_XXAA) - // Start the USB voltage regulator - NRF_VREGUSB->TASKS_START = VREGUSB_TASKS_START_TASKS_START_Trigger; - // Request HFXO crystal clock for PCLK24M (required by USBHS core) NRF_CLOCK->TASKS_XO24MSTART = CLOCK_TASKS_XO24MSTART_TASKS_XO24MSTART_Trigger; while (!NRF_CLOCK->EVENTS_XO24MSTARTED) {} NRF_CLOCK->EVENTS_XO24MSTARTED = 0; #endif -#if defined(NRF54H20_XXAA) - // Enable the USBHS wrapper (core + PHY) before any DWC2 register access - NRF_USBHS->ENABLE = (USBHS_ENABLE_PHY_Enabled << USBHS_ENABLE_PHY_Pos) | - (USBHS_ENABLE_CORE_Enabled << USBHS_ENABLE_CORE_Pos); - NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; - // Brief delay for PHY PLL lock and core power-up - for (volatile int i = 0; i < 1000; i++) {} -#endif - -#if defined(NRF54LM20A_ENGA_XXAA) - // Based on Zephyr usbhs_enable_core() in drivers/usb/udc/udc_dwc2_vendor_quirks.h - // Step 1: Power up core only (PHY not yet) - NRF_USBHS->ENABLE = USBHS_ENABLE_CORE_Msk; - - // Step 2: Override ID=Device (bit 31), and temporarily override VBUSVALID - NRF_USBHS->PHY.OVERRIDEVALUES = (USBHS_PHY_OVERRIDEVALUES_ID_Device << USBHS_PHY_OVERRIDEVALUES_ID_Pos); - NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk | USBHS_PHY_INPUTOVERRIDE_VBUSVALID_Msk; - - // Step 3: Release PHY power-on reset by enabling PHY - NRF_USBHS->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; - - // Step 4: Wait 45us for PHY clock to start - NRFX_DELAY_US(45); - - // Step 5: Release DWC2 reset - NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; - - // Step 6: Wait for clock to start to avoid hang on too early register read - NRFX_DELAY_US(2); - - // Step 7: Clear VBUSVALID override (keep ID=Device override) - // DWC2 is now in Non-Driving opmode; D+ pull-up will activate when DWC2 clears DCTL SftDiscon - NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk; - - // Barrier: USBHS wrapper (0x5005A000) and USBHSCORE (0x50020000) are separate - // peripheral blocks. Ensure the ENABLE/TASKS_START writes have propagated from - // the Cortex-M33 write buffer to hardware before anyone reads DWC2 core regs. - __DSB(); - -#endif - // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice // 2 is highest for application NVIC_SetPriority(USBD_IRQn, 2); @@ -329,11 +316,18 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { } int board_uart_read(uint8_t* buf, int len) { +#if CFG_TUSB_OS == OPT_OS_ZEPHYR (void) buf; (void) len; return -1; -// nrfx_err_t err = nrfx_uarte_rx(&_uart_id, buf, (size_t) len); -// return NRFX_SUCCESS == err ? len : 0; +#else + int count = 0; + while (count < len && rx_fifo_tail != rx_fifo_head) { + buf[count++] = rx_fifo[rx_fifo_tail]; + rx_fifo_tail = (rx_fifo_tail + 1) & (UART_RX_BUFSIZE - 1); + } + return count; +#endif } int board_uart_write(void const* buf, int len) { @@ -341,7 +335,10 @@ int board_uart_write(void const* buf, int len) { (void) buf; return len; #else - nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len ,0); + if (nrfx_uarte_tx_in_progress(&_uart_id)) { + return 0; + } + nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len, 0); return (NRFX_SUCCESS == err) ? len : 0; #endif } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index bdd3a59ed..da6ee894a 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -442,12 +442,12 @@ bool dcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { } bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_clock_init(rhport, rh_init->role); tu_memclr(&_dcd_data, sizeof(_dcd_data)); // Core Initialization + dwc2_regs_t* dwc2 = DWC2_REG(rhport); const bool is_hs_phy = dwc2_core_is_highspeed_phy(dwc2, TUD_OPT_HIGH_SPEED); const bool is_dma = dma_device_enabled(dwc2); TU_ASSERT(dwc2_core_init(rhport, is_hs_phy, is_dma)); diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 594d350b7..85fa9b20b 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -79,6 +79,12 @@ static const dwc2_controller_t _dwc2_controller[] = { #endif }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { (void) role; const IRQn_Type irqn = (IRQn_Type) _dwc2_controller[rhport].irqnum; diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index 50f3122e8..91cae821e 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -46,6 +46,12 @@ static const dwc2_controller_t _dwc2_controller[] = #define dcache_invalidate(_addr, _size) data_invalidate(_addr, _size) #define dcache_clean_invalidate(_addr, _size) data_clean_and_invalidate(_addr, _size) +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 9f28ab2e0..5c4798d21 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -38,13 +38,15 @@ #include "host/hcd.h" #endif -// Following symbols must be defined by port header -// - _dwc2_controller[]: array of controllers -// - DWC2_EP_MAX: largest EP counts of all controllers -// - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset -// - dwc2_phy_deinit(dwc2, hs_phy_type): phy deinit to disable PHY power, only deinit the phy used by core -// - dwc2_dcd_int_enable/dwc2_dcd_int_disable -// - dwc2_remote_wakeup_delay +/* Following symbols must be defined by port header + - _dwc2_controller[]: array of controllers + - DWC2_EP_MAX: largest EP counts of all controllers + - dwc2_clock_init(): clock init call before + - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset + - dwc2_phy_deinit(dwc2, hs_phy_type): phy deinit to disable PHY power, only deinit the phy used by core + - dwc2_dcd_int_enable/dwc2_dcd_int_disable + - dwc2_remote_wakeup_delay +*/ #if defined(TUP_USBIP_DWC2_STM32) #include "dwc2_stm32.h" diff --git a/src/portable/synopsys/dwc2/dwc2_efm32.h b/src/portable/synopsys/dwc2/dwc2_efm32.h index 167f5b4cd..063360873 100644 --- a/src/portable/synopsys/dwc2/dwc2_efm32.h +++ b/src/portable/synopsys/dwc2/dwc2_efm32.h @@ -43,6 +43,12 @@ static const dwc2_controller_t _dwc2_controller[] = { .reg_base = DWC2_REG_BASE, .irqnum = USB_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 512 } }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index 99ef9456f..6a10dc7f8 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -97,6 +97,12 @@ static void dwc2_int_handler_wrap(void* arg) { #endif } +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { if (enabled) { esp_intr_alloc(_dwc2_controller[rhport].irqnum, ESP_INTR_FLAG_LOWMED, diff --git a/src/portable/synopsys/dwc2/dwc2_gd32.h b/src/portable/synopsys/dwc2/dwc2_gd32.h index 396d17e30..28c3fde5e 100644 --- a/src/portable/synopsys/dwc2/dwc2_gd32.h +++ b/src/portable/synopsys/dwc2/dwc2_gd32.h @@ -57,6 +57,12 @@ static inline void __eclic_disable_interrupt (uint32_t irq){ *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 0; } +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h index fc9cd18bc..a1bf692f8 100644 --- a/src/portable/synopsys/dwc2/dwc2_nrf.h +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -29,8 +29,20 @@ #ifndef TUSB_DWC2_NRF_H #define TUSB_DWC2_NRF_H +// NRF is device only without OTG support #include "nrf.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" +#endif + +#include <soc/nrfx_coredep.h> + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #define DWC2_EP_MAX 16 // Use the auto-resolving peripheral pointer (respects TrustZone secure/non-secure mapping) @@ -44,6 +56,46 @@ static const dwc2_controller_t _dwc2_controller[] = { {.reg_base = DWC2_REG_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .otg_dfifo_depth = 3072}, }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; + + #if defined(NRF54LM20A_ENGA_XXAA) + // Start the USB voltage regulator + NRF_VREGUSB->TASKS_START = VREGUSB_TASKS_START_TASKS_START_Trigger; + + // Based on Zephyr usbhs_enable_core() in drivers/usb/udc/udc_dwc2_vendor_quirks.h + // Step 1: Power up core only (PHY not yet) + NRF_USBHS->ENABLE = USBHS_ENABLE_CORE_Msk; + + // Step 2: Override ID=Device (bit 31), and temporarily override VBUSVALID + NRF_USBHS->PHY.OVERRIDEVALUES = (USBHS_PHY_OVERRIDEVALUES_ID_Device << USBHS_PHY_OVERRIDEVALUES_ID_Pos); + NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk | USBHS_PHY_INPUTOVERRIDE_VBUSVALID_Msk; + + // Step 3: Release PHY power-on reset by enabling PHY + NRF_USBHS->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; + + // Step 4: Wait 45us for PHY clock to start + nrfx_coredep_delay_us(45); + + // Step 5: Release DWC2 reset + NRF_USBHS->TASKS_START = USBHS_TASKS_START_TASKS_START_Trigger; + + // Step 6: Wait for clock to start to avoid hang on too early register read + nrfx_coredep_delay_us(2); + + // Step 7: Clear VBUSVALID override (keep ID=Device override) + // DWC2 is now in Non-Driving opmode; D+ pull-up will activate when DWC2 clears DCTL SftDiscon + NRF_USBHS->PHY.INPUTOVERRIDE = USBHS_PHY_INPUTOVERRIDE_ID_Msk; + + // Barrier: USBHS wrapper (0x5005A000) and USBHSCORE (0x50020000) are separate + // peripheral blocks. Ensure the ENABLE/TASKS_START writes have propagated from + // the Cortex-M33 write buffer to hardware before anyone reads DWC2 core regs. + __DSB(); + #endif +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { (void)rhport; (void)role; diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 5f6e98224..e5379dfe3 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -162,6 +162,12 @@ static const dwc2_controller_t _dwc2_controller[] = { // SystemCoreClock is already included by family header // extern uint32_t SystemCoreClock; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { (void) role; const IRQn_Type irqn = (IRQn_Type) _dwc2_controller[rhport].irqnum; diff --git a/src/portable/synopsys/dwc2/dwc2_xmc.h b/src/portable/synopsys/dwc2/dwc2_xmc.h index b946444ee..85b2a2633 100644 --- a/src/portable/synopsys/dwc2/dwc2_xmc.h +++ b/src/portable/synopsys/dwc2/dwc2_xmc.h @@ -42,6 +42,12 @@ static const dwc2_controller_t _dwc2_controller[] = { .reg_base = USB0_BASE, .irqnum = USB0_0_IRQn, .ep_count = DWC2_EP_MAX, .otg_dfifo_depth = 512 } }; +// MCU specific to enable dwc2 clock/power before any access to register +TU_ATTR_ALWAYS_INLINE static inline void dwc2_clock_init(uint8_t rhport, tusb_role_t role) { + (void) rhport; + (void) role; +} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index cd2ddf572..6098d6eaa 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -407,10 +407,12 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { // Initialize controller to host mode bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_clock_init(rhport, rh_init->role); + tu_memclr(&_hcd_data, sizeof(_hcd_data)); // Core Initialization + dwc2_regs_t* dwc2 = DWC2_REG(rhport); const bool is_hs_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy); const bool is_dma = dma_host_enabled(dwc2); TU_ASSERT(dwc2_core_init(rhport, is_hs_phy, is_dma)); |
