From 33591e16b6092998f48f868f8fc4cce2a4e1328f Mon Sep 17 00:00:00 2001 From: hebinglin Date: Thu, 16 Jul 2026 11:59:34 +0800 Subject: [PATCH] change(esp_hw_support): split the sleep_clock_icg APIs into sleep_clock_icg.c --- components/esp_driver_ledc/src/ledc.c | 1 + components/esp_driver_uart/src/uart_wakeup.c | 1 + .../include/esp_private/sleep_clock_icg.h | 33 +++++++ .../esp_hw_support/lowpower/CMakeLists.txt | 4 + .../lowpower/port/esp32c5/sleep_clock_icg.c | 61 +++++++++++++ .../lowpower/port/esp32c6/sleep_clock_icg.c | 70 +++++++++++++++ .../lowpower/port/esp32c61/sleep_clock_icg.c | 66 ++++++++++++++ .../lowpower/port/esp32h2/sleep_clock_icg.c | 61 +++++++++++++ .../lowpower/port/esp32h21/sleep_clock_icg.c | 61 +++++++++++++ .../lowpower/port/esp32h4/sleep_clock_icg.c | 61 +++++++++++++ .../lowpower/port/esp32p4/sleep_clock_icg.c | 88 ++++++++++++++++++ .../lowpower/port/esp32s31/sleep_clock_icg.c | 71 +++++++++++++++ .../modem/port/esp32c6/modem_clock_impl.c | 1 + .../esp_hw_support/port/esp32s31/pmu_sleep.c | 1 - .../port/esp32s31/private_include/pmu_param.h | 3 - components/esp_hw_support/sleep_modes.c | 90 +------------------ 16 files changed, 581 insertions(+), 92 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/sleep_clock_icg.h create mode 100644 components/esp_hw_support/lowpower/port/esp32c5/sleep_clock_icg.c create mode 100644 components/esp_hw_support/lowpower/port/esp32c6/sleep_clock_icg.c create mode 100644 components/esp_hw_support/lowpower/port/esp32c61/sleep_clock_icg.c create mode 100644 components/esp_hw_support/lowpower/port/esp32h2/sleep_clock_icg.c create mode 100644 components/esp_hw_support/lowpower/port/esp32h21/sleep_clock_icg.c create mode 100644 components/esp_hw_support/lowpower/port/esp32h4/sleep_clock_icg.c create mode 100644 components/esp_hw_support/lowpower/port/esp32p4/sleep_clock_icg.c create mode 100644 components/esp_hw_support/lowpower/port/esp32s31/sleep_clock_icg.c diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index 78ebad614e8..50b2c369672 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -18,6 +18,7 @@ #include "hal/ledc_hal.h" #include "driver/ledc.h" #include "esp_private/esp_sleep_internal.h" +#include "esp_private/sleep_clock_icg.h" #include "esp_sleep.h" #include "esp_private/periph_ctrl.h" #include "driver/gpio.h" diff --git a/components/esp_driver_uart/src/uart_wakeup.c b/components/esp_driver_uart/src/uart_wakeup.c index 7cb20a3becf..e7c4c6c3175 100644 --- a/components/esp_driver_uart/src/uart_wakeup.c +++ b/components/esp_driver_uart/src/uart_wakeup.c @@ -15,6 +15,7 @@ #include "driver/uart_wakeup.h" #include "hal/uart_hal.h" #include "esp_private/esp_sleep_internal.h" +#include "esp_private/sleep_clock_icg.h" #include "esp_private/periph_ctrl.h" #include "esp_log.h" diff --git a/components/esp_hw_support/include/esp_private/sleep_clock_icg.h b/components/esp_hw_support/include/esp_private/sleep_clock_icg.h new file mode 100644 index 00000000000..e28c5a6a8ed --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_clock_icg.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "esp_err.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" +#if SOC_PM_SUPPORT_PMU_CLK_ICG +#include "soc/pmu_icg_mapping.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_PM_SUPPORT_PMU_CLK_ICG + +/** + * @brief Convert sleep clock ICG reference counts to PMU ICG flags for HP sleep mode + */ +pmu_sleep_clk_icg_flags_t esp_sleep_clock_get_clk_icg_flags(void); + +#endif /* SOC_PM_SUPPORT_PMU_CLK_ICG */ + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/lowpower/CMakeLists.txt b/components/esp_hw_support/lowpower/CMakeLists.txt index ec281fde598..c125355785d 100644 --- a/components/esp_hw_support/lowpower/CMakeLists.txt +++ b/components/esp_hw_support/lowpower/CMakeLists.txt @@ -40,6 +40,10 @@ if((CONFIG_SOC_PM_SUPPORT_MODEM_PD OR CONFIG_SOC_PM_SUPPORT_TOP_PD) AND CONFIG_S list(APPEND srcs "port/${target}/sleep_clock.c") endif() +if(CONFIG_SOC_PM_SUPPORT_PMU_CLK_ICG) + list(APPEND srcs "port/${target}/sleep_clock_icg.c") +endif() + if(CONFIG_SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY) list(APPEND srcs "port/${target}/sleep_phy.c") endif() diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock_icg.c new file mode 100644 index 00000000000..9f2eba2a12d --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock_icg.c @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint32_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint32_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock_icg.c new file mode 100644 index 00000000000..aad39b318e6 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock_icg.c @@ -0,0 +1,70 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint32_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint32_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } +#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND + /* Starting from C6ECO1 and later versions, when BLE RTC is configured to use + * MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL,the actual slow clock source is the WiFi power clock. + * As all 32 bits of ICG_FUNC are occupied, the ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK + * has been remapped to PMU_ICG_FUNC_ENA_RETENTION.*/ + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_RETENTION); + } +#endif + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock_icg.c new file mode 100644 index 00000000000..54abf12437b --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock_icg.c @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint32_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint32_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } +#if SOC_UART_HP_NUM > 2 + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2); + } +#endif + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock_icg.c new file mode 100644 index 00000000000..9f2eba2a12d --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock_icg.c @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint32_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint32_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock_icg.c new file mode 100644 index 00000000000..9f2eba2a12d --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock_icg.c @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint32_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint32_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock_icg.c new file mode 100644 index 00000000000..9f2eba2a12d --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock_icg.c @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint32_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint32_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock_icg.c new file mode 100644 index 00000000000..f5dcefb4b3e --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock_icg.c @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +ESP_LOG_ATTR_TAG(TAG, "sleep_clock_icg"); + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint32_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint32_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } +#if SOC_UART_HP_NUM > 2 + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2); + } +#endif +#if SOC_UART_HP_NUM > 3 + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART3] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART3); + } +#endif +#if SOC_UART_HP_NUM > 4 + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART4] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART4); + } +#endif + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ +#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !CONFIG_PM_SLEEP_CLK_ICG_ENABLE + static bool warned; + if (!warned) { + warned = true; + ESP_LOGW(TAG, "PM_SLEEP_CLK_ICG_ENABLE is disabled. " + "Clock ungate requests may not be honored during sleep."); + } +#endif + + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock_icg.c b/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock_icg.c new file mode 100644 index 00000000000..62adaa7552f --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock_icg.c @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_private/esp_sleep_internal.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_PM_SLP_IRAM_OPT +#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR +#else +#define SLEEP_CLOCK_ICG_FN_ATTR +#endif + +static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; + +SLEEP_CLOCK_ICG_FN_ATTR uint64_t esp_sleep_clock_get_clk_icg_flags(void) +{ + uint64_t icg_flags = 0; + + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); + } + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); + } +#if SOC_UART_HP_NUM > 2 + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2); + } +#endif +#if SOC_UART_HP_NUM > 3 + if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART3] > 0) { + icg_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART3); + } +#endif + + return icg_flags; +} + +esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) +{ + if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { + return ESP_ERR_INVALID_ARG; + } + + int __attribute__((unused)) refs; + esp_sleep_enter_critical_safe(); + refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \ + : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \ + : s_sleep_clock_icg_refs[clock]; + esp_sleep_exit_critical_safe(); + assert(refs >= 0); + + return ESP_OK; +} diff --git a/components/esp_hw_support/modem/port/esp32c6/modem_clock_impl.c b/components/esp_hw_support/modem/port/esp32c6/modem_clock_impl.c index 08b0d4a8d86..62f4562805f 100644 --- a/components/esp_hw_support/modem/port/esp32c6/modem_clock_impl.c +++ b/components/esp_hw_support/modem/port/esp32c6/modem_clock_impl.c @@ -9,6 +9,7 @@ #include "soc/soc_caps.h" #include "hal/efuse_hal.h" #include "esp_private/esp_sleep_internal.h" +#include "esp_private/sleep_clock_icg.h" #include "modem/modem_clock_impl.h" #include "esp_private/regi2c_ctrl.h" diff --git a/components/esp_hw_support/port/esp32s31/pmu_sleep.c b/components/esp_hw_support/port/esp32s31/pmu_sleep.c index 185e078ddb1..44d8b78724b 100644 --- a/components/esp_hw_support/port/esp32s31/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32s31/pmu_sleep.c @@ -289,7 +289,6 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c const bool icg_func_enabled = (dig->icg_func.clock[0] != 0) || (dig->icg_func.clock[1] != 0); pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), icg_func_enabled); pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func.clock[0], dig->icg_func.clock[1]); - pmu_ll_hp_set_icg_apb(ctx->hal->dev, HP(SLEEP), dig->icg_apb.clock[0], dig->icg_apb.clock[1]); pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel); pmu_ll_hp_set_hold_all_hp_pad (ctx->hal->dev, HP(SLEEP), dig->syscntl.hp_pad_hold_all); pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, HP(SLEEP), dig->syscntl.lp_pad_hold_all); diff --git a/components/esp_hw_support/port/esp32s31/private_include/pmu_param.h b/components/esp_hw_support/port/esp32s31/private_include/pmu_param.h index 8eb608e47ab..32d56edc0c1 100644 --- a/components/esp_hw_support/port/esp32s31/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32s31/private_include/pmu_param.h @@ -328,9 +328,6 @@ typedef struct { struct { uint32_t clock[2]; } icg_func; - struct { - uint32_t clock[2]; - } icg_apb; } pmu_sleep_digital_config_t; diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b9aa758be4e..21d0bee103a 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -18,6 +18,7 @@ #include "esp_private/esp_clk_tree_common.h" #include "esp_private/esp_clk_utils.h" #include "esp_private/esp_sleep_internal.h" +#include "esp_private/sleep_clock_icg.h" #include "esp_private/esp_timer_private.h" #include "esp_private/rtc_clk.h" #include "soc/rtc.h" @@ -281,10 +282,6 @@ typedef struct { int16_t refs; uint16_t reserved; /* reserved for 4 bytes aligned */ } domain[ESP_PD_DOMAIN_MAX]; -#if SOC_PM_SUPPORT_PMU_CLK_ICG - int16_t clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; - pmu_sleep_clk_icg_flags_t sleep_clk_icg_flags; -#endif portMUX_TYPE lock; uint64_t sleep_duration; uint32_t wakeup_triggers; @@ -334,10 +331,6 @@ static sleep_config_t s_config = { .refs = 0 } }, -#if SOC_PM_SUPPORT_PMU_CLK_ICG - .clock_icg_refs[0 ... ESP_SLEEP_CLOCK_MAX - 1] = 0, - .sleep_clk_icg_flags = 0, -#endif .lock = portMUX_INITIALIZER_UNLOCKED, .ccount_ticks_record = 0, .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, @@ -389,9 +382,6 @@ void esp_sleep_overhead_out_time_refresh(void) static uint32_t get_power_down_flags(void); static uint32_t get_sleep_flags(uint32_t pd_flags, bool deepsleep); -#if SOC_PM_SUPPORT_PMU_CLK_ICG -static void sleep_update_clk_icg_flags(void); -#endif #if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP && SOC_RTC_WDT_SUPPORTED static uint32_t get_sleep_rtc_wdt_timeout(uint64_t sleep_duration); static uint32_t calc_sleep_slow_clk_required_cycles(uint32_t timeout, uint32_t rtc_slow_clk_cal_period); @@ -1176,7 +1166,7 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_m #endif pmu_sleep_config_t config; - pmu_sleep_clk_icg_flags_t clk_flags = deep_sleep ? 0 : s_config.sleep_clk_icg_flags; + pmu_sleep_clk_icg_flags_t clk_flags = deep_sleep ? 0 : esp_sleep_clock_get_clk_icg_flags(); pmu_sleep_init(pmu_sleep_config_default(&config, sleep_flags, clk_flags, s_config.sleep_time_adjustment, rtc_clk_slow_src_get(), s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period, deep_sleep), deep_sleep); @@ -1605,11 +1595,6 @@ esp_err_t esp_light_sleep_start(void) uint32_t pd_flags = get_power_down_flags(); // Append flags to indicate the sleep sub-mode and modify the pd_flags according to sub-mode attributes. uint32_t sleep_flags = get_sleep_flags(pd_flags, false); - // Decide which clock can be ungate during sleep -#if SOC_PM_SUPPORT_PMU_CLK_ICG - sleep_update_clk_icg_flags(); -#endif - // Re-calibrate the RTC clock sleep_low_power_clock_calibration(false); @@ -2854,32 +2839,6 @@ int32_t* esp_sleep_sub_mode_dump_config(FILE *stream) { return s_sleep_sub_mode_ref_cnt; } -#if SOC_PM_SUPPORT_PMU_CLK_ICG -esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) -{ -#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !CONFIG_PM_SLEEP_CLK_ICG_ENABLE - static bool warned; - if (!warned) { - warned = true; - ESP_LOGW(TAG, "PM_SLEEP_CLK_ICG_ENABLE is disabled. " - "Clock ungate requests may not be honored during sleep."); - } -#endif - if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) { - return ESP_ERR_INVALID_ARG; - } - - int __attribute__((unused)) refs; - esp_sleep_enter_critical_safe(); - refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_config.clock_icg_refs[clock]++ \ - : (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_config.clock_icg_refs[clock] \ - : s_config.clock_icg_refs[clock]; - esp_sleep_exit_critical_safe(); - assert(refs >= 0); - return ESP_OK; -} -#endif - /** * The modules in the CPU and modem power domains still depend on the top power domain. * To be safe, the CPU and Modem power domains must also be powered off and saved when @@ -3196,51 +3155,6 @@ static SLEEP_FN_ATTR uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsle return sleep_flags; } -#if SOC_PM_SUPPORT_PMU_CLK_ICG -SLEEP_FN_ATTR static void sleep_update_clk_icg_flags(void) -{ - pmu_sleep_clk_icg_flags_t clk_flags = 0; - - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); - } - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0); - } - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0); - } - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); - } -#if SOC_UART_HP_NUM > 2 - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2); - } -#endif -#if SOC_UART_HP_NUM > 3 - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART3] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART3); - } -#endif -#if SOC_UART_HP_NUM > 4 - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART4] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART4); - } -#endif -#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND - /* Starting from C6ECO1 and later versions, when BLE RTC is configured to use - * MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL,the actual slow clock source is the WiFi power clock. - * As all 32 bits of ICG_FUNC are occupied, the ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK - * has been remapped to PMU_ICG_FUNC_ENA_RETENTION.*/ - if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK] > 0) { - clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_RETENTION); - } -#endif - s_config.sleep_clk_icg_flags = clk_flags; -} -#endif /* SOC_PM_SUPPORT_PMU_CLK_ICG */ - #if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP && SOC_RTC_WDT_SUPPORTED /* TODO: PM-609 */ /* Calculate drift cycles of rtc slow clock in long-term working scenarios. */