diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index e6ce90bb83..6bc59c3528 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -225,6 +225,8 @@ static bool uart_module_enable(uart_port_t uart_num) PERIPH_RCC_ATOMIC() { uart_ll_enable_bus_clock(uart_num, true); } + uart_ll_mem_set_low_power_mode(uart_num, UART_LL_MEM_LP_MODE_SHUT_DOWN); + uart_ll_mem_power_by_pmu(uart_num); if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { // Workaround: Set RX signal to high to avoid false RX BRK_DET interrupt raised after register reset if (uart_context[uart_num].rx_io_num == -1) { @@ -270,6 +272,8 @@ static bool uart_module_enable(uart_port_t uart_num) gpio_pullup_en(io_num); #endif } + lp_uart_ll_mem_set_low_power_mode(UART_LL_MEM_LP_MODE_SHUT_DOWN); + lp_uart_ll_mem_power_by_pmu(); PERIPH_RCC_ATOMIC() { lp_uart_ll_enable_bus_clock(TO_LP_UART_NUM(uart_num), true); lp_uart_ll_reset_register(TO_LP_UART_NUM(uart_num)); diff --git a/components/esp_driver_uart/test_apps/.build-test-rules.yml b/components/esp_driver_uart/test_apps/.build-test-rules.yml index 9483fa5bfe..835eacb669 100644 --- a/components/esp_driver_uart/test_apps/.build-test-rules.yml +++ b/components/esp_driver_uart/test_apps/.build-test-rules.yml @@ -3,9 +3,6 @@ components/esp_driver_uart/test_apps/rs485: disable: - if: SOC_UART_SUPPORTED != 1 - - if: IDF_TARGET in ["esp32s31"] - temporary: true - reason: not support yet # TODO: [ESP32S31] IDF-14789 disable_test: - if: IDF_TARGET not in ["esp32", "esp32h2"] temporary: true @@ -20,9 +17,6 @@ components/esp_driver_uart/test_apps/rs485: components/esp_driver_uart/test_apps/uart: disable: - if: SOC_UART_SUPPORTED != 1 - - if: IDF_TARGET in ["esp32s31"] - temporary: true - reason: not support yet # TODO: [ESP32S31] IDF-14789 depends_components: - esp_driver_uart - esp_hal_uart diff --git a/components/esp_driver_uart/test_apps/rs485/README.md b/components/esp_driver_uart/test_apps/rs485/README.md index 44f3780f1d..d76348d52c 100644 --- a/components/esp_driver_uart/test_apps/rs485/README.md +++ b/components/esp_driver_uart/test_apps/rs485/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | diff --git a/components/esp_driver_uart/test_apps/uart/README.md b/components/esp_driver_uart/test_apps/uart/README.md index 44f3780f1d..d76348d52c 100644 --- a/components/esp_driver_uart/test_apps/uart/README.md +++ b/components/esp_driver_uart/test_apps/uart/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | diff --git a/components/esp_driver_uart/test_apps/uart/pytest_uart.py b/components/esp_driver_uart/test_apps/uart/pytest_uart.py index 6b3167c2e2..2c10b7386b 100644 --- a/components/esp_driver_uart/test_apps/uart/pytest_uart.py +++ b/components/esp_driver_uart/test_apps/uart/pytest_uart.py @@ -15,6 +15,7 @@ input_argv = { 'esp32p4': ['uart', 'lp_uart'], 'esp32c5': ['uart', 'lp_uart'], 'esp32c61': ['uart'], + 'esp32s31': ['uart', 'lp_uart'], } @@ -29,7 +30,6 @@ input_argv = { indirect=True, ) @idf_parametrize('target', ['supported_targets'], indirect=['target']) -@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='s31 bringup on this module is not done') def test_uart_single_dev(case_tester) -> None: # type: ignore dut = case_tester.first_dut chip_type = dut.app.target diff --git a/components/esp_hal_uart/esp32/include/hal/uart_ll.h b/components/esp_hal_uart/esp32/include/hal/uart_ll.h index f0ece1f813..d9bfc10dd1 100644 --- a/components/esp_hal_uart/esp32/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -62,6 +62,10 @@ typedef enum { UART_INTR_CMD_CHAR_DET = (0x1 << 18), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, /*!< mem_pd only; no mem_lp_mode stage field (cf. rmt_ll_mem_set_low_power_mode) */ +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -208,6 +212,47 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief UART FIFO/RAM memory power control (HP blocks). + */ +/** + * @brief Force UART FIFO memory powered on for this block (clear mem_pd). + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_pd = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage (ESP32 has no mem_lp_mode; no-op). + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + +/** + * @brief Let UART FIFO memory power follow PMU (clear software mem_pd), same idea as rmt_ll_mem_power_by_pmu. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_pd = 0; +} + +/** + * @brief Force UART FIFO memory to low power (set mem_pd), same idea as rmt_ll_mem_force_low_power. + * + * @note When all three UART instances have mem_pd set, shared memory enters low power (TRM). + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_pd = 1; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32c2/include/hal/uart_ll.h b/components/esp_hal_uart/esp32c2/include/hal/uart_ll.h index ed7f7a72de..551db95263 100644 --- a/components/esp_hal_uart/esp32c2/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32c2/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,6 +64,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -211,6 +215,62 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pd = 0; + hw->mem_conf.force_pu = 1; +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pu = 0; + hw->mem_conf.force_pd = 1; +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pd = 0; + hw->mem_conf.force_pu = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32c3/include/hal/uart_ll.h b/components/esp_hal_uart/esp32c3/include/hal/uart_ll.h index 0371050a9f..de9ac39363 100644 --- a/components/esp_hal_uart/esp32c3/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32c3/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -63,6 +63,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -217,6 +221,62 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pd = 0; + hw->mem_conf.force_pu = 1; +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pu = 0; + hw->mem_conf.force_pd = 1; +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pd = 0; + hw->mem_conf.force_pu = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32c5/include/hal/uart_ll.h b/components/esp_hal_uart/esp32c5/include/hal/uart_ll.h index 83ed7a8192..9ef18b3776 100644 --- a/components/esp_hal_uart/esp32c5/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32c5/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -92,6 +92,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Sync the update to UART core clock domain * @@ -242,6 +246,42 @@ static inline void lp_uart_ll_reset_register(int hw_id) lp_uart_ll_reset_register(__VA_ARGS__); \ } while(0) +/** + * @brief Force LP UART memory block powered on by software. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_power_on(void) +{ + LP_UART.mem_conf.mem_force_pd = 0; + LP_UART.mem_conf.mem_force_pu = 1; +} + +/** + * @brief Force LP UART memory block in low power by software. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_low_power(void) +{ + LP_UART.mem_conf.mem_force_pu = 0; + LP_UART.mem_conf.mem_force_pd = 1; +} + +/** + * @brief Control LP UART memory block by PMU logic. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_power_by_pmu(void) +{ + LP_UART.mem_conf.mem_force_pd = 0; + LP_UART.mem_conf.mem_force_pu = 0; +} + +/** + * @brief Set LP UART memory low power mode in low power stage (no mem_lp_mode field; assert shut-down mode only). + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_set_low_power_mode(uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)mode; +} + /*************************************** General LL functions ******************************************/ /** @@ -428,6 +468,74 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 1; + } else { + lp_uart_ll_mem_force_power_on(); + } +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pu = 0; + hw->mem_conf.mem_force_pd = 1; + } else { + lp_uart_ll_mem_force_low_power(); + } +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 0; + } else { + lp_uart_ll_mem_power_by_pmu(); + } +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32c6/include/hal/uart_ll.h b/components/esp_hal_uart/esp32c6/include/hal/uart_ll.h index b47dd7e86f..55410eae64 100644 --- a/components/esp_hal_uart/esp32c6/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32c6/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -92,6 +92,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Sync the update to UART core clock domain * @@ -242,6 +246,42 @@ static inline void lp_uart_ll_reset_register(int hw_id) lp_uart_ll_reset_register(__VA_ARGS__); \ } while(0) +/** + * @brief Force LP UART memory block powered on by software. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_power_on(void) +{ + LP_UART.mem_conf.mem_force_pd = 0; + LP_UART.mem_conf.mem_force_pu = 1; +} + +/** + * @brief Force LP UART memory block in low power by software. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_low_power(void) +{ + LP_UART.mem_conf.mem_force_pu = 0; + LP_UART.mem_conf.mem_force_pd = 1; +} + +/** + * @brief Control LP UART memory block by PMU logic. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_power_by_pmu(void) +{ + LP_UART.mem_conf.mem_force_pd = 0; + LP_UART.mem_conf.mem_force_pu = 0; +} + +/** + * @brief Set LP UART memory low power mode in low power stage (no mem_lp_mode field; assert shut-down mode only). + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_set_low_power_mode(uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)mode; +} + /*************************************** General LL functions ******************************************/ /** @@ -409,6 +449,74 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 1; + } else { + lp_uart_ll_mem_force_power_on(); + } +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pu = 0; + hw->mem_conf.mem_force_pd = 1; + } else { + lp_uart_ll_mem_force_low_power(); + } +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 0; + } else { + lp_uart_ll_mem_power_by_pmu(); + } +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32c61/include/hal/uart_ll.h b/components/esp_hal_uart/esp32c61/include/hal/uart_ll.h index 0e0821de01..efde9e715f 100644 --- a/components/esp_hal_uart/esp32c61/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32c61/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -94,6 +94,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -255,6 +259,62 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 1; +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pu = 0; + hw->mem_conf.mem_force_pd = 1; +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32h2/include/hal/uart_ll.h b/components/esp_hal_uart/esp32h2/include/hal/uart_ll.h index 2de57a9880..e9d432fc86 100644 --- a/components/esp_hal_uart/esp32h2/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32h2/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -88,6 +88,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -236,6 +240,62 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 1; +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pu = 0; + hw->mem_conf.mem_force_pd = 1; +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32h21/include/hal/uart_ll.h b/components/esp_hal_uart/esp32h21/include/hal/uart_ll.h index 7196d574e7..39b04b0609 100644 --- a/components/esp_hal_uart/esp32h21/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32h21/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -88,6 +88,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -236,6 +240,62 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 1; +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pu = 0; + hw->mem_conf.mem_force_pd = 1; +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32h4/include/hal/uart_ll.h b/components/esp_hal_uart/esp32h4/include/hal/uart_ll.h index 81aa1cf83b..f66278ea2e 100644 --- a/components/esp_hal_uart/esp32h4/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32h4/include/hal/uart_ll.h @@ -86,6 +86,13 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_DEEP_SLEEP, // memory enters deep sleep in low power stage + UART_LL_MEM_LP_MODE_LIGHT_SLEEP, // memory enters light sleep in low power stage + UART_LL_MEM_LP_MODE_SHUT_DOWN, // memory is powered down in low power stage + UART_LL_MEM_LP_MODE_DISABLE, // disable low power stage behavior +} uart_ll_mem_lp_mode_t; + /** * @brief Sync the update to UART core clock domain * @@ -251,6 +258,101 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + switch (uart_num) { + case 0: + PCR.uart0_mem_lp_ctrl.uart0_mem_force_ctrl = 1; + PCR.uart0_mem_lp_ctrl.uart0_mem_lp_en = 0; + break; + case 1: + PCR.uart1_mem_lp_ctrl.uart1_mem_force_ctrl = 1; + PCR.uart1_mem_lp_ctrl.uart1_mem_lp_en = 0; + break; + default: + abort(); + break; + } +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + switch (uart_num) { + case 0: + PCR.uart0_mem_lp_ctrl.uart0_mem_force_ctrl = 1; + PCR.uart0_mem_lp_ctrl.uart0_mem_lp_en = 1; + break; + case 1: + PCR.uart1_mem_lp_ctrl.uart1_mem_force_ctrl = 1; + PCR.uart1_mem_lp_ctrl.uart1_mem_lp_en = 1; + break; + default: + abort(); + break; + } +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + switch (uart_num) { + case 0: + PCR.uart0_mem_lp_ctrl.uart0_mem_force_ctrl = 0; + PCR.uart0_mem_lp_ctrl.uart0_mem_lp_en = 0; + break; + case 1: + PCR.uart1_mem_lp_ctrl.uart1_mem_force_ctrl = 0; + PCR.uart1_mem_lp_ctrl.uart1_mem_lp_en = 0; + break; + default: + abort(); + break; + } +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + switch (uart_num) { + case 0: + PCR.uart0_mem_lp_ctrl.uart0_mem_lp_mode = mode; + break; + case 1: + PCR.uart1_mem_lp_ctrl.uart1_mem_lp_mode = mode; + break; + default: + abort(); + break; + } +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h b/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h index 6eb8ed759d..80cbf54324 100644 --- a/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32p4/include/hal/uart_ll.h @@ -83,6 +83,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, /*!< mem_force_pd/pu only; no mem_lp_mode stage config */ +} uart_ll_mem_lp_mode_t; + /** * @brief Sync the update to UART core clock domain * @@ -240,6 +244,42 @@ static inline void lp_uart_ll_reset_register(int hw_id) lp_uart_ll_reset_register(__VA_ARGS__); \ } while(0) +/** + * @brief Force LP UART memory block powered on by software. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_power_on(void) +{ + LP_UART.mem_conf.mem_force_pd = 0; + LP_UART.mem_conf.mem_force_pu = 1; +} + +/** + * @brief Force LP UART memory block in low power by software. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_low_power(void) +{ + LP_UART.mem_conf.mem_force_pu = 0; + LP_UART.mem_conf.mem_force_pd = 1; +} + +/** + * @brief Control LP UART memory block by PMU logic. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_power_by_pmu(void) +{ + LP_UART.mem_conf.mem_force_pd = 0; + LP_UART.mem_conf.mem_force_pu = 0; +} + +/** + * @brief Set LP UART memory low power mode in low power stage (no mem_lp_mode field; assert shut-down mode only). + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_set_low_power_mode(uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)mode; +} + /*************************************** General LL functions ******************************************/ /** @@ -528,6 +568,66 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param uart_num UART port number for HP UART. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 1; + } else { + lp_uart_ll_mem_force_power_on(); + } +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param uart_num UART port number for HP UART. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pu = 0; + hw->mem_conf.mem_force_pd = 1; + } else { + lp_uart_ll_mem_force_low_power(); + } +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param uart_num UART port number for HP UART. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + if (uart_num != LP_UART_NUM_0) { + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 0; + } else { + lp_uart_ll_mem_power_by_pmu(); + } +} + +/** + * @brief Set UART memory low power mode in low power stage (no mem_lp_mode on ESP32-P4; no-op). + * + * @param uart_num UART port number for HP UART. + * @param mode UART memory low power mode. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32s2/include/hal/uart_ll.h b/components/esp_hal_uart/esp32s2/include/hal/uart_ll.h index 4039252d91..17ad8cefe4 100644 --- a/components/esp_hal_uart/esp32s2/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32s2/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -61,6 +61,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -197,6 +201,62 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pd = 0; + hw->mem_conf.force_pu = 1; +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pu = 0; + hw->mem_conf.force_pd = 1; +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.force_pd = 0; + hw->mem_conf.force_pu = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32s3/include/hal/uart_ll.h b/components/esp_hal_uart/esp32s3/include/hal/uart_ll.h index 193d8d152d..a2e123c7ac 100644 --- a/components/esp_hal_uart/esp32s3/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32s3/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -63,6 +63,10 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_SHUT_DOWN, // force memory low power +} uart_ll_mem_lp_mode_t; + /** * @brief Check if UART is enabled or disabled. * @@ -221,6 +225,62 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 1; +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pu = 0; + hw->mem_conf.mem_force_pd = 1; +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->mem_conf.mem_force_pd = 0; + hw->mem_conf.mem_force_pu = 0; +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param hw Beginning address of the peripheral registers. + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + HAL_ASSERT(mode == UART_LL_MEM_LP_MODE_SHUT_DOWN); + (void)uart_num; +} + /** * @brief Configure the baud-rate. * diff --git a/components/esp_hal_uart/esp32s31/include/hal/uart_ll.h b/components/esp_hal_uart/esp32s31/include/hal/uart_ll.h index 2ea5c72547..091935e7bf 100644 --- a/components/esp_hal_uart/esp32s31/include/hal/uart_ll.h +++ b/components/esp_hal_uart/esp32s31/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,12 +19,12 @@ #include "soc/hp_sys_clkrst_reg.h" #include "soc/lp_uart_reg.h" #include "soc/lp_clkrst_struct.h" +#include "soc/lp_peri_clkrst_struct.h" +#include "soc/lp_peri_clkrst_reg.h" #include "soc/hp_system_struct.h" #include "soc/lp_system_struct.h" #include "soc/hp_alive_sys_struct.h" -// TODO: [ESP32S31] IDF-14789 - // The default fifo depth #define UART_LL_FIFO_DEF_LEN (SOC_UART_FIFO_LEN) #define LP_UART_LL_FIFO_DEF_LEN (SOC_LP_UART_FIFO_LEN) @@ -77,6 +77,13 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +typedef enum { + UART_LL_MEM_LP_MODE_DEEP_SLEEP, // memory enters deep sleep in low power stage + UART_LL_MEM_LP_MODE_LIGHT_SLEEP, // memory enters light sleep in low power stage + UART_LL_MEM_LP_MODE_SHUT_DOWN, // memory is powered down in low power stage + UART_LL_MEM_LP_MODE_DISABLE, // disable low power stage behavior +} uart_ll_mem_lp_mode_t; + /** * @brief Sync the update to UART core clock domain * @@ -99,33 +106,67 @@ FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) */ FORCE_INLINE_ATTR void lp_uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk) { - // TODO: [ESP32S31] IDF-14789 + (void)hw; + switch (LP_PERI_CLKRST.uart_ctrl.lp_uart_clk_sel) { + default: + case 0: + *source_clk = (soc_module_clk_t)LP_UART_SCLK_RC_FAST; + break; + case 1: + *source_clk = (soc_module_clk_t)LP_UART_SCLK_XTAL; + break; + } } /** - * @brief Configure the lp uart baud-rate. + * @brief Set LP UART source clock * + * @param hw Address offset of the LP UART peripheral registers + * @param src_clk Source clock for the LP UART peripheral + */ +static inline void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_clk_src_t src_clk) +{ + (void)hw; + switch (src_clk) { + case LP_UART_SCLK_RC_FAST: + LP_PERI_CLKRST.uart_ctrl.lp_uart_clk_sel = 0; + break; + case LP_UART_SCLK_XTAL: + LP_PERI_CLKRST.uart_ctrl.lp_uart_clk_sel = 1; + break; + default: + // Invalid LP_UART clock source + HAL_ASSERT(false); + } +} + +/** + * @brief Configure the LP UART baud rate (same two-stage division as HP UART). * @param hw Beginning address of the peripheral registers. * @param baud The baud rate to be set. - * @param sclk_freq Frequency of the clock source of UART, in Hz. + * @param sclk_freq Frequency of the LP UART clock source (RC_FAST / XTAL), in Hz. * * @return True if baud-rate set successfully; False if baud-rate requested cannot be achieved */ FORCE_INLINE_ATTR bool lp_uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq) { +#define DIV_UP(a, b) (((a) + (b) - 1) / (b)) if (baud == 0) { return false; } - // No pre-divider for LP UART clock source on the target - uint32_t clk_div = (sclk_freq << 4) / baud; - // The baud rate configuration register is divided into an integer part and a fractional part. - uint32_t clkdiv_int = clk_div >> 4; - if (clkdiv_int > UART_CLKDIV_V) { - return false; // unachievable baud-rate + const uint32_t max_div = UART_CLKDIV_V; + uint32_t sclk_div = DIV_UP(sclk_freq, (uint64_t)max_div * baud); +#undef DIV_UP + + if (sclk_div == 0 || sclk_div > (LP_PERICLKRST_LP_UART_CLK_DIV_NUM_V + 1)) { + return false; } - uint32_t clkdiv_frag = clk_div & 0xf; - hw->clkdiv_sync.clkdiv = clkdiv_int; - hw->clkdiv_sync.clkdiv_frag = clkdiv_frag; + + uint32_t clk_div = ((sclk_freq) << 4) / (baud * sclk_div); + hw->clkdiv_sync.clkdiv = clk_div >> 4; + hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf; + HAL_FORCE_MODIFY_U32_REG_FIELD(LP_PERI_CLKRST.uart_ctrl, lp_uart_clk_div_num, sclk_div - 1); + uart_ll_update(hw); return true; } @@ -138,7 +179,8 @@ FORCE_INLINE_ATTR bool lp_uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, ui */ static inline void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) { - // TODO: [ESP32S31] IDF-14789 + (void)hw_id; + LP_PERI_CLKRST.uart_ctrl.lp_uart_clk_en = enable; } /** @@ -172,8 +214,46 @@ FORCE_INLINE_ATTR void lp_uart_ll_sclk_disable(int hw_id) */ static inline void lp_uart_ll_reset_register(int hw_id) { - // (void)hw_id; - // lp_uart = 0; + (void)hw_id; + LP_PERI_CLKRST.uart_ctrl.lp_uart_rst_en = 1; + LP_PERI_CLKRST.uart_ctrl.lp_uart_rst_en = 0; +} + +/** + * @brief Force LP UART memory block powered on by software (LP AON `uart_mem_lp_ctrl`). + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_power_on(void) +{ + LP_SYS.uart_mem_lp_ctrl.uart_mem_lp_force_ctrl = 1; + LP_SYS.uart_mem_lp_ctrl.uart_mem_lp_en = 0; +} + +/** + * @brief Force LP UART memory block in low power by software. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_force_low_power(void) +{ + LP_SYS.uart_mem_lp_ctrl.uart_mem_lp_force_ctrl = 1; + LP_SYS.uart_mem_lp_ctrl.uart_mem_lp_en = 1; +} + +/** + * @brief Release software force so LP UART memory is controlled by PMU. + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_power_by_pmu(void) +{ + LP_SYS.uart_mem_lp_ctrl.uart_mem_lp_force_ctrl = 0; + LP_SYS.uart_mem_lp_ctrl.uart_mem_lp_en = 0; +} + +/** + * @brief Set LP UART memory low power mode in low power stage. + * + * @param mode UART memory low power mode (see `uart_ll_mem_lp_mode_t`). + */ +FORCE_INLINE_ATTR void lp_uart_ll_mem_set_low_power_mode(uart_ll_mem_lp_mode_t mode) +{ + LP_SYS.uart_mem_lp_ctrl.uart_mem_lp_mode = mode; } /*************************************** General LL functions ******************************************/ @@ -211,6 +291,11 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) uart_apb_en = HP_SYS_CLKRST.uart3_ctrl0.reg_uart3_apb_clk_en; uart_sys_en = HP_SYS_CLKRST.uart3_ctrl0.reg_uart3_sys_clk_en; break; + case 4: + uart_rst_en = LP_PERI_CLKRST.uart_ctrl.lp_uart_rst_en; + uart_apb_en = LP_PERI_CLKRST.uart_ctrl.lp_uart_clk_en; + uart_sys_en = true; + break; default: // Unknown uart port number HAL_ASSERT(false); @@ -407,6 +492,143 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source } } +/** + * @brief Force UART memory block powered on by software. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_power_on(uart_port_t uart_num) +{ + switch (uart_num) { + case 0: + HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_lp_en = 0; + break; + case 1: + HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_lp_en = 0; + break; + case 2: + HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_lp_en = 0; + break; + case 3: + HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_lp_en = 0; + break; + case 4: + lp_uart_ll_mem_force_power_on(); + break; + default: + abort(); + break; + } +} + +/** + * @brief Force UART memory block in low power by software. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_force_low_power(uart_port_t uart_num) +{ + switch (uart_num) { + case 0: + HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_lp_en = 1; + break; + case 1: + HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_lp_en = 1; + break; + case 2: + HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_lp_en = 1; + break; + case 3: + HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_force_ctrl = 1; + HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_lp_en = 1; + break; + case 4: + lp_uart_ll_mem_force_low_power(); + break; + default: + abort(); + break; + } +} + +/** + * @brief Control UART memory block by PMU logic. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_power_by_pmu(uart_port_t uart_num) +{ + switch (uart_num) { + case 0: + HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_force_ctrl = 0; + HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_lp_en = 0; + break; + case 1: + HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_force_ctrl = 0; + HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_lp_en = 0; + break; + case 2: + HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_force_ctrl = 0; + HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_lp_en = 0; + break; + case 3: + HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_force_ctrl = 0; + HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_lp_en = 0; + break; + case 4: + lp_uart_ll_mem_power_by_pmu(); + break; + default: + abort(); + break; + } +} + +/** + * @brief Set UART memory low power mode in low power stage. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param mode UART memory low power mode. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_mem_set_low_power_mode(uart_port_t uart_num, uart_ll_mem_lp_mode_t mode) +{ + switch (uart_num) { + case 0: + HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_lp_mode = mode; + break; + case 1: + HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_lp_mode = mode; + break; + case 2: + HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_lp_mode = mode; + break; + case 3: + HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_lp_mode = mode; + break; + case 4: + lp_uart_ll_mem_set_low_power_mode(mode); + break; + default: + abort(); + break; + } +} + /** * @brief Configure the baud-rate. * @@ -478,7 +700,7 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_fr } else if ((hw) == &UART3) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.uart3_ctrl0, reg_uart3_sclk_div_num) + 1; } else if ((hw) == &LP_UART) { - // sclk_div = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1; + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(LP_PERI_CLKRST.uart_ctrl, lp_uart_clk_div_num) + 1; } return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * sclk_div); } @@ -503,8 +725,8 @@ FORCE_INLINE_ATTR void uart_ll_set_glitch_filt_thrd(uart_dev_t *hw, uint32_t gli sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.uart2_ctrl0, reg_uart2_sclk_div_num) + 1; } else if ((hw) == &UART3) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.uart3_ctrl0, reg_uart3_sclk_div_num) + 1; - // } else if ((hw) == &LP_UART) { - // sclk_div = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1; + } else if ((hw) == &LP_UART) { + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(LP_PERI_CLKRST.uart_ctrl, lp_uart_clk_div_num) + 1; } uint32_t ref_clk_freq = sclk_freq / sclk_div; clk_cycles = ((uint64_t)glitch_filt_thrd * ref_clk_freq + 1000000000 - 1) / 1000000000; // round up to always filter something @@ -1537,7 +1759,7 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_tx_fsm_status(uart_port_t uart_num) * * @param hw Beginning address of the peripheral registers. * @param discard true: Receiver stops storing data into FIFO when data is wrong - * false: Receiver continue storing data into FIFO when data is wrong +* false: Receiver continue storing data into FIFO when data is wrong */ FORCE_INLINE_ATTR void uart_ll_discard_error_data(uart_dev_t *hw, bool discard) { @@ -1545,62 +1767,6 @@ FORCE_INLINE_ATTR void uart_ll_discard_error_data(uart_dev_t *hw, bool discard) uart_ll_update(hw); } -/** - * @brief Set UART memory into low power mode. - * - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - * - * @return UART module FSM status. - */ -FORCE_INLINE_ATTR void uart_ll_memory_lp_enable(uart_port_t uart_num) -{ - switch (uart_num) { - case 0: - HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_lp_en = 1; - break; - case 1: - HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_lp_en = 1; - break; - case 2: - HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_lp_en = 1; - break; - case 3: - HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_lp_en = 1; - break; - default: - abort(); - break; - } -} - -/** - * @brief Set UART memory exit low power mode - * - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - * - * @return UART module FSM status. - */ -FORCE_INLINE_ATTR void uart_ll_memory_lp_disable(uart_port_t uart_num) -{ - switch (uart_num) { - case 0: - HP_SYSTEM.sys_uart0_mem_lp_ctrl.sys_uart0_mem_lp_en = 0; - break; - case 1: - HP_SYSTEM.sys_uart1_mem_lp_ctrl.sys_uart1_mem_lp_en = 0; - break; - case 2: - HP_SYSTEM.sys_uart2_mem_lp_ctrl.sys_uart2_mem_lp_en = 0; - break; - case 3: - HP_SYSTEM.sys_uart3_mem_lp_ctrl.sys_uart3_mem_lp_en = 0; - break; - default: - abort(); - break; - } -} - #ifdef __cplusplus } #endif diff --git a/components/esp_hal_uart/esp32s31/uart_periph.c b/components/esp_hal_uart/esp32s31/uart_periph.c index 0a94208001..9fe03739cf 100644 --- a/components/esp_hal_uart/esp32s31/uart_periph.c +++ b/components/esp_hal_uart/esp32s31/uart_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,8 +8,6 @@ #include "soc/lp_gpio_sig_map.h" #include "soc/uart_reg.h" -// TODO: to be checked IDF-14789 - /* Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc */ @@ -43,7 +41,20 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { .iomux_func = U0CTS_MUX_FUNC, .input = 1, .signal = UART0_CTS_PAD_IN_IDX, - } + }, + [SOC_UART_PERIPH_SIGNAL_DTR] = { + .default_gpio = U0DTR_GPIO_NUM, + .iomux_func = U0DTR_MUX_FUNC, + .input = 0, + .signal = UART0_DTR_PAD_OUT_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_DSR] = { + .default_gpio = U0DSR_GPIO_NUM, + .iomux_func = U0DSR_MUX_FUNC, + .input = 1, + .signal = UART0_DSR_PAD_IN_IDX, + }, }, .irq = ETS_UART0_INTR_SOURCE, }, @@ -78,6 +89,19 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { .input = 1, .signal = UART1_CTS_PAD_IN_IDX, }, + [SOC_UART_PERIPH_SIGNAL_DTR] = { + .default_gpio = U1DTR_GPIO_NUM, + .iomux_func = U1DTR_MUX_FUNC, + .input = 0, + .signal = UART1_DTR_PAD_OUT_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_DSR] = { + .default_gpio = U1DSR_GPIO_NUM, + .iomux_func = U1DSR_MUX_FUNC, + .input = 1, + .signal = UART1_DSR_PAD_IN_IDX, + }, }, .irq = ETS_UART1_INTR_SOURCE, }, @@ -112,6 +136,19 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { .input = 1, .signal = UART2_CTS_PAD_IN_IDX, }, + [SOC_UART_PERIPH_SIGNAL_DTR] = { + .default_gpio = U2DTR_GPIO_NUM, + .iomux_func = U2DTR_MUX_FUNC, + .input = 0, + .signal = UART2_DTR_PAD_OUT_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_DSR] = { + .default_gpio = U2DSR_GPIO_NUM, + .iomux_func = U2DSR_MUX_FUNC, + .input = 1, + .signal = UART2_DSR_PAD_IN_IDX, + }, }, .irq = ETS_UART2_INTR_SOURCE, }, @@ -145,7 +182,130 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { .input = 1, .signal = -1, }, + [SOC_UART_PERIPH_SIGNAL_DTR] = { + .default_gpio = U3DTR_GPIO_NUM, + .iomux_func = U3DTR_MUX_FUNC, + .input = 0, + .signal = UART3_DTR_PAD_OUT_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_DSR] = { + .default_gpio = U3DSR_GPIO_NUM, + .iomux_func = U3DSR_MUX_FUNC, + .input = 1, + .signal = UART3_DSR_PAD_IN_IDX, + }, }, .irq = ETS_UART3_INTR_SOURCE, }, + { + // LP UART0 + .pins = { + [SOC_UART_PERIPH_SIGNAL_TX] = { + .default_gpio = LP_U0TXD_GPIO_NUM, + .iomux_func = LP_U0TXD_MUX_FUNC, + .input = 0, + .signal = LP_UART_TXD_PAD_OUT_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_RX] = { + .default_gpio = LP_U0RXD_GPIO_NUM, + .iomux_func = LP_U0RXD_MUX_FUNC, + .input = 1, + .signal = LP_UART_RXD_PAD_IN_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_RTS] = { + .default_gpio = LP_U0RTS_GPIO_NUM, + .iomux_func = LP_U0RTS_MUX_FUNC, + .input = 0, + .signal = LP_UART_RTSN_PAD_OUT_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_CTS] = { + .default_gpio = LP_U0CTS_GPIO_NUM, + .iomux_func = LP_U0CTS_MUX_FUNC, + .input = 1, + .signal = LP_UART_CTSN_PAD_IN_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_DTR] = { + .default_gpio = LP_U0DTR_GPIO_NUM, + .iomux_func = LP_U0DTR_MUX_FUNC, + .input = 0, + .signal = LP_UART_DTRN_PAD_OUT_IDX, + }, + + [SOC_UART_PERIPH_SIGNAL_DSR] = { + .default_gpio = LP_U0DSR_GPIO_NUM, + .iomux_func = LP_U0DSR_MUX_FUNC, + .input = 1, + .signal = LP_UART_DSRN_PAD_IN_IDX, + }, + }, + .irq = ETS_LP_UART_INTR_SOURCE, + }, +}; + +/** + * UART registers to be saved during sleep retention + * + * Reset TXFIFO and RXFIFO + * UART registers require set the reg_update bit to make the configuration take effect + * + * UART_INT_ENA_REG, UART_CLKDIV_SYNC_REG, UART_RX_FILT_REG, UART_CONF0_SYNC_REG, UART_CONF1_REG, + * UART_HWFC_CONF_SYNC_REG, UART_SLEEP_CONF0_REG, UART_SLEEP_CONF1_REG, UART_SLEEP_CONF2_REG, + * UART_SWFC_CONF0_SYNC_REG, UART_SWFC_CONF1_REG, UART_TXBRK_CONF_SYNC_REG, UART_IDLE_CONF_SYNC_REG, + * UART_RS485_CONF_SYNC_REG, UART_AT_CMD_PRECNT_SYNC_REG, UART_AT_CMD_POSTCNT_SYNC_REG, UART_AT_CMD_GAPTOUT_SYNC_REG, + * UART_AT_CMD_CHAR_SYNC_REG, UART_MEM_CONF_REG, UART_TOUT_CONF_SYNC_REG, UART_CLK_CONF_REG, UART_ID_REG + */ +#define UART_RETENTION_ADDR_MAP_REGS_CNT 22 +#define UART_RETENTION_REGS_BASE(i) UART_INT_ENA_REG(i) +static const uint32_t uart_regs_map[4] = {0x807fff6d, 0x10, 0x0, 0x0}; +#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \ + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_UART_LINK(0x00), \ + UART_RETENTION_REGS_BASE(uart_num), UART_RETENTION_REGS_BASE(uart_num), \ + UART_RETENTION_ADDR_MAP_REGS_CNT, 0, 0, \ + uart_regs_map[0], uart_regs_map[1], \ + uart_regs_map[2], uart_regs_map[3] \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \ + UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \ + UART_REG_UPDATE_REG(uart_num), 0x0, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + } + +static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1); +static const regdma_entries_config_t uart2_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(2); +static const regdma_entries_config_t uart3_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(3); + +const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { + [0] = { + .module = SLEEP_RETENTION_MODULE_UART0, + .regdma_entry_array = uart0_regdma_entries, + .array_size = ARRAY_SIZE(uart0_regdma_entries), + }, + [1] = { + .module = SLEEP_RETENTION_MODULE_UART1, + .regdma_entry_array = uart1_regdma_entries, + .array_size = ARRAY_SIZE(uart1_regdma_entries), + }, + [2] = { + .module = SLEEP_RETENTION_MODULE_UART2, + .regdma_entry_array = uart2_regdma_entries, + .array_size = ARRAY_SIZE(uart2_regdma_entries), + }, + [3] = { + .module = SLEEP_RETENTION_MODULE_UART3, + .regdma_entry_array = uart3_regdma_entries, + .array_size = ARRAY_SIZE(uart3_regdma_entries), + }, }; diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index 0c04b025e0..3860fc25e7 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -761,12 +761,16 @@ config SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX config SOC_UART_NUM int - default 4 + default 5 config SOC_UART_HP_NUM int default 4 +config SOC_UART_LP_NUM + int + default 1 + config SOC_UART_FIFO_LEN int default 128 @@ -791,6 +795,14 @@ config SOC_UART_SUPPORT_WAKEUP_INT bool default y +config SOC_UART_HAS_LP_UART + bool + default y + +config SOC_UART_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN int default 5 @@ -799,6 +811,18 @@ config SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE bool default y +config SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE + bool + default y + +config SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE + bool + default y + +config SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE + bool + default y + config SOC_MODEM_CLOCK_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32s31/include/soc/clk_tree_defs.h b/components/soc/esp32s31/include/soc/clk_tree_defs.h index d309969f6c..3931f15122 100644 --- a/components/soc/esp32s31/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s31/include/soc/clk_tree_defs.h @@ -238,9 +238,23 @@ typedef enum { UART_SCLK_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock is PLL_F80M */ UART_SCLK_RTC = SOC_MOD_CLK_RC_FAST, /*!< UART source clock is RC_FAST */ UART_SCLK_XTAL = SOC_MOD_CLK_XTAL, /*!< UART source clock is XTAL */ - UART_SCLK_DEFAULT = SOC_MOD_CLK_XTAL, /*!< UART source clock default choice is XTAL in fpga env */ + UART_SCLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock default choice is PLL_F80M */ } soc_periph_uart_clk_src_legacy_t; +/** + * @brief Array initializer for all supported clock sources of LP_UART + */ +#define SOC_LP_UART_CLKS {SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} + +/** + * @brief Type of LP_UART clock source + */ +typedef enum { + LP_UART_SCLK_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< LP_UART source clock is FOSC */ + LP_UART_SCLK_XTAL = SOC_MOD_CLK_XTAL, /*!< LP_UART source clock is XTAL */ + LP_UART_SCLK_DEFAULT = SOC_MOD_CLK_RC_FAST, /*!< LP_UART source clock default choice is FOSC */ +} soc_periph_lp_uart_clk_src_t; + //////////////////////////////////////////////////LEDC///////////////////////////////////////////////////////////////// /** diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index 5ee1af60fd..d234ad6717 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -26,7 +26,7 @@ // #define SOC_ADC_SUPPORTED 1 // TODO: [ESP32S31] IDF-14741 // #define SOC_ANA_CMPR_SUPPORTED 1 // TODO: [ESP32S31] IDF-14787 #define SOC_DEDICATED_GPIO_SUPPORTED 1 -#define SOC_UART_SUPPORTED 1 // TODO: [ESP32S31] IDF-14789 +#define SOC_UART_SUPPORTED 1 #define SOC_GDMA_SUPPORTED 1 // #define SOC_UHCI_SUPPORTED 1 // TODO: [ESP32S31] IDF-14791 #define SOC_AHB_GDMA_SUPPORTED 1 @@ -353,20 +353,23 @@ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64) /*-------------------------- UART CAPS ---------------------------------------*/ -// TODO: [ESP32S31] IDF-14789 -#define SOC_UART_NUM (4) +#define SOC_UART_NUM (5) #define SOC_UART_HP_NUM (4) +#define SOC_UART_LP_NUM (1U) #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_LP_UART_FIFO_LEN (16) /*!< The LP UART hardware FIFO length */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ #define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ #define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ -// #define SOC_UART_HAS_LP_UART (1) /*!< Support LP UART */ -// #define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */ +#define SOC_UART_HAS_LP_UART (1) /*!< Support LP UART */ +#define SOC_UART_SUPPORT_SLEEP_RETENTION (1) /*!< Support back up registers before sleep */ #define SOC_UART_WAKEUP_CHARS_SEQ_MAX_LEN 5 #define SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE (1) +#define SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE (1) +#define SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE (1) +#define SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE (1) // /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_MODEM_CLOCK_IS_INDEPENDENT (1) diff --git a/components/soc/esp32s31/include/soc/uart_pins.h b/components/soc/esp32s31/include/soc/uart_pins.h index 13634edba8..5249a70e4c 100644 --- a/components/soc/esp32s31/include/soc/uart_pins.h +++ b/components/soc/esp32s31/include/soc/uart_pins.h @@ -6,35 +6,34 @@ #pragma once -// TODO: to be checked IDF-14789 - /* Specify the GPIO pin number for each UART signal in the IOMUX */ #define U0RXD_GPIO_NUM 59 #define U0TXD_GPIO_NUM 58 #define U0RTS_GPIO_NUM (-1) #define U0CTS_GPIO_NUM (-1) -// DTR -// DSR +#define U0DTR_GPIO_NUM (-1) +#define U0DSR_GPIO_NUM (-1) #define U1RXD_GPIO_NUM (-1) #define U1TXD_GPIO_NUM (-1) #define U1RTS_GPIO_NUM (-1) #define U1CTS_GPIO_NUM (-1) +#define U1DTR_GPIO_NUM (-1) +#define U1DSR_GPIO_NUM (-1) #define U2RXD_GPIO_NUM (-1) #define U2TXD_GPIO_NUM (-1) #define U2RTS_GPIO_NUM (-1) #define U2CTS_GPIO_NUM (-1) +#define U2DTR_GPIO_NUM (-1) +#define U2DSR_GPIO_NUM (-1) #define U3RXD_GPIO_NUM (-1) #define U3TXD_GPIO_NUM (-1) #define U3RTS_GPIO_NUM (-1) #define U3CTS_GPIO_NUM (-1) - -#define U4RXD_GPIO_NUM (-1) -#define U4TXD_GPIO_NUM (-1) -#define U4RTS_GPIO_NUM (-1) -#define U4CTS_GPIO_NUM (-1) +#define U3DTR_GPIO_NUM (-1) +#define U3DSR_GPIO_NUM (-1) #define LP_U0RXD_GPIO_NUM 7 #define LP_U0TXD_GPIO_NUM 6 @@ -49,26 +48,29 @@ #define U0RXD_MUX_FUNC (0) #define U0RTS_MUX_FUNC (-1) #define U0CTS_MUX_FUNC (-1) +#define U0DTR_MUX_FUNC (-1) +#define U0DSR_MUX_FUNC (-1) #define U1TXD_MUX_FUNC (-1) #define U1RXD_MUX_FUNC (-1) #define U1RTS_MUX_FUNC (-1) #define U1CTS_MUX_FUNC (-1) +#define U1DTR_MUX_FUNC (-1) +#define U1DSR_MUX_FUNC (-1) #define U2TXD_MUX_FUNC (-1) #define U2RXD_MUX_FUNC (-1) #define U2RTS_MUX_FUNC (-1) #define U2CTS_MUX_FUNC (-1) +#define U2DTR_MUX_FUNC (-1) +#define U2DSR_MUX_FUNC (-1) #define U3TXD_MUX_FUNC (-1) #define U3RXD_MUX_FUNC (-1) #define U3RTS_MUX_FUNC (-1) #define U3CTS_MUX_FUNC (-1) - -#define U4TXD_MUX_FUNC (-1) -#define U4RXD_MUX_FUNC (-1) -#define U4RTS_MUX_FUNC (-1) -#define U4CTS_MUX_FUNC (-1) +#define U3DTR_MUX_FUNC (-1) +#define U3DSR_MUX_FUNC (-1) #define LP_U0TXD_MUX_FUNC (0) #define LP_U0RXD_MUX_FUNC (0) diff --git a/components/soc/esp32s31/register/soc/uart_struct.h b/components/soc/esp32s31/register/soc/uart_struct.h index 485f55feb5..ce96106ebd 100644 --- a/components/soc/esp32s31/register/soc/uart_struct.h +++ b/components/soc/esp32s31/register/soc/uart_struct.h @@ -1346,7 +1346,6 @@ extern uart_dev_t UART0; extern uart_dev_t UART1; extern uart_dev_t UART2; extern uart_dev_t UART3; -extern uart_dev_t UART4; extern uart_dev_t LP_UART; #ifndef __cplusplus