From ac3a3f801d9965ed4d07952330a61a0b436fd4a2 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Fri, 22 Nov 2024 11:18:46 +0100 Subject: [PATCH 1/3] feat(hal/usb): Explicitly enable clock and reset USB WRAP on init --- .../hal/esp32p4/include/hal/usb_wrap_ll.h | 8 +++--- .../hal/esp32s2/include/hal/usb_wrap_ll.h | 8 +++--- .../hal/esp32s3/include/hal/usb_wrap_ll.h | 8 +++--- components/hal/include/hal/usb_wrap_hal.h | 25 ++++++++++++++++++- components/hal/usb_wrap_hal.c | 9 ++++++- components/usb/usb_phy.c | 20 ++++++--------- 6 files changed, 51 insertions(+), 27 deletions(-) diff --git a/components/hal/esp32p4/include/hal/usb_wrap_ll.h b/components/hal/esp32p4/include/hal/usb_wrap_ll.h index 5e6b942366..d12c91b3dd 100644 --- a/components/hal/esp32p4/include/hal/usb_wrap_ll.h +++ b/components/hal/esp32p4/include/hal/usb_wrap_ll.h @@ -238,7 +238,7 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, * Enable the bus clock for USB Wrap module and USB_DWC_FS controller * @param clk_en True if enable the clock of USB Wrap module */ -FORCE_INLINE_ATTR void usb_wrap_ll_enable_bus_clock(bool clk_en) +FORCE_INLINE_ATTR void _usb_wrap_ll_enable_bus_clock(bool clk_en) { // Enable/disable system clock for USB_WRAP and USB_DWC_FS HP_SYS_CLKRST.soc_clk_ctrl1.reg_usb_otg11_sys_clk_en = clk_en; @@ -247,12 +247,12 @@ FORCE_INLINE_ATTR void usb_wrap_ll_enable_bus_clock(bool clk_en) } // HP_SYS_CLKRST.soc_clk_ctrlx and LP_AON_CLKRST.hp_usb_clkrst_ctrlx are shared registers, so this function must be used in an atomic way -#define usb_wrap_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_enable_bus_clock(__VA_ARGS__) +#define usb_wrap_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_ll_enable_bus_clock(__VA_ARGS__) /** * @brief Reset the USB Wrap module and USB_DWC_FS controller */ -FORCE_INLINE_ATTR void usb_wrap_ll_reset_register(void) +FORCE_INLINE_ATTR void _usb_wrap_ll_reset_register(void) { // Reset the USB_WRAP and USB_DWC_FS LP_AON_CLKRST.hp_usb_clkrst_ctrl1.rst_en_usb_otg11 = 1; @@ -260,7 +260,7 @@ FORCE_INLINE_ATTR void usb_wrap_ll_reset_register(void) } // P_AON_CLKRST.hp_usb_clkrst_ctrlx are shared registers, so this function must be used in an atomic way -#define usb_wrap_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_reset_register(__VA_ARGS__) +#define usb_wrap_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_ll_reset_register(__VA_ARGS__) #ifdef __cplusplus } diff --git a/components/hal/esp32s2/include/hal/usb_wrap_ll.h b/components/hal/esp32s2/include/hal/usb_wrap_ll.h index 09c1625e6a..bf88f7b8c3 100644 --- a/components/hal/esp32s2/include/hal/usb_wrap_ll.h +++ b/components/hal/esp32s2/include/hal/usb_wrap_ll.h @@ -207,25 +207,25 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, * Enable the bus clock for USB Wrap module * @param clk_en True if enable the clock of USB Wrap module */ -FORCE_INLINE_ATTR void usb_wrap_ll_enable_bus_clock(bool clk_en) +FORCE_INLINE_ATTR void _usb_wrap_ll_enable_bus_clock(bool clk_en) { REG_SET_FIELD(DPORT_PERIP_CLK_EN0_REG, DPORT_USB_CLK_EN, clk_en); } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_wrap_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_enable_bus_clock(__VA_ARGS__) +#define usb_wrap_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_ll_enable_bus_clock(__VA_ARGS__) /** * @brief Reset the USB Wrap module */ -FORCE_INLINE_ATTR void usb_wrap_ll_reset_register(void) +FORCE_INLINE_ATTR void _usb_wrap_ll_reset_register(void) { REG_SET_FIELD(DPORT_PERIP_RST_EN0_REG, DPORT_USB_RST, 1); REG_SET_FIELD(DPORT_PERIP_RST_EN0_REG, DPORT_USB_RST, 0); } // SYSTEM.perip_rst_enx are shared registers, so this function must be used in an atomic way -#define usb_wrap_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_reset_register(__VA_ARGS__) +#define usb_wrap_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_ll_reset_register(__VA_ARGS__) #ifdef __cplusplus } diff --git a/components/hal/esp32s3/include/hal/usb_wrap_ll.h b/components/hal/esp32s3/include/hal/usb_wrap_ll.h index 9ae285d50c..b11743baf8 100644 --- a/components/hal/esp32s3/include/hal/usb_wrap_ll.h +++ b/components/hal/esp32s3/include/hal/usb_wrap_ll.h @@ -216,25 +216,25 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, * Enable the bus clock for USB Wrap module * @param clk_en True if enable the clock of USB Wrap module */ -FORCE_INLINE_ATTR void usb_wrap_ll_enable_bus_clock(bool clk_en) +FORCE_INLINE_ATTR void _usb_wrap_ll_enable_bus_clock(bool clk_en) { SYSTEM.perip_clk_en0.usb_clk_en = clk_en; } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_wrap_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_enable_bus_clock(__VA_ARGS__) +#define usb_wrap_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_ll_enable_bus_clock(__VA_ARGS__) /** * @brief Reset the USB Wrap module */ -FORCE_INLINE_ATTR void usb_wrap_ll_reset_register(void) +FORCE_INLINE_ATTR void _usb_wrap_ll_reset_register(void) { SYSTEM.perip_rst_en0.usb_rst = 1; SYSTEM.perip_rst_en0.usb_rst = 0; } // SYSTEM.perip_rst_enx are shared registers, so this function must be used in an atomic way -#define usb_wrap_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_reset_register(__VA_ARGS__) +#define usb_wrap_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_ll_reset_register(__VA_ARGS__) #ifdef __cplusplus } diff --git a/components/hal/include/hal/usb_wrap_hal.h b/components/hal/include/hal/usb_wrap_hal.h index 8477b6927d..0571072add 100644 --- a/components/hal/include/hal/usb_wrap_hal.h +++ b/components/hal/include/hal/usb_wrap_hal.h @@ -32,7 +32,30 @@ typedef struct { * * @param hal USB WRAP HAL context */ -void usb_wrap_hal_init(usb_wrap_hal_context_t *hal); +void _usb_wrap_hal_init(usb_wrap_hal_context_t *hal); + +#if SOC_RCC_IS_INDEPENDENT +#define usb_wrap_hal_init(...) _usb_wrap_hal_init(__VA_ARGS__) +#else +// Use a macro to wrap the function, force the caller to use it in a critical section +// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define usb_wrap_hal_init(...) do {(void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_hal_init(__VA_ARGS__);} while(0) +#endif + +/** + * @brief Disable USB WRAP + * + * Disable clock to the peripheral + */ +void _usb_wrap_hal_disable(void); + +#if SOC_RCC_IS_INDEPENDENT +#define usb_wrap_hal_disable(...) _usb_wrap_hal_disable(__VA_ARGS__) +#else +// Use a macro to wrap the function, force the caller to use it in a critical section +// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define usb_wrap_hal_disable(...) do {(void)__DECLARE_RCC_ATOMIC_ENV; _usb_wrap_hal_disable(__VA_ARGS__);} while(0) +#endif /* ---------------------------- USB PHY Control ---------------------------- */ diff --git a/components/hal/usb_wrap_hal.c b/components/hal/usb_wrap_hal.c index 52d6933bce..d0218ead6f 100644 --- a/components/hal/usb_wrap_hal.c +++ b/components/hal/usb_wrap_hal.c @@ -8,14 +8,21 @@ #include "hal/usb_wrap_ll.h" #include "hal/usb_wrap_hal.h" -void usb_wrap_hal_init(usb_wrap_hal_context_t *hal) +void _usb_wrap_hal_init(usb_wrap_hal_context_t *hal) { hal->dev = &USB_WRAP; + _usb_wrap_ll_enable_bus_clock(true); + _usb_wrap_ll_reset_register(); #if !USB_WRAP_LL_EXT_PHY_SUPPORTED usb_wrap_ll_phy_set_defaults(hal->dev); #endif } +void _usb_wrap_hal_disable(void) +{ + _usb_wrap_ll_enable_bus_clock(false); +} + #if USB_WRAP_LL_EXT_PHY_SUPPORTED void usb_wrap_hal_phy_set_external(usb_wrap_hal_context_t *hal, bool external) { diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index 220e631732..43a2510997 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -21,9 +21,9 @@ #include "soc/usb_pins.h" #if !SOC_RCC_IS_INDEPENDENT -#define USB_WRAP_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#define USB_PHY_RCC_ATOMIC() PERIPH_RCC_ATOMIC() #else -#define USB_WRAP_RCC_ATOMIC() +#define USB_PHY_RCC_ATOMIC() #endif static const char *USBPHY_TAG = "usb_phy"; @@ -259,12 +259,7 @@ static esp_err_t usb_phy_install(void) PHY_EXIT_CRITICAL(); goto cleanup; } - // Enable USB peripheral and reset the register PHY_EXIT_CRITICAL(); - USB_WRAP_RCC_ATOMIC() { - usb_wrap_ll_enable_bus_clock(true); - usb_wrap_ll_reset_register(); - } return ESP_OK; cleanup: @@ -302,10 +297,9 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r phy_context->controller = config->controller; phy_context->status = USB_PHY_STATUS_IN_USE; - usb_wrap_hal_init(&phy_context->wrap_hal); -#if SOC_USB_SERIAL_JTAG_SUPPORTED - usb_serial_jtag_hal_init(&phy_context->usj_hal); -#endif + USB_PHY_RCC_ATOMIC() { + usb_wrap_hal_init(&phy_context->wrap_hal); + } if (config->controller == USB_PHY_CTRL_OTG) { #if USB_WRAP_LL_EXT_PHY_SUPPORTED usb_wrap_hal_phy_set_external(&phy_context->wrap_hal, (config->target == USB_PHY_TARGET_EXT)); @@ -361,9 +355,9 @@ static void phy_uninstall(void) if (p_phy_ctrl_obj->ref_count == 0) { p_phy_ctrl_obj_free = p_phy_ctrl_obj; p_phy_ctrl_obj = NULL; - USB_WRAP_RCC_ATOMIC() { + USB_PHY_RCC_ATOMIC() { // Disable USB peripheral without reset the module - usb_wrap_ll_enable_bus_clock(false); + usb_wrap_hal_disable(); } } PHY_EXIT_CRITICAL(); From b78bcaea361be7aa43f611178cee8f255f2aea77 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Wed, 18 Dec 2024 17:04:22 +0100 Subject: [PATCH 2/3] refactor(usb/phy): Do not use deprecated variables in usb_phy --- .../soc/esp32p4/include/soc/usb_dwc_cfg.h | 2 +- components/soc/esp32p4/usb_dwc_periph.c | 2 +- components/soc/esp32s2/usb_dwc_periph.c | 2 +- components/soc/esp32s3/usb_dwc_periph.c | 2 +- components/soc/include/soc/usb_dwc_periph.h | 4 +- components/usb/include/esp_private/usb_phy.h | 8 +- components/usb/usb_phy.c | 115 ++++++++---------- 7 files changed, 66 insertions(+), 69 deletions(-) diff --git a/components/soc/esp32p4/include/soc/usb_dwc_cfg.h b/components/soc/esp32p4/include/soc/usb_dwc_cfg.h index 816cff4285..ddd2cdc38b 100644 --- a/components/soc/esp32p4/include/soc/usb_dwc_cfg.h +++ b/components/soc/esp32p4/include/soc/usb_dwc_cfg.h @@ -25,7 +25,7 @@ Configuration Set ID: 11 #define OTG20_MULTI_PROC_INTRPT 1 /* 3.2 USB Physical Layer Interface Parameters */ -#define OTG20_HSPHY_INTERFACE 3 +#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 diff --git a/components/soc/esp32p4/usb_dwc_periph.c b/components/soc/esp32p4/usb_dwc_periph.c index 23fecc8afe..ce8a42997c 100644 --- a/components/soc/esp32p4/usb_dwc_periph.c +++ b/components/soc/esp32p4/usb_dwc_periph.c @@ -12,7 +12,7 @@ /* -------------------------------- Private --------------------------------- */ -static const usb_utmi_otg_signal_conn_t dwc_fs_otg_signals = { +static const usb_otg_signal_conn_t dwc_fs_otg_signals = { // Inputs .iddig = USB_OTG11_IDDIG_PAD_IN_IDX, .avalid = USB_OTG11_AVALID_PAD_IN_IDX, diff --git a/components/soc/esp32s2/usb_dwc_periph.c b/components/soc/esp32s2/usb_dwc_periph.c index 2cb76077e7..2656918294 100644 --- a/components/soc/esp32s2/usb_dwc_periph.c +++ b/components/soc/esp32s2/usb_dwc_periph.c @@ -24,7 +24,7 @@ static const usb_fsls_serial_signal_conn_t fsls_signals = { .fs_edge_sel = USB_EXTPHY_SPEED_IDX, }; -static const usb_utmi_otg_signal_conn_t otg_signals = { +static const usb_otg_signal_conn_t otg_signals = { // Inputs .iddig = USB_OTG_IDDIG_IN_IDX, .avalid = USB_OTG_AVALID_IN_IDX, diff --git a/components/soc/esp32s3/usb_dwc_periph.c b/components/soc/esp32s3/usb_dwc_periph.c index 51386dde8b..c2690906f0 100644 --- a/components/soc/esp32s3/usb_dwc_periph.c +++ b/components/soc/esp32s3/usb_dwc_periph.c @@ -25,7 +25,7 @@ static const usb_fsls_serial_signal_conn_t fsls_signals = { .fs_edge_sel = USB_EXTPHY_SPEED_IDX, }; -static const usb_utmi_otg_signal_conn_t otg_signals = { +static const usb_otg_signal_conn_t otg_signals = { // Inputs .iddig = USB_OTG_IDDIG_IN_IDX, .avalid = USB_OTG_AVALID_IN_IDX, diff --git a/components/soc/include/soc/usb_dwc_periph.h b/components/soc/include/soc/usb_dwc_periph.h index 8e1832c2ce..ae633eeeca 100644 --- a/components/soc/include/soc/usb_dwc_periph.h +++ b/components/soc/include/soc/usb_dwc_periph.h @@ -63,7 +63,7 @@ typedef struct { int drvvbus; int chrgvbus; int dischrgvbus; -} usb_utmi_otg_signal_conn_t; +} usb_otg_signal_conn_t; /** * @brief USB Controller Information @@ -73,7 +73,7 @@ typedef struct { typedef struct { struct { const usb_fsls_serial_signal_conn_t * const fsls_signals; // Must be set if external PHY is supported by controller - const usb_utmi_otg_signal_conn_t * const otg_signals; + const usb_otg_signal_conn_t * const otg_signals; const int irq; const int irq_2nd_cpu; // The USB-DWC can provide 2nd interrupt so each CPU can have its own interrupt line. Set to -1 if not supported } controllers [SOC_USB_OTG_PERIPH_NUM]; diff --git a/components/usb/include/esp_private/usb_phy.h b/components/usb/include/esp_private/usb_phy.h index 65ad137b72..d2426fd530 100644 --- a/components/usb/include/esp_private/usb_phy.h +++ b/components/usb/include/esp_private/usb_phy.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,12 +54,16 @@ typedef enum { * @brief USB external PHY IO pins configuration structure */ typedef struct { + // Inputs int vp_io_num; /**< GPIO pin to USB_EXTPHY_VP_IDX */ int vm_io_num; /**< GPIO pin to USB_EXTPHY_VM_IDX */ int rcv_io_num; /**< GPIO pin to USB_EXTPHY_RCV_IDX */ + // Outputs + int suspend_n_io_num; /**< GPIO pin to USB_EXTPHY_SUSPND_IDX */ int oen_io_num; /**< GPIO pin to USB_EXTPHY_OEN_IDX */ int vpo_io_num; /**< GPIO pin to USB_EXTPHY_VPO_IDX */ int vmo_io_num; /**< GPIO pin to USB_EXTPHY_VMO_IDX */ + int fs_edge_sel_io_num; /**< GPIO pin to USB_EXTPHY_SPEED_IDX */ } usb_phy_ext_io_conf_t; /** @@ -101,7 +105,7 @@ typedef struct phy_context_t *usb_phy_handle_t; /**< USB PHY context handle * * * This function will enable the OTG Controller * - * @param[in] config USB PHY configurtion struct + * @param[in] config USB PHY configuration struct * @param[out] handle_ret USB PHY context handle * * @return diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index 43a2510997..c8da32714e 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -13,12 +13,9 @@ #include "esp_private/critical_section.h" #include "soc/usb_dwc_periph.h" #include "hal/usb_wrap_hal.h" -#include "hal/usb_serial_jtag_hal.h" #include "esp_rom_gpio.h" #include "driver/gpio.h" -#include "hal/gpio_ll.h" #include "soc/soc_caps.h" -#include "soc/usb_pins.h" #if !SOC_RCC_IS_INDEPENDENT #define USB_PHY_RCC_ATOMIC() PERIPH_RCC_ATOMIC() @@ -40,9 +37,6 @@ struct phy_context_t { usb_phy_speed_t otg_speed; /**< USB speed */ usb_phy_ext_io_conf_t *iopins; /**< external PHY I/O pins */ usb_wrap_hal_context_t wrap_hal; /**< USB WRAP HAL context */ -#if SOC_USB_SERIAL_JTAG_SUPPORTED - usb_serial_jtag_hal_context_t usj_hal; /**< USJ HAL context */ -#endif }; typedef struct { @@ -51,72 +45,78 @@ typedef struct { uint32_t ref_count; /**< reference count used to protect p_phy_ctrl_obj */ } phy_ctrl_obj_t; -/** - * @brief A pin descriptor for initialize external PHY I/O pins - */ -typedef struct { - int pin; /**< GPIO pin num */ - const int func; /**< GPIO matrix signal */ - const bool is_output; /**< input/output signal */ -} usb_iopin_dsc_t; - static phy_ctrl_obj_t *p_phy_ctrl_obj = NULL; DEFINE_CRIT_SECTION_LOCK_STATIC(phy_spinlock); #define PHY_ENTER_CRITICAL() esp_os_enter_critical(&phy_spinlock) #define PHY_EXIT_CRITICAL() esp_os_exit_critical(&phy_spinlock) -static esp_err_t phy_iopins_configure(const usb_iopin_dsc_t *usb_periph_iopins, int iopins_num) +static esp_err_t phy_configure_pin_input(int gpio_pin, int signal_idx) { - for (int i = 0; i < iopins_num; i++) { - const usb_iopin_dsc_t iopin = usb_periph_iopins[i]; - if (iopin.pin != GPIO_NUM_NC) { - ESP_RETURN_ON_FALSE((iopin.is_output && GPIO_IS_VALID_OUTPUT_GPIO(iopin.pin)) || - (!iopin.is_output && GPIO_IS_VALID_GPIO(iopin.pin)), - ESP_ERR_INVALID_ARG, USBPHY_TAG, "io_num argument is invalid"); - esp_rom_gpio_pad_select_gpio(iopin.pin); - if (iopin.is_output) { - esp_rom_gpio_connect_out_signal(iopin.pin, iopin.func, false, false); - } else { - esp_rom_gpio_connect_in_signal(iopin.pin, iopin.func, false); - gpio_ll_input_enable(&GPIO, iopin.pin); - } - esp_rom_gpio_pad_unhold(iopin.pin); - } + if (gpio_pin != GPIO_NUM_NC) { + ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_pin), + ESP_ERR_INVALID_ARG, USBPHY_TAG, "io_num argument is invalid"); + esp_rom_gpio_pad_select_gpio(gpio_pin); + esp_rom_gpio_connect_in_signal(gpio_pin, signal_idx, false); + gpio_input_enable(gpio_pin); + esp_rom_gpio_pad_unhold(gpio_pin); + } + return ESP_OK; +} + +static esp_err_t phy_configure_pin_output(int gpio_pin, int signal_idx) +{ + if (gpio_pin != GPIO_NUM_NC) { + ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_pin), + ESP_ERR_INVALID_ARG, USBPHY_TAG, "io_num argument is invalid"); + esp_rom_gpio_pad_select_gpio(gpio_pin); + esp_rom_gpio_connect_out_signal(gpio_pin, signal_idx, false, false); + esp_rom_gpio_pad_unhold(gpio_pin); } return ESP_OK; } static esp_err_t phy_external_iopins_configure(const usb_phy_ext_io_conf_t *ext_io_conf) { - const usb_iopin_dsc_t usb_periph_iopins[] = { - {ext_io_conf->vp_io_num, usb_otg_periph_signal.extphy_vp_in, false}, - {ext_io_conf->vm_io_num, usb_otg_periph_signal.extphy_vm_in, false}, - {ext_io_conf->rcv_io_num, usb_otg_periph_signal.extphy_rcv_in, false}, - {ext_io_conf->oen_io_num, usb_otg_periph_signal.extphy_oen_out, true}, - {ext_io_conf->vpo_io_num, usb_otg_periph_signal.extphy_vpo_out, true}, - {ext_io_conf->vmo_io_num, usb_otg_periph_signal.extphy_vmo_out, true}, - }; + esp_err_t ret = ESP_OK; + const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[0].fsls_signals; - return phy_iopins_configure(usb_periph_iopins, sizeof(usb_periph_iopins) / sizeof(usb_iopin_dsc_t)); + // Inputs + ret |= phy_configure_pin_input(ext_io_conf->vp_io_num, fsls_sig->rx_dp); + ret |= phy_configure_pin_input(ext_io_conf->vm_io_num, fsls_sig->rx_dm); + ret |= phy_configure_pin_input(ext_io_conf->rcv_io_num, fsls_sig->rx_rcv); + + // Outputs + ret |= phy_configure_pin_output(ext_io_conf->suspend_n_io_num, fsls_sig->suspend_n); + ret |= phy_configure_pin_output(ext_io_conf->oen_io_num, fsls_sig->tx_enable_n); + ret |= phy_configure_pin_output(ext_io_conf->vpo_io_num, fsls_sig->tx_dp); + ret |= phy_configure_pin_output(ext_io_conf->vmo_io_num, fsls_sig->tx_dm); + ret |= phy_configure_pin_output(ext_io_conf->fs_edge_sel_io_num, fsls_sig->fs_edge_sel); + + return ret; } static esp_err_t phy_otg_iopins_configure(const usb_phy_otg_io_conf_t *otg_io_conf) { - const usb_iopin_dsc_t usb_periph_iopins[] = { - {otg_io_conf->iddig_io_num, usb_otg_periph_signal.otg_iddig_in, false}, - {otg_io_conf->avalid_io_num, usb_otg_periph_signal.otg_avalid_in, false}, - {otg_io_conf->vbusvalid_io_num, usb_otg_periph_signal.otg_vbusvalid_in, false}, - {otg_io_conf->idpullup_io_num, usb_otg_periph_signal.otg_idpullup_out, true}, - {otg_io_conf->dppulldown_io_num, usb_otg_periph_signal.otg_dppulldown_out, true}, - {otg_io_conf->dmpulldown_io_num, usb_otg_periph_signal.otg_dmpulldown_out, true}, - {otg_io_conf->drvvbus_io_num, usb_otg_periph_signal.otg_drvvbus_out, true}, - {otg_io_conf->bvalid_io_num, usb_otg_periph_signal.srp_bvalid_in, false}, - {otg_io_conf->sessend_io_num, usb_otg_periph_signal.srp_sessend_in, false}, - {otg_io_conf->chrgvbus_io_num, usb_otg_periph_signal.srp_chrgvbus_out, true}, - {otg_io_conf->dischrgvbus_io_num, usb_otg_periph_signal.srp_dischrgvbus_out, true}, - }; - return phy_iopins_configure(usb_periph_iopins, sizeof(usb_periph_iopins) / sizeof(usb_iopin_dsc_t)); + esp_err_t ret = ESP_OK; + const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[0].otg_signals; + + // Inputs + ret |= phy_configure_pin_input(otg_io_conf->iddig_io_num, otg_sig->iddig); + ret |= phy_configure_pin_input(otg_io_conf->avalid_io_num, otg_sig->avalid); + ret |= phy_configure_pin_input(otg_io_conf->vbusvalid_io_num, otg_sig->vbusvalid); + ret |= phy_configure_pin_input(otg_io_conf->bvalid_io_num, otg_sig->bvalid); + ret |= phy_configure_pin_input(otg_io_conf->sessend_io_num, otg_sig->sessend); + + // Outputs + ret |= phy_configure_pin_output(otg_io_conf->idpullup_io_num, otg_sig->idpullup); + ret |= phy_configure_pin_output(otg_io_conf->dppulldown_io_num, otg_sig->dppulldown); + ret |= phy_configure_pin_output(otg_io_conf->dmpulldown_io_num, otg_sig->dmpulldown); + ret |= phy_configure_pin_output(otg_io_conf->drvvbus_io_num, otg_sig->drvvbus); + ret |= phy_configure_pin_output(otg_io_conf->chrgvbus_io_num, otg_sig->chrgvbus); + ret |= phy_configure_pin_output(otg_io_conf->dischrgvbus_io_num, otg_sig->dischrgvbus); + + return ret; } esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode) @@ -305,13 +305,6 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r usb_wrap_hal_phy_set_external(&phy_context->wrap_hal, (config->target == USB_PHY_TARGET_EXT)); #endif } -#if SOC_USB_SERIAL_JTAG_SUPPORTED - else if (config->controller == USB_PHY_CTRL_SERIAL_JTAG) { - usb_serial_jtag_hal_phy_set_external(&phy_context->usj_hal, (config->target == USB_PHY_TARGET_EXT)); - phy_context->otg_mode = USB_OTG_MODE_DEVICE; - phy_context->otg_speed = USB_PHY_SPEED_FULL; - } -#endif if (config->target == USB_PHY_TARGET_INT) { gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); From f93e1bc43b241a5fa9300ea6469fd6e26e5399ce Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Fri, 3 Jan 2025 18:51:08 +0100 Subject: [PATCH 3/3] refactor(usb/phy): Start using values from usb_dwc_info in PHY driver Add tests for PHY sanity checks --- components/hal/include/hal/usb_phy_types.h | 5 +- components/usb/include/esp_private/usb_phy.h | 11 +- .../usb/test_apps/.build-test-rules.yml | 18 ++ components/usb/test_apps/phy/CMakeLists.txt | 9 + components/usb/test_apps/phy/README.md | 4 + .../usb/test_apps/phy/main/CMakeLists.txt | 6 + .../usb/test_apps/phy/main/test_app_main.c | 180 ++++++++++++++++++ .../usb/test_apps/phy/pytest_usb_phy.py | 13 ++ .../usb/test_apps/phy/sdkconfig.defaults | 8 + components/usb/usb_phy.c | 52 +++-- 10 files changed, 280 insertions(+), 26 deletions(-) create mode 100644 components/usb/test_apps/phy/CMakeLists.txt create mode 100644 components/usb/test_apps/phy/README.md create mode 100644 components/usb/test_apps/phy/main/CMakeLists.txt create mode 100644 components/usb/test_apps/phy/main/test_app_main.c create mode 100644 components/usb/test_apps/phy/pytest_usb_phy.py create mode 100644 components/usb/test_apps/phy/sdkconfig.defaults diff --git a/components/hal/include/hal/usb_phy_types.h b/components/hal/include/hal/usb_phy_types.h index 50636a64dd..62da8f6ae0 100644 --- a/components/hal/include/hal/usb_phy_types.h +++ b/components/hal/include/hal/usb_phy_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,7 +22,8 @@ extern "C" * @brief USB PHY target */ typedef enum { - USB_PHY_TARGET_INT, /**< USB target is internal PHY */ + USB_PHY_TARGET_INT, /**< USB target is internal FSLS PHY */ + USB_PHY_TARGET_UTMI, /**< USB target is internal UTMI PHY */ USB_PHY_TARGET_EXT, /**< USB target is external PHY */ USB_PHY_TARGET_MAX, } usb_phy_target_t; diff --git a/components/usb/include/esp_private/usb_phy.h b/components/usb/include/esp_private/usb_phy.h index d2426fd530..e8e892a856 100644 --- a/components/usb/include/esp_private/usb_phy.h +++ b/components/usb/include/esp_private/usb_phy.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -109,10 +109,11 @@ typedef struct phy_context_t *usb_phy_handle_t; /**< USB PHY context handle * * @param[out] handle_ret USB PHY context handle * * @return - * - ESP_OK Success - * - ESP_FAIL USB PHY init error. - * - ESP_ERR_INVALID_STATE USB PHY not installed. - * - ESP_ERR_NO_MEM USB_OTG installation failed due to no mem. + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE USB PHY already initialized. + * - ESP_ERR_NO_MEM USB_OTG Installation failed due to no mem. + * - ESP_ERR_NOT_SUPPORTED Selected PHY is not supported on this target. + * - ESP_ERR_INVALID_ARG Invalid input argument. */ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_ret); diff --git a/components/usb/test_apps/.build-test-rules.yml b/components/usb/test_apps/.build-test-rules.yml index c8b66b72e6..44446d7b22 100644 --- a/components/usb/test_apps/.build-test-rules.yml +++ b/components/usb/test_apps/.build-test-rules.yml @@ -17,3 +17,21 @@ components/usb/test_apps: - components/soc/include/soc/usb*.h - components/soc/esp32*/include/soc/usb_dwc_*.h - components/soc/esp32*/include/soc/usb_wrap_*.h + +components/usb/test_apps/phy: + enable: + - if: SOC_USB_OTG_SUPPORTED == 1 + disable_test: + - if: IDF_TARGET in ["esp32p4"] + temporary: true + reason: ESP32-P4 PHY driver not yet migrated + depends_components: + - usb + depends_filepatterns: + - components/hal/usb*.c + - components/hal/include/hal/usb*.h + - components/hal/esp32*/include/hal/usb*.h + - components/soc/esp32*/usb*.c + - components/soc/include/soc/usb*.h + - components/soc/esp32*/include/soc/usb_dwc_*.h + - components/soc/esp32*/include/soc/usb_wrap_*.h diff --git a/components/usb/test_apps/phy/CMakeLists.txt b/components/usb/test_apps/phy/CMakeLists.txt new file mode 100644 index 0000000000..5724e9e640 --- /dev/null +++ b/components/usb/test_apps/phy/CMakeLists.txt @@ -0,0 +1,9 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +project(test_app_usb_phy) diff --git a/components/usb/test_apps/phy/README.md b/components/usb/test_apps/phy/README.md new file mode 100644 index 0000000000..5b5662288f --- /dev/null +++ b/components/usb/test_apps/phy/README.md @@ -0,0 +1,4 @@ +| Supported Targets | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | + +# USB: PHY sanity checks diff --git a/components/usb/test_apps/phy/main/CMakeLists.txt b/components/usb/test_apps/phy/main/CMakeLists.txt new file mode 100644 index 0000000000..2e5a9bcdaf --- /dev/null +++ b/components/usb/test_apps/phy/main/CMakeLists.txt @@ -0,0 +1,6 @@ +# In order for the cases defined by `TEST_CASE` to be linked into the final elf, +# the component can be registered as WHOLE_ARCHIVE +idf_component_register(SRC_DIRS "." + PRIV_INCLUDE_DIRS "." + REQUIRES usb unity + WHOLE_ARCHIVE) diff --git a/components/usb/test_apps/phy/main/test_app_main.c b/components/usb/test_apps/phy/main/test_app_main.c new file mode 100644 index 0000000000..a7994e8799 --- /dev/null +++ b/components/usb/test_apps/phy/main/test_app_main.c @@ -0,0 +1,180 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "unity_test_utils_memory.h" +#include "esp_private/usb_phy.h" +#include "hal/usb_wrap_ll.h" // For USB_WRAP_LL_EXT_PHY_SUPPORTED symbol +#include "soc/soc_caps.h" // For SOC_USB_UTMI_PHY_NUM symbol + +#if USB_WRAP_LL_EXT_PHY_SUPPORTED +#define EXT_PHY_SUPPORTED 1 +#else +#define EXT_PHY_SUPPORTED 0 +#endif + +#if SOC_USB_UTMI_PHY_NUM > 0 +#define UTMI_PHY_SUPPORTED 1 +#else +#define UTMI_PHY_SUPPORTED 0 +#endif + +void setUp(void) +{ + unity_utils_record_free_mem(); +} + +void tearDown(void) +{ + unity_utils_evaluate_leaks(); +} + +void app_main(void) +{ + // ____ ___ ___________________ __ __ + // | | \/ _____/\______ \ _/ |_ ____ _______/ |_ + // | | /\_____ \ | | _/ \ __\/ __ \ / ___/\ __\. + // | | / / \ | | \ | | \ ___/ \___ \ | | + // |______/ /_______ / |______ / |__| \___ >____ > |__| + // \/ \/ \/ \/ + printf(" ____ ___ ___________________ __ __ \r\n"); + printf("| | \\/ _____/\\______ \\ _/ |_ ____ _______/ |_ \r\n"); + printf("| | /\\_____ \\ | | _/ \\ __\\/ __ \\ / ___/\\ __\\\r\n"); + printf("| | / / \\ | | \\ | | \\ ___/ \\___ \\ | | \r\n"); + printf("|______/ /_______ / |______ / |__| \\___ >____ > |__| \r\n"); + printf(" \\/ \\/ \\/ \\/ \r\n"); + + unity_utils_setup_heap_record(80); + unity_utils_set_leak_level(128); + unity_run_menu(); +} + +/** + * Test init and deinit of internal FSLS PHY + */ +TEST_CASE("Init internal FSLS PHY", "[phy]") +{ + usb_phy_handle_t phy_handle = NULL; + const usb_phy_config_t phy_config = { + .controller = USB_PHY_CTRL_OTG, + .target = USB_PHY_TARGET_INT, + .otg_mode = USB_OTG_MODE_HOST, + .otg_speed = USB_PHY_SPEED_UNDEFINED, + .ext_io_conf = NULL, + .otg_io_conf = NULL, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NOT_NULL(phy_handle); + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); +} + +/** + * Test init and deinit of external FSLS PHY + */ +TEST_CASE("Init external FSLS PHY", "[phy]") +{ + usb_phy_handle_t phy_handle = NULL; + usb_phy_config_t phy_config = { + .controller = USB_PHY_CTRL_OTG, + .target = USB_PHY_TARGET_EXT, + .otg_mode = USB_OTG_MODE_HOST, + .otg_speed = USB_PHY_SPEED_UNDEFINED, + .ext_io_conf = NULL, + .otg_io_conf = NULL, + }; +#if EXT_PHY_SUPPORTED + // Init ext PHY without ext_io_conf -> FAIL + TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NULL(phy_handle); + + // Init ext PHY with ext_io_conf -> PASS + const usb_phy_ext_io_conf_t ext_io_conf = { // Some random values + .vp_io_num = 1, + .vm_io_num = 1, + .rcv_io_num = 1, + .suspend_n_io_num = 1, + .oen_io_num = 1, + .vpo_io_num = 1, + .vmo_io_num = 1, + .fs_edge_sel_io_num = 1, + }; + phy_config.ext_io_conf = &ext_io_conf; + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NOT_NULL(phy_handle); + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); +#else + TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NULL(phy_handle); +#endif +} + +/** + * Test init and deinit of internal UTMI PHY + */ +TEST_CASE("Init internal UTMI PHY", "[phy]") +{ + usb_phy_handle_t phy_handle = NULL; + const usb_phy_config_t phy_config = { + .controller = USB_PHY_CTRL_OTG, + .target = USB_PHY_TARGET_UTMI, + .otg_mode = USB_OTG_MODE_HOST, + .otg_speed = USB_PHY_SPEED_UNDEFINED, + .ext_io_conf = NULL, + .otg_io_conf = NULL, + }; +#if UTMI_PHY_SUPPORTED + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NOT_NULL(phy_handle); + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); +#else + TEST_ASSERT_NOT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NULL(phy_handle); +#endif +} + +/** + * Test init and deinit of all PHYs at the same time + */ +TEST_CASE("Init all PHYs", "[phy]") +{ + usb_phy_handle_t phy_handle = NULL; + usb_phy_handle_t phy_handle_2 = NULL; + usb_phy_config_t phy_config = { + .controller = USB_PHY_CTRL_OTG, + .target = USB_PHY_TARGET_INT, + .otg_mode = USB_OTG_MODE_HOST, + .otg_speed = USB_PHY_SPEED_UNDEFINED, + .ext_io_conf = NULL, + .otg_io_conf = NULL, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle)); + TEST_ASSERT_NOT_NULL(phy_handle); + + // Our current targets support either UTMI or external PHY + // so if/else suffice here +#if UTMI_PHY_SUPPORTED + phy_config.target = USB_PHY_TARGET_UTMI; +#else + const usb_phy_ext_io_conf_t ext_io_conf = { // Some random values + .vp_io_num = 1, + .vm_io_num = 1, + .rcv_io_num = 1, + .suspend_n_io_num = 1, + .oen_io_num = 1, + .vpo_io_num = 1, + .vmo_io_num = 1, + .fs_edge_sel_io_num = 1, + }; + phy_config.target = USB_PHY_TARGET_EXT; + phy_config.ext_io_conf = &ext_io_conf; +#endif + TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_handle_2)); + TEST_ASSERT_NOT_NULL(phy_handle_2); + + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle)); + TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_handle_2)); +} diff --git a/components/usb/test_apps/phy/pytest_usb_phy.py b/components/usb/test_apps/phy/pytest_usb_phy.py new file mode 100644 index 0000000000..27cb20eca7 --- /dev/null +++ b/components/usb/test_apps/phy/pytest_usb_phy.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32p4 +@pytest.mark.generic +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='P4 PHY not yet migrated') +def test_usb_phy(dut: Dut) -> None: + dut.run_all_single_board_cases(group='phy') diff --git a/components/usb/test_apps/phy/sdkconfig.defaults b/components/usb/test_apps/phy/sdkconfig.defaults new file mode 100644 index 0000000000..0632edf757 --- /dev/null +++ b/components/usb/test_apps/phy/sdkconfig.defaults @@ -0,0 +1,8 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +# CONFIG_ESP_TASK_WDT_INIT is not set +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +# CONFIG_UNITY_ENABLE_FLOAT is not set +# CONFIG_UNITY_ENABLE_DOUBLE is not set +CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index c8da32714e..1cf9a25b81 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -76,10 +76,10 @@ static esp_err_t phy_configure_pin_output(int gpio_pin, int signal_idx) return ESP_OK; } -static esp_err_t phy_external_iopins_configure(const usb_phy_ext_io_conf_t *ext_io_conf) +static esp_err_t phy_external_iopins_configure(const usb_phy_ext_io_conf_t *ext_io_conf, const usb_fsls_serial_signal_conn_t *fsls_sig) { + ESP_RETURN_ON_FALSE(ext_io_conf && fsls_sig, ESP_ERR_INVALID_ARG, USBPHY_TAG, "argument is invalid"); esp_err_t ret = ESP_OK; - const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[0].fsls_signals; // Inputs ret |= phy_configure_pin_input(ext_io_conf->vp_io_num, fsls_sig->rx_dp); @@ -96,10 +96,10 @@ static esp_err_t phy_external_iopins_configure(const usb_phy_ext_io_conf_t *ext_ return ret; } -static esp_err_t phy_otg_iopins_configure(const usb_phy_otg_io_conf_t *otg_io_conf) +static esp_err_t phy_otg_iopins_configure(const usb_phy_otg_io_conf_t *otg_io_conf, const usb_otg_signal_conn_t *otg_sig) { + ESP_RETURN_ON_FALSE(otg_io_conf && otg_sig, ESP_ERR_INVALID_ARG, USBPHY_TAG, "argument is invalid"); esp_err_t ret = ESP_OK; - const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[0].otg_signals; // Inputs ret |= phy_configure_pin_input(otg_io_conf->iddig_io_num, otg_sig->iddig); @@ -126,11 +126,13 @@ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode) ESP_RETURN_ON_FALSE(handle->controller == USB_PHY_CTRL_OTG, ESP_FAIL, USBPHY_TAG, "phy source is not USB_OTG"); handle->otg_mode = mode; + const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[0].otg_signals; + assert(otg_sig); if (mode == USB_OTG_MODE_HOST) { - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_IDDIG_IN_IDX, false); // connected connector is A side - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false); - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); // receiving a valid Vbus from host - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false); // HIGH to force USB host mode + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, otg_sig->iddig, false); // connected connector is A side + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, otg_sig->bvalid, false); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->vbusvalid, false); // receiving a valid Vbus from host + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->avalid, false); if (handle->target == USB_PHY_TARGET_INT) { // Configure pull resistors for host usb_wrap_pull_override_vals_t vals = { @@ -142,10 +144,10 @@ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode) usb_wrap_hal_phy_enable_pull_override(&handle->wrap_hal, &vals); } } else if (mode == USB_OTG_MODE_DEVICE) { - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, false); // connected connector is mini-B side - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false); // HIGH to force USB device mode - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); // receiving a valid Vbus from device - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, false); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->iddig, false); // connected connector is mini-B side + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->bvalid, false); // HIGH to force USB device mode + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, otg_sig->vbusvalid, false); // receiving a valid Vbus from device + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, otg_sig->avalid, false); } return ESP_OK; @@ -185,6 +187,9 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) ESP_ERR_INVALID_ARG, USBPHY_TAG, "wrong target for the action"); esp_err_t ret = ESP_OK; + const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[0].fsls_signals; + assert(fsls_sig); + switch (action) { case USB_PHY_ACTION_HOST_ALLOW_CONN: if (handle->target == USB_PHY_TARGET_INT) { @@ -198,8 +203,8 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) /* Allow for connections on the external PHY by connecting the VP and VM signals to the external PHY. */ - esp_rom_gpio_connect_in_signal(handle->iopins->vp_io_num, USB_EXTPHY_VP_IDX, false); - esp_rom_gpio_connect_in_signal(handle->iopins->vm_io_num, USB_EXTPHY_VM_IDX, false); + esp_rom_gpio_connect_in_signal(handle->iopins->vp_io_num, fsls_sig->rx_dp, false); + esp_rom_gpio_connect_in_signal(handle->iopins->vm_io_num, fsls_sig->rx_dm, false); } break; @@ -224,8 +229,8 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) /* Disable connections on the external PHY by connecting the VP and VM signals to the constant LOW signal. */ - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VP_IDX, false); - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VM_IDX, false); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, fsls_sig->rx_dp, false); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, fsls_sig->rx_dm, false); } break; @@ -272,6 +277,13 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, USBPHY_TAG, "config argument is invalid"); ESP_RETURN_ON_FALSE(config->target < USB_PHY_TARGET_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified PHY argument is invalid"); ESP_RETURN_ON_FALSE(config->controller < USB_PHY_CTRL_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified source argument is invalid"); + ESP_RETURN_ON_FALSE(config->target != USB_PHY_TARGET_EXT || config->ext_io_conf, ESP_ERR_INVALID_ARG, USBPHY_TAG, "ext_io_conf must be provided for ext PHY"); +#if !USB_WRAP_LL_EXT_PHY_SUPPORTED + ESP_RETURN_ON_FALSE(config->target != USB_PHY_TARGET_EXT, ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "Ext PHY not supported on this target"); +#endif +#if !SOC_USB_UTMI_PHY_NUM + ESP_RETURN_ON_FALSE(config->target != USB_PHY_TARGET_UTMI, ESP_ERR_NOT_SUPPORTED, USBPHY_TAG, "UTMI PHY not supported on this target"); +#endif ESP_RETURN_ON_ERROR(usb_phy_install(), USBPHY_TAG, "usb_phy driver installation failed"); esp_err_t ret = ESP_OK; @@ -316,7 +328,8 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r phy_context->iopins = (usb_phy_ext_io_conf_t *) calloc(1, sizeof(usb_phy_ext_io_conf_t)); ESP_GOTO_ON_FALSE(phy_context->iopins, ESP_ERR_NO_MEM, cleanup, USBPHY_TAG, "no mem for storing I/O pins"); memcpy(phy_context->iopins, config->ext_io_conf, sizeof(usb_phy_ext_io_conf_t)); - ESP_ERROR_CHECK(phy_external_iopins_configure(phy_context->iopins)); + const usb_fsls_serial_signal_conn_t *fsls_sig = usb_dwc_info.controllers[0].fsls_signals; + ESP_ERROR_CHECK(phy_external_iopins_configure(phy_context->iopins, fsls_sig)); } if (config->otg_mode != USB_PHY_MODE_DEFAULT) { ESP_ERROR_CHECK(usb_phy_otg_set_mode(*handle_ret, config->otg_mode)); @@ -325,7 +338,8 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r ESP_ERROR_CHECK(usb_phy_otg_dev_set_speed(*handle_ret, config->otg_speed)); } if (config->otg_io_conf && (phy_context->controller == USB_PHY_CTRL_OTG)) { - ESP_ERROR_CHECK(phy_otg_iopins_configure(config->otg_io_conf)); + const usb_otg_signal_conn_t *otg_sig = usb_dwc_info.controllers[0].otg_signals; + ESP_ERROR_CHECK(phy_otg_iopins_configure(config->otg_io_conf, otg_sig)); } return ESP_OK;