From 023eae4f0baa5cec59a51cecb9d6317b6b937417 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 2 Apr 2024 19:55:44 +0800 Subject: [PATCH] feat(hal/usb): Update USB WRAP and USJ LL, add missing ESP32-P4 LL This commit updates updates the LLs of USB WRAP and USJ as follows: - Added missing 'usb_wrap_ll.h' and 'usb_serial_jtag_ll.h' for the ESP32-P4 - Added LL cap macros to distinguish feature differences between the LLs of different targets: - '..._LL_EXT_PHY_SUPPORTED' indicates whether the USB WRAP/USJ supports routing to an external FSLS PHY. - '..._LL_SWAP_PHY_SUPPORTED' indicates whether the USB WRAP/USJ supports swapping between multiple internal FSLS PHYs. - Tidied up some RCC LL functions and their callers. - Added 'usb_wrap_types.h' and 'usb_serial_jtag_types.h' to provide types used in LLs. - Fixed some spelling/naming issues as part of code-spell pre-commit --- .../src/usb_serial_jtag.c | 4 + components/esp_system/port/soc/esp32c3/clk.c | 5 +- components/esp_system/port/soc/esp32s3/clk.c | 3 + components/hal/CMakeLists.txt | 9 +- .../esp32c3/include/hal/usb_serial_jtag_ll.h | 68 +++-- .../esp32c6/include/hal/usb_serial_jtag_ll.h | 58 ++-- .../esp32h2/include/hal/usb_serial_jtag_ll.h | 58 ++-- .../esp32p4/include/hal/usb_serial_jtag_ll.h | 204 +++++++++++++ .../hal/esp32p4/include/hal/usb_wrap_ll.h | 267 ++++++++++++++++++ .../hal/esp32s2/include/hal/usb_wrap_ll.h | 50 ++-- .../esp32s3/include/hal/usb_serial_jtag_ll.h | 56 ++-- .../hal/esp32s3/include/hal/usb_wrap_ll.h | 50 ++-- .../hal/include/hal/usb_serial_jtag_types.h | 35 +++ components/hal/include/hal/usb_wrap_hal.h | 5 +- components/hal/include/hal/usb_wrap_types.h | 53 ++++ components/hal/usb_wrap_hal.c | 48 +++- .../soc/esp32p4/include/soc/usb_wrap_struct.h | 48 +++- components/usb/usb_phy.c | 10 +- 18 files changed, 838 insertions(+), 193 deletions(-) create mode 100644 components/hal/esp32p4/include/hal/usb_serial_jtag_ll.h create mode 100644 components/hal/esp32p4/include/hal/usb_wrap_ll.h create mode 100644 components/hal/include/hal/usb_serial_jtag_types.h create mode 100644 components/hal/include/hal/usb_wrap_types.h diff --git a/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag.c b/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag.c index fe374417e9..e03b4efc76 100644 --- a/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag.c +++ b/components/esp_driver_usb_serial_jtag/src/usb_serial_jtag.c @@ -186,8 +186,12 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE); // Configure PHY +#if USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED usb_serial_jtag_ll_phy_enable_external(false); // Use internal PHY usb_serial_jtag_ll_phy_enable_pad(true); // Enable USB PHY pads +#else // USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED + usb_serial_jtag_ll_phy_set_defaults(); // External PHY not supported. Set default values. +#endif // USB_WRAP_LL_EXT_PHY_SUPPORTED usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT); diff --git a/components/esp_system/port/soc/esp32c3/clk.c b/components/esp_system/port/soc/esp32c3/clk.c index fe35c4e60a..972dc75d1b 100644 --- a/components/esp_system/port/soc/esp32c3/clk.c +++ b/components/esp_system/port/soc/esp32c3/clk.c @@ -246,9 +246,12 @@ __attribute__((weak)) void esp_perip_clk_init(void) SYSTEM_WIFI_CLK_UNUSED_BIT12; #if !CONFIG_USJ_ENABLE_USB_SERIAL_JTAG && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED + /* This function only called on startup thus is thread safe. To avoid build errors/warnings + * declare __DECLARE_RCC_ATOMIC_ENV here. */ + int __DECLARE_RCC_ATOMIC_ENV __attribute__((unused)); // Disable USB-Serial-JTAG clock and it's pad if not used usb_serial_jtag_ll_phy_enable_pad(false); - _usb_serial_jtag_ll_enable_bus_clock(false); + usb_serial_jtag_ll_enable_bus_clock(false); #endif } diff --git a/components/esp_system/port/soc/esp32s3/clk.c b/components/esp_system/port/soc/esp32s3/clk.c index f1c55204c8..4589d5e4f9 100644 --- a/components/esp_system/port/soc/esp32s3/clk.c +++ b/components/esp_system/port/soc/esp32s3/clk.c @@ -263,6 +263,9 @@ __attribute__((weak)) void esp_perip_clk_init(void) SYSTEM_WIFI_CLK_SDIO_HOST_EN; #if !CONFIG_USJ_ENABLE_USB_SERIAL_JTAG && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED + /* This function only called on startup thus is thread safe. To avoid build errors/warnings + * declare __DECLARE_RCC_ATOMIC_ENV here. */ + int __DECLARE_RCC_ATOMIC_ENV __attribute__((unused)); // Disable USB-Serial-JTAG clock and it's pad if not used usb_serial_jtag_ll_phy_enable_pad(false); usb_serial_jtag_ll_enable_bus_clock(false); diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index d6454e3446..7ab06d3728 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -4,7 +4,7 @@ set(srcs "hal_utils.c") set(includes "platform_port/include") # target specific include must be added before the generic one -# becuase of the "include_next" directive used by the efuse_hal.h +# because of the "include_next" directive used by the efuse_hal.h if(NOT ${target} STREQUAL "linux") list(APPEND includes "${target}/include") endif() @@ -257,10 +257,9 @@ if(NOT BOOTLOADER_BUILD) endif() if(CONFIG_SOC_USB_OTG_SUPPORTED) - list(APPEND srcs "usb_dwc_hal.c") - if(NOT ${target} STREQUAL "esp32p4") - list(APPEND srcs "usb_wrap_hal.c") - endif() + list(APPEND srcs + "usb_dwc_hal.c" + "usb_wrap_hal.c") endif() if(${target} STREQUAL "esp32") diff --git a/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h index a706cee908..1183029621 100644 --- a/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h @@ -4,23 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer of the USB-serial-jtag controller - #pragma once + #include #include "esp_attr.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/usb_serial_jtag_struct.h" #include "soc/system_struct.h" +#include "hal/usb_serial_jtag_types.h" -#ifdef __cplusplus -extern "C" { -#endif +/* ----------------------------- Macros & Types ----------------------------- */ -//The in and out endpoints are this long. -#define USB_SERIAL_JTAG_PACKET_SZ_BYTES 64 - -#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) //All interrupt mask +#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) // All interrupts mask // Define USB_SERIAL_JTAG interrupts // Note the hardware has more interrupts, but they're only useful for debugging @@ -34,6 +29,11 @@ typedef enum { USB_SERIAL_JTAG_INTR_EP1_ZERO_PAYLOAD = (1 << 10), } usb_serial_jtag_ll_intr_t; + +#ifdef __cplusplus +extern "C" { +#endif + /* ----------------------------- USJ Peripheral ----------------------------- */ /** @@ -125,7 +125,7 @@ static inline int usb_serial_jtag_ll_read_rxfifo(uint8_t *buf, uint32_t rd_len) * is room in the buffer. * * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return Amount of bytes actually written. May be less than wr_len. */ @@ -182,13 +182,18 @@ static inline void usb_serial_jtag_ll_txfifo_flush(void) /* ---------------------------- USB PHY Control ---------------------------- */ /** - * @brief Sets whether the USJ's FSLS PHY interface routes to an internal or external PHY + * @brief Sets PHY defaults * - * @param enable Enables external PHY, internal otherwise + * Some PHY register fields/features of the USJ are redundant on the ESP32-C3. + * This function those fields are set to the appropriate default values. + * + * @param hw Start address of the USB Wrap registers */ -FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_external(bool enable) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_defaults(void) { - USB_SERIAL_JTAG.conf0.phy_sel = enable; + // External FSLS PHY is not supported + USB_SERIAL_JTAG.conf0.phy_sel = 0; + USB_SERIAL_JTAG.conf0.usb_pad_enable = 1; } /** @@ -231,17 +236,14 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_vref_override(void) /** * @brief Enable override of USB FSLS PHY's pull up/down resistors * - * @param dp_pu Enable D+ pullup - * @param dm_pu Enable D- pullup - * @param dp_pd Enable D+ pulldown - * @param dm_pd Enable D- pulldown + * @param vals Override values to set */ -FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(const usb_serial_jtag_pull_override_vals_t *vals) { - USB_SERIAL_JTAG.conf0.dp_pullup = dp_pu; - USB_SERIAL_JTAG.conf0.dp_pulldown = dp_pd; - USB_SERIAL_JTAG.conf0.dm_pullup = dm_pu; - USB_SERIAL_JTAG.conf0.dm_pulldown = dm_pd; + USB_SERIAL_JTAG.conf0.dp_pullup = vals->dp_pu; + USB_SERIAL_JTAG.conf0.dp_pulldown = vals->dp_pd; + USB_SERIAL_JTAG.conf0.dm_pullup = vals->dm_pu; + USB_SERIAL_JTAG.conf0.dm_pulldown = vals->dm_pd; USB_SERIAL_JTAG.conf0.pad_pull_override = 1; } @@ -286,19 +288,19 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pad(bool enable) /* ----------------------------- RCC Functions ----------------------------- */ /** - * @brief Enable the bus clock for USB Serial_JTAG module - * @param clk_en True if enable the clock of USB Serial_JTAG module + * @brief Enable the bus clock for USJ module + * @param clk_en True if enable the clock of USJ module */ -FORCE_INLINE_ATTR void _usb_serial_jtag_ll_enable_bus_clock(bool clk_en) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_bus_clock(bool clk_en) { SYSTEM.perip_clk_en0.reg_usb_device_clk_en = clk_en; } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_serial_jtag_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_serial_jtag_ll_enable_bus_clock(__VA_ARGS__) +#define usb_serial_jtag_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_serial_jtag_ll_enable_bus_clock(__VA_ARGS__) /** - * @brief Reset the usb serial jtag module + * @brief Reset the USJ module */ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) { @@ -310,15 +312,21 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) #define usb_serial_jtag_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_serial_jtag_ll_reset_register(__VA_ARGS__) /** - * Get the enable status USB Serial_JTAG module + * Get the enable status of the USJ module * - * @return Return true if USB Serial_JTAG module is enabled + * @return Return true if USJ module is enabled */ FORCE_INLINE_ATTR bool usb_serial_jtag_ll_module_is_enabled(void) { return (SYSTEM.perip_clk_en0.reg_usb_device_clk_en && !SYSTEM.perip_rst_en0.reg_usb_device_rst); } +// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way +#define usb_serial_jtag_ll_module_is_enabled(...) ({ \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + usb_serial_jtag_ll_module_is_enabled(__VA_ARGS__); \ +}) + #ifdef __cplusplus } diff --git a/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h index d21821ad35..56b44d0a1a 100644 --- a/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h @@ -4,23 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer of the USB-serial-jtag controller - #pragma once + #include #include "esp_attr.h" #include "soc/pcr_struct.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/usb_serial_jtag_struct.h" +#include "hal/usb_serial_jtag_types.h" -#ifdef __cplusplus -extern "C" { -#endif +/* ----------------------------- Macros & Types ----------------------------- */ -//The in and out endpoints are this long. -#define USB_SERIAL_JTAG_PACKET_SZ_BYTES 64 - -#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) //All interrupt mask +#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) // All interrupts mask // Define USB_SERIAL_JTAG interrupts // Note the hardware has more interrupts, but they're only useful for debugging @@ -34,6 +29,11 @@ typedef enum { USB_SERIAL_JTAG_INTR_EP1_ZERO_PAYLOAD = (1 << 10), } usb_serial_jtag_ll_intr_t; + +#ifdef __cplusplus +extern "C" { +#endif + /* ----------------------------- USJ Peripheral ----------------------------- */ /** @@ -125,7 +125,7 @@ static inline int usb_serial_jtag_ll_read_rxfifo(uint8_t *buf, uint32_t rd_len) * is room in the buffer. * * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return Amount of bytes actually written. May be less than wr_len. */ @@ -195,13 +195,18 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_jtag_bridge(bool enable) /* ---------------------------- USB PHY Control ---------------------------- */ /** - * @brief Sets whether the USJ's FSLS PHY interface routes to an internal or external PHY + * @brief Sets PHY defaults * - * @param enable Enables external PHY, internal otherwise + * Some PHY register fields/features of the USJ are redundant on the ESP32-C6. + * This function those fields are set to the appropriate default values. + * + * @param hw Start address of the USB Wrap registers */ -FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_external(bool enable) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_defaults(void) { - USB_SERIAL_JTAG.conf0.phy_sel = enable; + // External FSLS PHY is not supported + USB_SERIAL_JTAG.conf0.phy_sel = 0; + USB_SERIAL_JTAG.conf0.usb_pad_enable = 1; } /** @@ -244,17 +249,14 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_vref_override(void) /** * @brief Enable override of USB FSLS PHY's pull up/down resistors * - * @param dp_pu Enable D+ pullup - * @param dm_pu Enable D- pullup - * @param dp_pd Enable D+ pulldown - * @param dm_pd Enable D- pulldown + * @param vals Override values to set */ -FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(const usb_serial_jtag_pull_override_vals_t *vals) { - USB_SERIAL_JTAG.conf0.dp_pullup = dp_pu; - USB_SERIAL_JTAG.conf0.dp_pulldown = dp_pd; - USB_SERIAL_JTAG.conf0.dm_pullup = dm_pu; - USB_SERIAL_JTAG.conf0.dm_pulldown = dm_pd; + USB_SERIAL_JTAG.conf0.dp_pullup = vals->dp_pu; + USB_SERIAL_JTAG.conf0.dp_pulldown = vals->dp_pd; + USB_SERIAL_JTAG.conf0.dm_pullup = vals->dm_pu; + USB_SERIAL_JTAG.conf0.dm_pulldown = vals->dm_pd; USB_SERIAL_JTAG.conf0.pad_pull_override = 1; } @@ -299,8 +301,8 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pad(bool enable) /* ----------------------------- RCC Functions ----------------------------- */ /** - * @brief Enable the bus clock for USB Serial_JTAG module - * @param clk_en True if enable the clock of USB Serial_JTAG module + * @brief Enable the bus clock for USJ module + * @param clk_en True if enable the clock of USJ module */ FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_bus_clock(bool clk_en) { @@ -308,7 +310,7 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_bus_clock(bool clk_en) } /** - * @brief Reset the usb serial jtag module + * @brief Reset the USJ module */ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) { @@ -317,9 +319,9 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) } /** - * Get the enable status USB Serial_JTAG module + * Get the enable status of the USJ module * - * @return Return true if USB Serial_JTAG module is enabled + * @return Return true if USJ module is enabled */ FORCE_INLINE_ATTR bool usb_serial_jtag_ll_module_is_enabled(void) { diff --git a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h index ec8a32ea67..bacbf3d3fb 100644 --- a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h @@ -4,23 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer of the USB-serial-jtag controller - #pragma once + #include #include "esp_attr.h" #include "soc/pcr_struct.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/usb_serial_jtag_struct.h" +#include "hal/usb_serial_jtag_types.h" -#ifdef __cplusplus -extern "C" { -#endif +/* ----------------------------- Macros & Types ----------------------------- */ -//The in and out endpoints are this long. -#define USB_SERIAL_JTAG_PACKET_SZ_BYTES 64 - -#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) //All interrupt mask +#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) // All interrupts mask // Define USB_SERIAL_JTAG interrupts // Note the hardware has more interrupts, but they're only useful for debugging @@ -34,6 +29,11 @@ typedef enum { USB_SERIAL_JTAG_INTR_EP1_ZERO_PAYLOAD = (1 << 10), } usb_serial_jtag_ll_intr_t; + +#ifdef __cplusplus +extern "C" { +#endif + /* ----------------------------- USJ Peripheral ----------------------------- */ /** @@ -125,7 +125,7 @@ static inline int usb_serial_jtag_ll_read_rxfifo(uint8_t *buf, uint32_t rd_len) * is room in the buffer. * * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return Amount of bytes actually written. May be less than wr_len. */ @@ -195,13 +195,18 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_jtag_bridge(bool enable) /* ---------------------------- USB PHY Control ---------------------------- */ /** - * @brief Sets whether the USJ's FSLS PHY interface routes to an internal or external PHY + * @brief Sets PHY defaults * - * @param enable Enables external PHY, internal otherwise + * Some PHY register fields/features of the USJ are redundant on the ESP32-H2. + * This function those fields are set to the appropriate default values. + * + * @param hw Start address of the USB Wrap registers */ -FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_external(bool enable) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_defaults(void) { - USB_SERIAL_JTAG.conf0.phy_sel = enable; + // External FSLS PHY is not supported + USB_SERIAL_JTAG.conf0.phy_sel = 0; + USB_SERIAL_JTAG.conf0.usb_pad_enable = 1; } /** @@ -244,17 +249,14 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_vref_override(void) /** * @brief Enable override of USB FSLS PHY's pull up/down resistors * - * @param dp_pu Enable D+ pullup - * @param dm_pu Enable D- pullup - * @param dp_pd Enable D+ pulldown - * @param dm_pd Enable D- pulldown + * @param vals Override values to set */ -FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(const usb_serial_jtag_pull_override_vals_t *vals) { - USB_SERIAL_JTAG.conf0.dp_pullup = dp_pu; - USB_SERIAL_JTAG.conf0.dp_pulldown = dp_pd; - USB_SERIAL_JTAG.conf0.dm_pullup = dm_pu; - USB_SERIAL_JTAG.conf0.dm_pulldown = dm_pd; + USB_SERIAL_JTAG.conf0.dp_pullup = vals->dp_pu; + USB_SERIAL_JTAG.conf0.dp_pulldown = vals->dp_pd; + USB_SERIAL_JTAG.conf0.dm_pullup = vals->dm_pu; + USB_SERIAL_JTAG.conf0.dm_pulldown = vals->dm_pd; USB_SERIAL_JTAG.conf0.pad_pull_override = 1; } @@ -299,8 +301,8 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pad(bool enable) /* ----------------------------- RCC Functions ----------------------------- */ /** - * @brief Enable the bus clock for USB Serial_JTAG module - * @param clk_en True if enable the clock of USB Serial_JTAG module + * @brief Enable the bus clock for USJ module + * @param clk_en True if enable the clock of USJ module */ FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_bus_clock(bool clk_en) { @@ -308,7 +310,7 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_bus_clock(bool clk_en) } /** - * @brief Reset the usb serial jtag module + * @brief Reset the USJ module */ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) { @@ -317,9 +319,9 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) } /** - * Get the enable status USB Serial_JTAG module + * Get the enable status of the USJ module * - * @return Return true if USB Serial_JTAG module is enabled + * @return Return true if USJ module is enabled */ FORCE_INLINE_ATTR bool usb_serial_jtag_ll_module_is_enabled(void) { diff --git a/components/hal/esp32p4/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32p4/include/hal/usb_serial_jtag_ll.h new file mode 100644 index 0000000000..029e363526 --- /dev/null +++ b/components/hal/esp32p4/include/hal/usb_serial_jtag_ll.h @@ -0,0 +1,204 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_attr.h" +#include "soc/lp_system_struct.h" +#include "soc/lp_clkrst_struct.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/usb_serial_jtag_struct.h" +#include "hal/usb_serial_jtag_types.h" + +// This header is temporarily disabled until USJ is supported on the P4 (IDF-7496) +#if SOC_USB_SERIAL_JTAG_SUPPORTED + +/* ----------------------------- Macros & Types ----------------------------- */ + +#define USB_SERIAL_JTAG_LL_SELECT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------- USB PHY Control ---------------------------- */ + +/** + * @brief Sets PHY defaults + * + * Some PHY register fields/features of the USJ are redundant on the ESP32-P4. + * This function those fields are set to the appropriate default values. + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_defaults(void) +{ + // External FSLS PHY is not supported + USB_SERIAL_JTAG.conf0.phy_sel = 0; + USB_SERIAL_JTAG.conf0.usb_pad_enable = 1; +} + +/** + * @brief Select the internal USB FSLS PHY for the USJ + * + * @param phy_idx Selected PHY's index + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_select(unsigned int phy_idx) +{ + // Enable SW control mapping USB_WRAP and USJ to USB FSLS PHY 0 and 1 + LP_SYS.usb_ctrl.sw_hw_usb_phy_sel = 1; + /* + For 'sw_usb_phy_sel': + False - USJ mapped to USB FSLS PHY 0, USB_WRAP mapped to USB FSLS PHY 1 + True - USJ mapped to USB FSLS PHY 1, USB_WRAP mapped to USB FSLS PHY 0 + */ + switch (phy_idx) { + case 0: + LP_SYS.usb_ctrl.sw_usb_phy_sel = false; + case 1: + LP_SYS.usb_ctrl.sw_usb_phy_sel = true; + default: + break; + } +} + +/** + * @brief Enables/disables exchanging of the D+/D- pins USB PHY + * + * @param enable Enables pin exchange, disabled otherwise + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pin_exchg(bool enable) +{ + if (enable) { + USB_SERIAL_JTAG.conf0.exchg_pins = 1; + USB_SERIAL_JTAG.conf0.exchg_pins_override = 1; + } else { + USB_SERIAL_JTAG.conf0.exchg_pins_override = 0; + USB_SERIAL_JTAG.conf0.exchg_pins = 0; + } +} + +/** + * @brief Enables and sets voltage threshold overrides for USB FSLS PHY single-ended inputs + * + * @param vrefh_step High voltage threshold. 0 to 3 indicating 80mV steps from 1.76V to 2V. + * @param vrefl_step Low voltage threshold. 0 to 3 indicating 80mV steps from 0.8V to 1.04V. + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_vref_override(unsigned int vrefh_step, unsigned int vrefl_step) +{ + USB_SERIAL_JTAG.conf0.vrefh = vrefh_step; + USB_SERIAL_JTAG.conf0.vrefl = vrefl_step; + USB_SERIAL_JTAG.conf0.vref_override = 1; +} + +/** + * @brief Disables voltage threshold overrides for USB FSLS PHY single-ended inputs + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_vref_override(void) +{ + USB_SERIAL_JTAG.conf0.vref_override = 0; +} + +/** + * @brief Enable override of USB FSLS PHY's pull up/down resistors + * + * @param vals Override values to set + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(const usb_serial_jtag_pull_override_vals_t *vals) +{ + USB_SERIAL_JTAG.conf0.dp_pullup = vals->dp_pu; + USB_SERIAL_JTAG.conf0.dp_pulldown = vals->dp_pd; + USB_SERIAL_JTAG.conf0.dm_pullup = vals->dm_pu; + USB_SERIAL_JTAG.conf0.dm_pulldown = vals->dm_pd; + USB_SERIAL_JTAG.conf0.pad_pull_override = 1; +} + +/** + * @brief Disable override of USB FSLS PHY pull up/down resistors + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_pull_override(void) +{ + USB_SERIAL_JTAG.conf0.pad_pull_override = 0; +} + +/** + * @brief Sets the strength of the pullup resistor + * + * @param strong True is a ~1.4K pullup, false is a ~2.4K pullup + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_pullup_strength(bool strong) +{ + USB_SERIAL_JTAG.conf0.pullup_value = strong; +} + +/** + * @brief Check if USB FSLS PHY pads are enabled + * + * @return True if enabled, false otherwise + */ +FORCE_INLINE_ATTR bool usb_serial_jtag_ll_phy_is_pad_enabled(void) +{ + return USB_SERIAL_JTAG.conf0.usb_pad_enable; +} + +/** + * @brief Enable the USB FSLS PHY pads + * + * @param enable Whether to enable the USB FSLS PHY pads + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pad(bool enable) +{ + USB_SERIAL_JTAG.conf0.usb_pad_enable = enable; +} + +/* ----------------------------- RCC Functions ----------------------------- */ + +/** + * @brief Enable the bus clock for USJ module + * @param clk_en True if enable the clock of USJ module + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_bus_clock(bool clk_en) +{ + HP_SYS_CLKRST.soc_clk_ctrl2.reg_usb_device_apb_clk_en = clk_en; + // Enable PHY clock (48MHz) for USB FSLS PHY 0 + LP_AON_CLKRST.hp_usb_clkrst_ctrl0.usb_device_48m_clk_en = 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_serial_jtag_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_serial_jtag_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the USJ module + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) +{ + LP_AON_CLKRST.hp_usb_clkrst_ctrl1.rst_en_usb_device = 1; + LP_AON_CLKRST.hp_usb_clkrst_ctrl1.rst_en_usb_device = 0; +} + +// 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_serial_jtag_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_serial_jtag_ll_reset_register(__VA_ARGS__) + +/** + * Get the enable status of the USJ module + * + * @return Return true if USJ module is enabled + */ +FORCE_INLINE_ATTR bool usb_serial_jtag_ll_module_is_enabled(void) +{ + return (HP_SYS_CLKRST.soc_clk_ctrl2.reg_usb_device_apb_clk_en && !LP_AON_CLKRST.hp_usb_clkrst_ctrl1.rst_en_usb_device); +} + +// 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_serial_jtag_ll_module_is_enabled(...) ({ \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + usb_serial_jtag_ll_module_is_enabled(__VA_ARGS__); \ +}) + +#ifdef __cplusplus +} +#endif + +#endif // #if SOC_USB_SERIAL_JTAG_SUPPORTED diff --git a/components/hal/esp32p4/include/hal/usb_wrap_ll.h b/components/hal/esp32p4/include/hal/usb_wrap_ll.h new file mode 100644 index 0000000000..5e6b942366 --- /dev/null +++ b/components/hal/esp32p4/include/hal/usb_wrap_ll.h @@ -0,0 +1,267 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "esp_attr.h" +#include "soc/soc.h" +#include "soc/lp_system_struct.h" +#include "soc/lp_clkrst_struct.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/usb_wrap_struct.h" +#include "hal/usb_wrap_types.h" + +/* ----------------------------- Macros & Types ----------------------------- */ + +#define USB_WRAP_LL_SELECT_PHY_SUPPORTED 1 // Can swap to another internal FSLS PHY + + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------- USB PHY Control ---------------------------- */ + +/** + * @brief Sets default + * + * Some register fields/features of the USB WRAP are redundant on the ESP32-P4. + * This function those fields are set to the appropriate default values. + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_set_defaults(usb_wrap_dev_t *hw) +{ + // External FSLS PHY is not supported + hw->otg_conf.phy_sel = 0; + hw->otg_conf.usb_pad_enable = 1; +} + +/** + * @brief Select the internal USB FSLS PHY for the USB WRAP + * + * @param hw Start address of the USB Wrap registers + * @param phy_idx Selected PHY's index + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_select(usb_wrap_dev_t *hw, unsigned int phy_idx) +{ + // Enable SW control mapping USB_WRAP and USJ to USB FSLS PHY 0 and 1 + LP_SYS.usb_ctrl.sw_hw_usb_phy_sel = 1; + /* + For 'sw_usb_phy_sel': + False - USJ mapped to USB FSLS PHY 0, USB_WRAP mapped to USB FSLS PHY 1 (default) + True - USJ mapped to USB FSLS PHY 1, USB_WRAP mapped to USB FSLS PHY 0 + */ + switch (phy_idx) { + case 0: + LP_SYS.usb_ctrl.sw_usb_phy_sel = true; + case 1: + LP_SYS.usb_ctrl.sw_usb_phy_sel = false; + default: + break; + } +} + +/** + * @brief Enables and sets the override value for the session end signal + * + * @param hw Start address of the USB Wrap registers + * @param sessend Session end override value. True means VBus < 0.2V, false means VBus > 0.8V + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_srp_sessend_override(usb_wrap_dev_t *hw, bool sessend) +{ + hw->otg_conf.srp_sessend_value = sessend; + hw->otg_conf.srp_sessend_override = 1; +} + +/** + * @brief Disable session end override + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_srp_sessend_override(usb_wrap_dev_t *hw) +{ + hw->otg_conf.srp_sessend_override = 0; +} + +/** + * @brief Enables/disables exchanging of the D+/D- pins USB PHY + * + * @param hw Start address of the USB Wrap registers + * @param enable Enables pin exchange, disabled otherwise + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pin_exchg(usb_wrap_dev_t *hw, bool enable) +{ + if (enable) { + hw->otg_conf.exchg_pins = 1; + hw->otg_conf.exchg_pins_override = 1; + } else { + hw->otg_conf.exchg_pins_override = 0; + hw->otg_conf.exchg_pins = 0; + } +} + +/** + * @brief Enables and sets voltage threshold overrides for USB FSLS PHY single-ended inputs + * + * @param hw Start address of the USB Wrap registers + * @param vrefh_step High voltage threshold. 0 to 3 indicating 80mV steps from 1.76V to 2V. + * @param vrefl_step Low voltage threshold. 0 to 3 indicating 80mV steps from 0.8V to 1.04V. + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_vref_override(usb_wrap_dev_t *hw, unsigned int vrefh_step, unsigned int vrefl_step) +{ + hw->otg_conf.vrefh = vrefh_step; + hw->otg_conf.vrefl = vrefl_step; + hw->otg_conf.vref_override = 1; +} + +/** + * @brief Disables voltage threshold overrides for USB FSLS PHY single-ended inputs + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_vref_override(usb_wrap_dev_t *hw) +{ + hw->otg_conf.vref_override = 0; +} + +/** + * @brief Enable override of USB FSLS PHY's pull up/down resistors + * + * @param hw Start address of the USB Wrap registers + * @param vals Override values to set + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pull_override(usb_wrap_dev_t *hw, const usb_wrap_pull_override_vals_t *vals) +{ + hw->otg_conf.dp_pullup = vals->dp_pu; + hw->otg_conf.dp_pulldown = vals->dp_pd; + hw->otg_conf.dm_pullup = vals->dm_pu; + hw->otg_conf.dm_pulldown = vals->dm_pd; + hw->otg_conf.pad_pull_override = 1; +} + +/** + * @brief Disable override of USB FSLS PHY pull up/down resistors + * + * @param hw Start address of the USB Wrap registers + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_pull_override(usb_wrap_dev_t *hw) +{ + hw->otg_conf.pad_pull_override = 0; +} + +/** + * @brief Sets the strength of the pullup resistor + * + * @param hw Start address of the USB Wrap registers + * @param strong True is a ~1.4K pullup, false is a ~2.4K pullup + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_set_pullup_strength(usb_wrap_dev_t *hw, bool strong) +{ + hw->otg_conf.pullup_value = strong; +} + +/** + * @brief Check if USB FSLS PHY pads are enabled + * + * @param hw Start address of the USB Wrap registers + * @return True if enabled, false otherwise + */ +FORCE_INLINE_ATTR bool usb_wrap_ll_phy_is_pad_enabled(usb_wrap_dev_t *hw) +{ + return hw->otg_conf.usb_pad_enable; +} + +/** + * @brief Enable the USB FSLS PHY pads + * + * @param hw Start address of the USB Wrap registers + * @param enable Whether to enable the USB FSLS PHY pads + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pad(usb_wrap_dev_t *hw, bool enable) +{ + hw->otg_conf.usb_pad_enable = enable; +} + +/** + * @brief Set USB FSLS PHY TX output clock edge + * + * @param hw Start address of the USB Wrap registers + * @param clk_neg_edge True if TX output at negedge, posedge otherwise + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_set_tx_edge(usb_wrap_dev_t *hw, bool clk_neg_edge) +{ + hw->otg_conf.phy_tx_edge_sel = clk_neg_edge; +} + +/* ------------------------------ USB PHY Test ------------------------------ */ + +/** + * @brief Enable the USB FSLS PHY's test mode + * + * @param hw Start address of the USB Wrap registers + * @param enable Whether to enable the USB FSLS PHY's test mode + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_test_mode(usb_wrap_dev_t *hw, bool enable) +{ + hw->test_conf.test_enable = enable; +} + +/** + * @brief Set the USB FSLS PHY's signal test values + * + * @param hw Start address of the USB Wrap registers + * @param vals Test values to set + */ +FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, const usb_wrap_test_mode_vals_t *vals) +{ + usb_wrap_test_conf_reg_t test_conf; + test_conf.val = hw->test_conf.val; + + test_conf.test_usb_wrap_oe = vals->tx_enable_n; + test_conf.test_tx_dp = vals->tx_dp; + test_conf.test_tx_dm = vals->tx_dm; + test_conf.test_rx_rcv = vals->rx_rcv; + test_conf.test_rx_dp = vals->rx_dp; + test_conf.test_rx_dm = vals->rx_dm; + + hw->test_conf.val = test_conf.val; +} + +/* ----------------------------- RCC Functions ----------------------------- */ + +/** + * 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) +{ + // 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; + // Enable PHY clock (48MHz) for USB FSLS PHY 1 + LP_AON_CLKRST.hp_usb_clkrst_ctrl0.usb_otg11_48m_clk_en = 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__) + +/** + * @brief Reset the USB Wrap module and USB_DWC_FS controller + */ +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; + LP_AON_CLKRST.hp_usb_clkrst_ctrl1.rst_en_usb_otg11 = 0; +} + +// 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__) + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/usb_wrap_ll.h b/components/hal/esp32s2/include/hal/usb_wrap_ll.h index 879106067c..09c1625e6a 100644 --- a/components/hal/esp32s2/include/hal/usb_wrap_ll.h +++ b/components/hal/esp32s2/include/hal/usb_wrap_ll.h @@ -11,6 +11,12 @@ #include "soc/soc.h" #include "soc/system_reg.h" #include "soc/usb_wrap_struct.h" +#include "hal/usb_wrap_types.h" + +/* ----------------------------- Macros & Types ----------------------------- */ + +#define USB_WRAP_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY + #ifdef __cplusplus extern "C" { @@ -96,17 +102,14 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_vref_override(usb_wrap_dev_t *hw) * @brief Enable override of USB FSLS PHY's pull up/down resistors * * @param hw Start address of the USB Wrap registers - * @param dp_pu Enable D+ pullup - * @param dm_pu Enable D- pullup - * @param dp_pd Enable D+ pulldown - * @param dm_pd Enable D- pulldown + * @param vals Override values to set */ -FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pull_override(usb_wrap_dev_t *hw, bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd) +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pull_override(usb_wrap_dev_t *hw, const usb_wrap_pull_override_vals_t *vals) { - hw->otg_conf.dp_pullup = dp_pu; - hw->otg_conf.dp_pulldown = dp_pd; - hw->otg_conf.dm_pullup = dm_pu; - hw->otg_conf.dm_pulldown = dm_pd; + hw->otg_conf.dp_pullup = vals->dp_pu; + hw->otg_conf.dp_pulldown = vals->dp_pd; + hw->otg_conf.dm_pullup = vals->dm_pu; + hw->otg_conf.dm_pulldown = vals->dm_pd; hw->otg_conf.pad_pull_override = 1; } @@ -181,30 +184,19 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_test_mode(usb_wrap_dev_t *hw, bool * @brief Set the USB FSLS PHY's signal test values * * @param hw Start address of the USB Wrap registers - * @param oen Output Enable (active low) signal - * @param tx_dp TX D+ - * @param tx_dm TX D- - * @param rx_dp RX D+ - * @param rx_dm RX D- - * @param rx_rcv RX RCV + * @param vals Test values to set */ -FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, - bool oen, - bool tx_dp, - bool tx_dm, - bool rx_dp, - bool rx_dm, - bool rx_rcv) +FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, const usb_wrap_test_mode_vals_t *vals) { usb_wrap_test_conf_reg_t test_conf; test_conf.val = hw->test_conf.val; - test_conf.test_usb_wrap_oe = oen; - test_conf.test_tx_dp = tx_dp; - test_conf.test_tx_dm = tx_dm; - test_conf.test_rx_rcv = rx_rcv; - test_conf.test_rx_dp = rx_dp; - test_conf.test_rx_dm = rx_dm; + test_conf.test_usb_wrap_oe = vals->tx_enable_n; + test_conf.test_tx_dp = vals->tx_dp; + test_conf.test_tx_dm = vals->tx_dm; + test_conf.test_rx_rcv = vals->rx_rcv; + test_conf.test_rx_dp = vals->rx_dp; + test_conf.test_rx_dm = vals->rx_dm; hw->test_conf.val = test_conf.val; } @@ -232,7 +224,7 @@ FORCE_INLINE_ATTR void usb_wrap_ll_reset_register(void) REG_SET_FIELD(DPORT_PERIP_RST_EN0_REG, DPORT_USB_RST, 0); } -// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way +// 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__) #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h index ad20f050ad..a3b8c90733 100644 --- a/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h @@ -4,24 +4,20 @@ * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer of the USB-serial-jtag controller - #pragma once + #include #include "esp_attr.h" #include "soc/system_struct.h" #include "soc/rtc_cntl_struct.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/usb_serial_jtag_struct.h" +#include "hal/usb_serial_jtag_types.h" -#ifdef __cplusplus -extern "C" { -#endif +/* ----------------------------- Macros & Types ----------------------------- */ -//The in and out endpoints are this long. -#define USB_SERIAL_JTAG_PACKET_SZ_BYTES 64 - -#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) //All interrupt mask +#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) // All interrupts mask +#define USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY // Define USB_SERIAL_JTAG interrupts // Note the hardware has more interrupts, but they're only useful for debugging @@ -35,6 +31,11 @@ typedef enum { USB_SERIAL_JTAG_INTR_EP1_ZERO_PAYLOAD = (1 << 10), } usb_serial_jtag_intr_t; + +#ifdef __cplusplus +extern "C" { +#endif + /* ----------------------------- USJ Peripheral ----------------------------- */ /** @@ -126,7 +127,7 @@ static inline uint32_t usb_serial_jtag_ll_read_rxfifo(uint8_t *buf, uint32_t rd_ * is room in the buffer. * * @param buf The data buffer. - * @param wr_len The data length needs to be writen. + * @param wr_len The data length needs to be written. * * @return Amount of bytes actually written. May be less than wr_len. */ @@ -253,17 +254,14 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_vref_override(void) /** * @brief Enable override of USB FSLS PHY's pull up/down resistors * - * @param dp_pu Enable D+ pullup - * @param dm_pu Enable D- pullup - * @param dp_pd Enable D+ pulldown - * @param dm_pd Enable D- pulldown + * @param vals Override values to set */ -FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(const usb_serial_jtag_pull_override_vals_t *vals) { - USB_SERIAL_JTAG.conf0.dp_pullup = dp_pu; - USB_SERIAL_JTAG.conf0.dp_pulldown = dp_pd; - USB_SERIAL_JTAG.conf0.dm_pullup = dm_pu; - USB_SERIAL_JTAG.conf0.dm_pulldown = dm_pd; + USB_SERIAL_JTAG.conf0.dp_pullup = vals->dp_pu; + USB_SERIAL_JTAG.conf0.dp_pulldown = vals->dp_pd; + USB_SERIAL_JTAG.conf0.dm_pullup = vals->dm_pu; + USB_SERIAL_JTAG.conf0.dm_pulldown = vals->dm_pd; USB_SERIAL_JTAG.conf0.pad_pull_override = 1; } @@ -318,19 +316,19 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_tx_edge(bool clk_neg_edge) /* ----------------------------- RCC Functions ----------------------------- */ /** - * @brief Enable the bus clock for USB Serial_JTAG module - * @param clk_en True if enable the clock of USB Serial_JTAG module + * @brief Enable the bus clock for USJ module + * @param clk_en True if enable the clock of USJ module */ -FORCE_INLINE_ATTR void _usb_serial_jtag_ll_enable_bus_clock(bool clk_en) +FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_bus_clock(bool clk_en) { SYSTEM.perip_clk_en1.usb_device_clk_en = clk_en; } // SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define usb_serial_jtag_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_serial_jtag_ll_enable_bus_clock(__VA_ARGS__) +#define usb_serial_jtag_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_serial_jtag_ll_enable_bus_clock(__VA_ARGS__) /** - * @brief Reset the usb serial jtag module + * @brief Reset the USJ module */ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) { @@ -342,15 +340,21 @@ FORCE_INLINE_ATTR void usb_serial_jtag_ll_reset_register(void) #define usb_serial_jtag_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_serial_jtag_ll_reset_register(__VA_ARGS__) /** - * Get the enable status USB Serial_JTAG module + * Get the enable status of the USJ module * - * @return Return true if USB Serial_JTAG module is enabled + * @return Return true if USJ module is enabled */ FORCE_INLINE_ATTR bool usb_serial_jtag_ll_module_is_enabled(void) { return (SYSTEM.perip_clk_en1.usb_device_clk_en && !SYSTEM.perip_rst_en1.usb_device_rst); } +// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way +#define usb_serial_jtag_ll_module_is_enabled(...) ({ \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + usb_serial_jtag_ll_module_is_enabled(__VA_ARGS__); \ +}) + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/usb_wrap_ll.h b/components/hal/esp32s3/include/hal/usb_wrap_ll.h index e3dd68a2b9..9ae285d50c 100644 --- a/components/hal/esp32s3/include/hal/usb_wrap_ll.h +++ b/components/hal/esp32s3/include/hal/usb_wrap_ll.h @@ -12,6 +12,12 @@ #include "soc/system_struct.h" #include "soc/usb_wrap_struct.h" #include "soc/rtc_cntl_struct.h" +#include "hal/usb_wrap_types.h" + +/* ----------------------------- Macros & Types ----------------------------- */ + +#define USB_WRAP_LL_EXT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY + #ifdef __cplusplus extern "C" { @@ -105,17 +111,14 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_vref_override(usb_wrap_dev_t *hw) * @brief Enable override of USB FSLS PHY's pull up/down resistors * * @param hw Start address of the USB Wrap registers - * @param dp_pu Enable D+ pullup - * @param dm_pu Enable D- pullup - * @param dp_pd Enable D+ pulldown - * @param dm_pd Enable D- pulldown + * @param vals Override values to set */ -FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pull_override(usb_wrap_dev_t *hw, bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd) +FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pull_override(usb_wrap_dev_t *hw, const usb_wrap_pull_override_vals_t *vals) { - hw->otg_conf.dp_pullup = dp_pu; - hw->otg_conf.dp_pulldown = dp_pd; - hw->otg_conf.dm_pullup = dm_pu; - hw->otg_conf.dm_pulldown = dm_pd; + hw->otg_conf.dp_pullup = vals->dp_pu; + hw->otg_conf.dp_pulldown = vals->dp_pd; + hw->otg_conf.dm_pullup = vals->dm_pu; + hw->otg_conf.dm_pulldown = vals->dm_pd; hw->otg_conf.pad_pull_override = 1; } @@ -190,30 +193,19 @@ FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_test_mode(usb_wrap_dev_t *hw, bool * @brief Set the USB FSLS PHY's signal test values * * @param hw Start address of the USB Wrap registers - * @param oen Output Enable (active low) signal - * @param tx_dp TX D+ - * @param tx_dm TX D- - * @param rx_dp RX D+ - * @param rx_dm RX D- - * @param rx_rcv RX RCV + * @param vals Test values to set */ -FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, - bool oen, - bool tx_dp, - bool tx_dm, - bool rx_dp, - bool rx_dm, - bool rx_rcv) +FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw, const usb_wrap_test_mode_vals_t *vals) { usb_wrap_test_conf_reg_t test_conf; test_conf.val = hw->test_conf.val; - test_conf.test_usb_wrap_oe = oen; - test_conf.test_tx_dp = tx_dp; - test_conf.test_tx_dm = tx_dm; - test_conf.test_rx_rcv = rx_rcv; - test_conf.test_rx_dp = rx_dp; - test_conf.test_rx_dm = rx_dm; + test_conf.test_usb_wrap_oe = vals->tx_enable_n; + test_conf.test_tx_dp = vals->tx_dp; + test_conf.test_tx_dm = vals->tx_dm; + test_conf.test_rx_rcv = vals->rx_rcv; + test_conf.test_rx_dp = vals->rx_dp; + test_conf.test_rx_dm = vals->rx_dm; hw->test_conf.val = test_conf.val; } @@ -241,7 +233,7 @@ FORCE_INLINE_ATTR void usb_wrap_ll_reset_register(void) SYSTEM.perip_rst_en0.usb_rst = 0; } -// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way +// 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__) #ifdef __cplusplus diff --git a/components/hal/include/hal/usb_serial_jtag_types.h b/components/hal/include/hal/usb_serial_jtag_types.h new file mode 100644 index 0000000000..1418ea528b --- /dev/null +++ b/components/hal/include/hal/usb_serial_jtag_types.h @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_USB_SERIAL_JTAG_SUPPORTED + +/** + * @brief USJ test mode values + * + * Specifies the logic values of each of the USB FSLS Serial PHY interface + * signals when in test mode. + */ +typedef struct { + bool dp_pu; /**< D+ pull-up resistor enable/disable */ + bool dm_pu; /**< D- pull-up resistor enable/disable */ + bool dp_pd; /**< D+ pull-down resistor enable/disable */ + bool dm_pd; /**< D- pull-down resistor enable/disable */ +} usb_serial_jtag_pull_override_vals_t; + +#endif // SOC_USB_SERIAL_JTAG_SUPPORTED + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/usb_wrap_hal.h b/components/hal/include/hal/usb_wrap_hal.h index 5e4915fe7b..d484eb89c0 100644 --- a/components/hal/include/hal/usb_wrap_hal.h +++ b/components/hal/include/hal/usb_wrap_hal.h @@ -12,6 +12,7 @@ #include "soc/soc_caps.h" #if SOC_USB_OTG_SUPPORTED #include "soc/usb_wrap_struct.h" +#include "hal/usb_wrap_ll.h" #endif #if SOC_USB_SERIAL_JTAG_SUPPORTED #include "soc/usb_serial_jtag_struct.h" @@ -41,6 +42,7 @@ typedef struct { */ void usb_fsls_phy_hal_init(usb_fsls_phy_hal_context_t *hal); +#if USB_WRAP_LL_EXT_PHY_SUPPORTED /** * @brief Configure internal/external PHY for USB_OTG * @@ -48,6 +50,7 @@ void usb_fsls_phy_hal_init(usb_fsls_phy_hal_context_t *hal); * @param phy_target USB PHY target */ void usb_fsls_phy_hal_otg_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target); +#endif // USB_WRAP_LL_EXT_PHY_SUPPORTED #if SOC_USB_SERIAL_JTAG_SUPPORTED /** @@ -75,7 +78,7 @@ void usb_fsls_phy_hal_int_load_conf_host(usb_fsls_phy_hal_context_t *hal); void usb_fsls_phy_hal_int_load_conf_dev(usb_fsls_phy_hal_context_t *hal, usb_phy_speed_t speed); /** - * @brief Enable/Disable test mode for internal PHY to mimick host-device disconnection + * @brief Enable/Disable test mode for internal PHY to mimic host-device disconnection * * @param hal Context of the HAL layer * @param disconn Whether to disconnect diff --git a/components/hal/include/hal/usb_wrap_types.h b/components/hal/include/hal/usb_wrap_types.h new file mode 100644 index 0000000000..9d3310fb06 --- /dev/null +++ b/components/hal/include/hal/usb_wrap_types.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_USB_OTG_SUPPORTED + +/** + * @brief USB WRAP pull up/down resistor override values + * + * Specifies whether each pull up/down resistor should be enabled/disabled when + * overriding connected USB PHY's pull resistors. + */ +typedef struct { + bool dp_pu; /**< D+ pull-up resistor enable/disable */ + bool dm_pu; /**< D- pull-up resistor enable/disable */ + bool dp_pd; /**< D+ pull-down resistor enable/disable */ + bool dm_pd; /**< D- pull-down resistor enable/disable */ +} usb_wrap_pull_override_vals_t; + +/** + * @brief USB WRAP test mode values + * + * Specifies the logic values of each of the USB FSLS Serial PHY interface + * signals when in test mode. + * + * @note See section "2.2.1.13 FsLsSerialMode" of UTMI+ specification for more + * details of each signal. + */ +typedef struct { + bool tx_enable_n; /**< Active low output enable signal */ + bool tx_dp; /**< Single-ended D+ line driver */ + bool tx_dm; /**< Single-ended D- line driver */ + bool rx_dp; /**< Single-ended D+ signal from the transceiver */ + bool rx_dm; /**< Single-ended D- signal from the transceiver */ + bool rx_rcv; /**< Differential receive data from D+ and D- lines */ +} usb_wrap_test_mode_vals_t; + +#endif // SOC_USB_OTG_SUPPORTED + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/usb_wrap_hal.c b/components/hal/usb_wrap_hal.c index ffa4656634..de805083d8 100644 --- a/components/hal/usb_wrap_hal.c +++ b/components/hal/usb_wrap_hal.c @@ -5,7 +5,6 @@ */ #include "soc/soc_caps.h" -#include "soc/rtc_cntl_struct.h" #if SOC_USB_SERIAL_JTAG_SUPPORTED #include "hal/usb_serial_jtag_ll.h" #endif @@ -18,8 +17,12 @@ void usb_fsls_phy_hal_init(usb_fsls_phy_hal_context_t *hal) #if SOC_USB_SERIAL_JTAG_SUPPORTED hal->jtag_dev = &USB_SERIAL_JTAG; #endif +#if !USB_WRAP_LL_EXT_PHY_SUPPORTED + usb_wrap_ll_phy_set_defaults(hal->wrap_dev); +#endif } +#if USB_WRAP_LL_EXT_PHY_SUPPORTED void usb_fsls_phy_hal_otg_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target) { if (phy_target == USB_PHY_TARGET_EXT) { @@ -29,6 +32,7 @@ void usb_fsls_phy_hal_otg_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t usb_wrap_ll_phy_enable_pad(hal->wrap_dev, true); } } +#endif // USB_WRAP_LL_EXT_PHY_SUPPORTED #if SOC_USB_SERIAL_JTAG_SUPPORTED void usb_fsls_phy_hal_jtag_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target) @@ -45,7 +49,13 @@ void usb_fsls_phy_hal_jtag_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_ void usb_fsls_phy_hal_int_load_conf_host(usb_fsls_phy_hal_context_t *hal) { // HOST - upstream: dp_pd = 1, dm_pd = 1 - usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, false, false, true, true); + usb_wrap_pull_override_vals_t vals = { + .dp_pu = false, + .dm_pu = false, + .dp_pd = true, + .dm_pd = true, + }; + usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, &vals); } void usb_fsls_phy_hal_int_load_conf_dev(usb_fsls_phy_hal_context_t *hal, usb_phy_speed_t speed) @@ -53,10 +63,22 @@ void usb_fsls_phy_hal_int_load_conf_dev(usb_fsls_phy_hal_context_t *hal, usb_phy // DEVICE - downstream if (speed == USB_PHY_SPEED_LOW) { // LS: dm_pu = 1 - usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, false, true, false, false); + usb_wrap_pull_override_vals_t vals = { + .dp_pu = false, + .dm_pu = true, + .dp_pd = false, + .dm_pd = false, + }; + usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, &vals); } else { // FS: dp_pu = 1 - usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, true, false, false, false); + usb_wrap_pull_override_vals_t vals = { + .dp_pu = true, + .dm_pu = false, + .dm_pd = false, + .dp_pd = false, + }; + usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, &vals); } } @@ -64,16 +86,18 @@ void usb_fsls_phy_hal_int_mimick_disconn(usb_fsls_phy_hal_context_t *hal, bool d { if (disconn) { /* - We mimick a disconnect by enabling the internal PHY's test mode, then forcing the output_enable to HIGH. This will: + We mimic a disconnect by enabling the internal PHY's test mode, then forcing the output_enable to HIGH. This will: A HIGH output_enable will cause the received VP and VM to be zero, thus mimicking a disconnection. */ - usb_wrap_ll_phy_test_mode_set_signals(hal->wrap_dev, - true, // OEN - false, // TX D+ - false, // TX D- - false, // RX D+ - false, // RX D- - false); // RX RCv + usb_wrap_test_mode_vals_t vals = { + .tx_enable_n = true, + .tx_dp = false, + .tx_dm = false, + .rx_dp = false, + .rx_dm = false, + .rx_rcv = false, + }; + usb_wrap_ll_phy_test_mode_set_signals(hal->wrap_dev, &vals); usb_wrap_ll_phy_enable_test_mode(hal->wrap_dev, true); } else { usb_wrap_ll_phy_enable_test_mode(hal->wrap_dev, false); diff --git a/components/soc/esp32p4/include/soc/usb_wrap_struct.h b/components/soc/esp32p4/include/soc/usb_wrap_struct.h index 98ec41832b..b5f36b526d 100644 --- a/components/soc/esp32p4/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32p4/include/soc/usb_wrap_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -94,7 +94,10 @@ typedef union { * Force phy clock always on. */ uint32_t phy_clk_force_on:1; - uint32_t reserved_21:1; + /** phy_tx_edge_sel : R/W; bitpos: [21]; default: 0; + * Select PHY tx signal output clock edge.1'b0: negedge;1'b1: posedge. + */ + uint32_t phy_tx_edge_sel:1; /** dfifo_force_pu : R/W; bitpos: [22]; default: 0; * Disable the dfifo to go into low power mode. The data in dfifo will not lost. */ @@ -108,6 +111,44 @@ typedef union { uint32_t val; } usb_wrap_otg_conf_reg_t; +/** Type of test_conf register + * TEST relative configuration registers. + */ +typedef union { + struct { + /** test_enable : R/W; bitpos: [0]; default: 0; + * Enable to test the USB pad. + */ + uint32_t test_enable:1; + /** test_usb_wrap_oe : R/W; bitpos: [1]; default: 0; + * USB pad one in test. + */ + uint32_t test_usb_wrap_oe:1; + /** test_tx_dp : R/W; bitpos: [2]; default: 0; + * USB D+ tx value in test. + */ + uint32_t test_tx_dp:1; + /** test_tx_dm : R/W; bitpos: [3]; default: 0; + * USB D- tx value in test. + */ + uint32_t test_tx_dm:1; + /** test_rx_rcv : RO; bitpos: [4]; default: 0; + * USB differential rx value in test. + */ + uint32_t test_rx_rcv:1; + /** test_rx_dp : RO; bitpos: [5]; default: 0; + * USB D+ rx value in test. + */ + uint32_t test_rx_dp:1; + /** test_rx_dm : RO; bitpos: [6]; default: 0; + * USB D- rx value in test. + */ + uint32_t test_rx_dm:1; + uint32_t reserved_7:25; + }; + uint32_t val; +} usb_wrap_test_conf_reg_t; + /** Type of date register * Date register. */ @@ -124,7 +165,8 @@ typedef union { typedef struct usb_wrap_dev_t { volatile usb_wrap_otg_conf_reg_t otg_conf; - uint32_t reserved_004[254]; + volatile usb_wrap_test_conf_reg_t test_conf; + uint32_t reserved_008[253]; volatile usb_wrap_date_reg_t date; } usb_wrap_dev_t; diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c index eef3a4ffe8..40df183f07 100644 --- a/components/usb/usb_phy.c +++ b/components/usb/usb_phy.c @@ -265,7 +265,9 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r usb_fsls_phy_hal_init(&(phy_context->hal_context)); if (config->controller == USB_PHY_CTRL_OTG) { +#if USB_WRAP_LL_EXT_PHY_SUPPORTED usb_fsls_phy_hal_otg_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); +#endif } #if SOC_USB_SERIAL_JTAG_SUPPORTED else if (config->controller == USB_PHY_CTRL_SERIAL_JTAG) { @@ -334,7 +336,13 @@ esp_err_t usb_del_phy(usb_phy_handle_t handle) p_phy_ctrl_obj->external_phy = NULL; } else { // Clear pullup and pulldown loads on D+ / D-, and disable the pads - usb_wrap_ll_phy_enable_pull_override(handle->hal_context.wrap_dev, false, false, false, false); + usb_wrap_pull_override_vals_t vals = { + .dp_pu = false, + .dm_pu = false, + .dp_pd = false, + .dm_pd = false, + }; + usb_wrap_ll_phy_enable_pull_override(handle->hal_context.wrap_dev, &vals); usb_wrap_ll_phy_enable_pad(handle->hal_context.wrap_dev, false); p_phy_ctrl_obj->internal_phy = NULL; }