From 1711ed88aae656b4c440d27400239f5833392e5b Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Thu, 28 Aug 2025 13:42:12 +0200 Subject: [PATCH] feat(usb/host): Add USB Host support to ESP32-P4 v3 --- .../hal/esp32p4/include/hal/usb_dwc_ll.h | 29 ++- .../hal/esp32s2/include/hal/usb_dwc_ll.h | 8 +- .../hal/esp32s3/include/hal/usb_dwc_ll.h | 8 +- components/hal/usb_dwc_hal.c | 9 +- .../soc/esp32p4/include/soc/usb_dwc_struct.h | 12 +- .../hw_ver1}/soc/usb_dwc_cfg.h | 0 .../register/hw_ver3/soc/usb_dwc_cfg.h | 181 ++++++++++++++++++ 7 files changed, 222 insertions(+), 25 deletions(-) rename components/soc/esp32p4/{include => register/hw_ver1}/soc/usb_dwc_cfg.h (100%) create mode 100644 components/soc/esp32p4/register/hw_ver3/soc/usb_dwc_cfg.h diff --git a/components/hal/esp32p4/include/hal/usb_dwc_ll.h b/components/hal/esp32p4/include/hal/usb_dwc_ll.h index 6760db5637..4d7748e394 100644 --- a/components/hal/esp32p4/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32p4/include/hal/usb_dwc_ll.h @@ -28,7 +28,8 @@ extern "C" { ----------------------------------------------------------------------------- */ #define USB_DWC_QTD_LIST_MEM_ALIGN 512 -#define USB_DWC_FRAME_LIST_MEM_ALIGN 512 // The frame list needs to be 512 bytes aligned (contrary to the databook) +#define USB_DWC_FRAME_LIST_MEM_ALIGN 512 // The frame list needs to be 512 bytes aligned (contrary to the databook) +#define USB_DWC_CORE_REG_GSNPSID_4_20a 0x4F54420A // From 4.20a upward, the reset sequence is changed /* ----------------------------------------------------------------------------- ------------------------------- Global Registers ------------------------------- @@ -279,12 +280,28 @@ static inline void usb_dwc_ll_grstctl_reset_frame_counter(usb_dwc_dev_t *hw) static inline void usb_dwc_ll_grstctl_core_soft_reset(usb_dwc_dev_t *hw) { - hw->grstctl_reg.csftrst = 1; -} + const uint32_t gnspsid = hw->gsnpsid_reg.val; -static inline bool usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(usb_dwc_dev_t *hw) -{ - return hw->grstctl_reg.csftrst; + // Start core soft reset + hw->grstctl_reg.csftrst = 1; + + // Wait for the reset to complete + if (gnspsid < USB_DWC_CORE_REG_GSNPSID_4_20a) { + // Version < 4.20a + while (hw->grstctl_reg.csftrst) { + ; + } + } else { + // Version >= 4.20a + while (!(hw->grstctl_reg.csftrstdone)) { + ; + } + usb_dwc_grstctl_reg_t grstctl; + grstctl.val = hw->grstctl_reg.val; + grstctl.csftrst = 0; // Clear RESET bit once reset is done + grstctl.csftrstdone = 1; // Write 1 to clear RESET_DONE bit + hw->grstctl_reg.val = grstctl.val; + } } // --------------------------- GINTSTS Register -------------------------------- diff --git a/components/hal/esp32s2/include/hal/usb_dwc_ll.h b/components/hal/esp32s2/include/hal/usb_dwc_ll.h index 27859e5ef7..d3eef71367 100644 --- a/components/hal/esp32s2/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32s2/include/hal/usb_dwc_ll.h @@ -274,11 +274,9 @@ static inline void usb_dwc_ll_grstctl_reset_frame_counter(usb_dwc_dev_t *hw) static inline void usb_dwc_ll_grstctl_core_soft_reset(usb_dwc_dev_t *hw) { hw->grstctl_reg.csftrst = 1; -} - -static inline bool usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(usb_dwc_dev_t *hw) -{ - return hw->grstctl_reg.csftrst; + while (hw->grstctl_reg.csftrst) { + ; + } } // --------------------------- GINTSTS Register -------------------------------- diff --git a/components/hal/esp32s3/include/hal/usb_dwc_ll.h b/components/hal/esp32s3/include/hal/usb_dwc_ll.h index fc5edff0bd..32f7469a3e 100644 --- a/components/hal/esp32s3/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32s3/include/hal/usb_dwc_ll.h @@ -274,11 +274,9 @@ static inline void usb_dwc_ll_grstctl_reset_frame_counter(usb_dwc_dev_t *hw) static inline void usb_dwc_ll_grstctl_core_soft_reset(usb_dwc_dev_t *hw) { hw->grstctl_reg.csftrst = 1; -} - -static inline bool usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(usb_dwc_dev_t *hw) -{ - return hw->grstctl_reg.csftrst; + while (hw->grstctl_reg.csftrst) { + ; + } } // --------------------------- GINTSTS Register -------------------------------- diff --git a/components/hal/usb_dwc_hal.c b/components/hal/usb_dwc_hal.c index bf0fb93258..fa46d8228c 100644 --- a/components/hal/usb_dwc_hal.c +++ b/components/hal/usb_dwc_hal.c @@ -23,7 +23,9 @@ #define BENDPOINTADDRESS_NUM_MSK 0x0F //Endpoint number mask of the bEndpointAddress field of an endpoint descriptor #define BENDPOINTADDRESS_DIR_MSK 0x80 //Endpoint direction mask of the bEndpointAddress field of an endpoint descriptor -#define CORE_REG_GSNPSID 0x4F54400A //Release number of USB_DWC used in Espressif's SoCs +// Core register IDs supported by this driver: v4.00a and v4.30a +#define CORE_REG_GSNPSID_4_00a 0x4F54400A +#define CORE_REG_GSNPSID_4_30a 0x4F54430A // -------------------- Configurable ----------------------- @@ -131,7 +133,7 @@ void usb_dwc_hal_init(usb_dwc_hal_context_t *hal, int port_id) HAL_ASSERT(port_id < SOC_USB_OTG_PERIPH_NUM); usb_dwc_dev_t *dev = USB_DWC_LL_GET_HW(port_id); uint32_t core_id = usb_dwc_ll_gsnpsid_get_id(dev); - HAL_ASSERT(core_id == CORE_REG_GSNPSID); + HAL_ASSERT(core_id == CORE_REG_GSNPSID_4_00a || core_id == CORE_REG_GSNPSID_4_30a); (void) core_id; //Suppress unused variable warning if asserts are disabled // Initialize HAL context @@ -163,9 +165,6 @@ void usb_dwc_hal_deinit(usb_dwc_hal_context_t *hal) void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal) { usb_dwc_ll_grstctl_core_soft_reset(hal->dev); - while (usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(hal->dev)) { - ; // Wait until core reset is done - } while (!usb_dwc_ll_grstctl_is_ahb_idle(hal->dev)) { ; // Wait until AHB Master bus is idle before doing any other operations } diff --git a/components/soc/esp32p4/include/soc/usb_dwc_struct.h b/components/soc/esp32p4/include/soc/usb_dwc_struct.h index f07575c52a..1848978546 100644 --- a/components/soc/esp32p4/include/soc/usb_dwc_struct.h +++ b/components/soc/esp32p4/include/soc/usb_dwc_struct.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,10 +14,13 @@ extern "C" { /* Registers and fields were generated based on a set of USB-DWC configuration options. -ESP32-P4 contains 2 instances of USB-DWC with different configurations, the structure below corresponds to the HS instance. -The FS instance contains a subset of registers from HS instance, the user (HAL) is responsible for accessing only existing fields. +ESP32-P4 contains 2 instances of USB-DWC with different configurations and versions, the structure below corresponds to the High Speed v4.30a instance. +The Full Speed instance contains a subset of registers from High Speed instance, the user (HAL) is responsible for accessing only existing fields. See ESP32-P4 "usb_dwc_cfg.h" for more details. + +List of changes v4.00a -> v4.30a +- GRSTCTL register now contains the CSftRstDone bit which indicates the completion of a soft reset. */ /* ---------------------------- Register Types ------------------------------ */ @@ -129,7 +132,8 @@ typedef union { uint32_t rxfflsh: 1; uint32_t txfflsh: 1; uint32_t txfnum: 5; - uint32_t reserved_11: 19; + uint32_t reserved_11: 18; + uint32_t csftrstdone: 1; uint32_t dmareq: 1; uint32_t ahbidle: 1; }; diff --git a/components/soc/esp32p4/include/soc/usb_dwc_cfg.h b/components/soc/esp32p4/register/hw_ver1/soc/usb_dwc_cfg.h similarity index 100% rename from components/soc/esp32p4/include/soc/usb_dwc_cfg.h rename to components/soc/esp32p4/register/hw_ver1/soc/usb_dwc_cfg.h diff --git a/components/soc/esp32p4/register/hw_ver3/soc/usb_dwc_cfg.h b/components/soc/esp32p4/register/hw_ver3/soc/usb_dwc_cfg.h new file mode 100644 index 0000000000..788e538823 --- /dev/null +++ b/components/soc/esp32p4/register/hw_ver3/soc/usb_dwc_cfg.h @@ -0,0 +1,181 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* +HS Instance: +Configuration Set ID: 11 +*/ + +/* 3.1 Basic Config Parameters */ +#define OTG20_MODE 0 +#define OTG20_ARCHITECTURE 2 +#define OTG20_SINGLE_POINT 1 +#define OTG20_ENABLE_LPM 0 +#define OTG20_EN_DED_TX_FIFO 1 +#define OTG20_EN_DESC_DMA 1 +#define OTG20_MULTI_PROC_INTRPT 1 + +/* 3.2 USB Physical Layer Interface Parameters */ +#define OTG20_HSPHY_INTERFACE 3 // Although we support both UTMI+ and ULPI, the ULPI is not wired out of the USB-DWC. Hence only UTMI+ can be used +#define OTG20_HSPHY_DWIDTH 2 +#define OTG20_FSPHY_INTERFACE 2 +#define OTG20_ENABLE_IC_USB 0 +#define OTG20_ENABLE_HSIC 0 +#define OTG20_I2C_INTERFACE 0 +#define OTG20_ULPI_CARKIT 1 +#define OTG20_ADP_SUPPORT 1 +#define OTG20_BC_SUPPORT 0 +#define OTG20_VENDOR_CTL_INTERFACE 1 + +/* 3.3 Device Endpoint Configuration Parameters */ +#define OTG20_NUM_EPS 15 +#define OTG20_NUM_IN_EPS 8 +#define OTG20_NUM_CRL_EPS 1 + +/* 3.4 Host Endpoint Configuration Parameters */ +#define OTG20_NUM_HOST_CHAN 16 +#define OTG20_EN_PERIO_HOST 1 + +/* 3.5 Endpoint Channel FIFO Configuration Parameters */ +#define OTG20_DFIFO_DEPTH 1024 +#define OTG20_DFIFO_DYNAMIC 1 +#define OTG20_RX_DFIFO_DEPTH 1024 +#define OTG20_TX_HNPERIO_DFIFO_DEPTH 1024 +#define OTG20_TX_HPERIO_DFIFO_DEPTH 1024 +#define OTG20_NPERIO_TX_QUEUE_DEPTH 8 +#define OTG20_PERIO_TX_QUEUE_DEPTH 16 + +/* 3.6 Additional Configuration Options Parameters */ +#define OTG20_TRANS_COUNT_WIDTH 17 +#define OTG20_PACKET_COUNT_WIDTH 8 +#define OTG20_RM_OPT_FEATURES 1 +#define OTG20_EN_PWROPT 1 +#define OTG20_SYNC_RESET_TYPE 0 +#define OTG20_EN_IDDIG_FILTER 1 +#define OTG20_EN_VBUSVALID_FILTER 1 +#define OTG20_EN_A_VALID_FILTER 1 +#define OTG20_EN_B_VALID_FILTER 1 +#define OTG20_EN_SESSIONEND_FILTER 1 +#define OTG20_EXCP_CNTL_XFER_FLOW 1 +#define OTG20_PWR_CLAMP 0 +#define OTG20_PWR_SWITCH_POLARITY 0 + +/* 3.7 Endpoint Direction Parameters */ +#define OTG20_EP_DIR_1 0 +#define OTG20_EP_DIR_2 0 +#define OTG20_EP_DIR_3 0 +#define OTG20_EP_DIR_4 0 +#define OTG20_EP_DIR_5 0 +#define OTG20_EP_DIR_6 0 +#define OTG20_EP_DIR_7 0 +#define OTG20_EP_DIR_8 0 +#define OTG20_EP_DIR_9 0 +#define OTG20_EP_DIR_10 0 +#define OTG20_EP_DIR_11 0 +#define OTG20_EP_DIR_12 0 +#define OTG20_EP_DIR_13 0 +#define OTG20_EP_DIR_14 0 +#define OTG20_EP_DIR_15 0 + +/* 3.8 Device Periodic FIFO Depth Parameters */ + +/* 3.9 Device IN Endpoint FIFO Depth Parameters */ +#define OTG20_TX_DINEP_DFIFO_DEPTH_0 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_1 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_2 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_3 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_4 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_5 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_6 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_7 512 + +/* 3.10 UTMI-To-UTMI Bridge Component Parameters */ +#define OTG20_U2UB_EN 0 + +/* +FS Instance: +Configuration Set ID: 1 +*/ + +/* 3.1 Basic Config Parameters */ +#define OTG11_MODE 0 +#define OTG11_ARCHITECTURE 2 +#define OTG11_SINGLE_POINT 1 +#define OTG11_ENABLE_LPM 0 +#define OTG11_EN_DED_TX_FIFO 1 +#define OTG11_EN_DESC_DMA 1 +#define OTG11_MULTI_PROC_INTRPT 0 + +/* 3.2 USB Physical Layer Interface Parameters */ +#define OTG11_HSPHY_INTERFACE 0 +#define OTG11_FSPHY_INTERFACE 1 +#define OTG11_ENABLE_IC_USB 0 +#define OTG11_I2C_INTERFACE 0 +#define OTG11_ADP_SUPPORT 0 +#define OTG11_BC_SUPPORT 0 + +/* 3.3 Device Endpoint Configuration Parameters */ +#define OTG11_NUM_EPS 6 +#define OTG11_NUM_IN_EPS 5 +#define OTG11_NUM_CRL_EPS 0 + +/* 3.4 Host Endpoint Configuration Parameters */ +#define OTG11_NUM_HOST_CHAN 8 +#define OTG11_EN_PERIO_HOST 1 + +/* 3.5 Endpoint Channel FIFO Configuration Parameters */ +#define OTG11_DFIFO_DEPTH 256 +#define OTG11_DFIFO_DYNAMIC 1 +#define OTG11_RX_DFIFO_DEPTH 256 +#define OTG11_TX_HNPERIO_DFIFO_DEPTH 256 +#define OTG11_TX_NPERIO_DFIFO_DEPTH 256 +#define OTG11_TX_HPERIO_DFIFO_DEPTH 256 +#define OTG11_NPERIO_TX_QUEUE_DEPTH 4 +#define OTG11_PERIO_TX_QUEUE_DEPTH 8 + +/* 3.6 Additional Configuration Options Parameters */ +#define OTG11_TRANS_COUNT_WIDTH 16 +#define OTG11_PACKET_COUNT_WIDTH 7 +#define OTG11_RM_OPT_FEATURES 1 +#define OTG11_EN_PWROPT 1 +#define OTG11_SYNC_RESET_TYPE 0 +#define OTG11_EN_IDDIG_FILTER 1 +#define OTG11_EN_VBUSVALID_FILTER 1 +#define OTG11_EN_A_VALID_FILTER 1 +#define OTG11_EN_B_VALID_FILTER 1 +#define OTG11_EN_SESSIONEND_FILTER 1 +#define OTG11_EXCP_CNTL_XFER_FLOW 1 +#define OTG11_PWR_CLAMP 0 +#define OTG11_PWR_SWITCH_POLARITY 0 + +/* 3.7 Endpoint Direction Parameters */ +#define OTG11_EP_DIR_1 0 +#define OTG11_EP_DIR_2 0 +#define OTG11_EP_DIR_3 0 +#define OTG11_EP_DIR_4 0 +#define OTG11_EP_DIR_5 0 +#define OTG11_EP_DIR_6 0 + +/* 3.8 Device Periodic FIFO Depth Parameters */ + +/* 3.9 Device IN Endpoint FIFO Depth Parameters */ +#define OTG11_TX_DINEP_DFIFO_DEPTH_1 256 +#define OTG11_TX_DINEP_DFIFO_DEPTH_2 256 +#define OTG11_TX_DINEP_DFIFO_DEPTH_3 256 +#define OTG11_TX_DINEP_DFIFO_DEPTH_4 256 + +/* 3.10 UTMI-To-UTMI Bridge Component Parameters */ +#define OTG11_U2UB_EN 0 + +#ifdef __cplusplus +} +#endif