From 57daf0a8f7fcf7064e14da95a5850cea83ca936f Mon Sep 17 00:00:00 2001 From: hebinglin Date: Tue, 21 Jul 2026 18:05:46 +0800 Subject: [PATCH] feat(esp_hw_support): add backup clk icg support --- components/esp_driver_ledc/src/ledc.c | 1 - components/esp_driver_uart/src/uart_wakeup.c | 1 - .../include/esp_private/esp_pmu.h | 2 +- .../include/esp_private/sleep_clock_icg.h | 57 +++++++- .../lowpower/port/esp32c5/sleep_clock_icg.c | 4 +- .../lowpower/port/esp32c6/sleep_clock_icg.c | 4 +- .../lowpower/port/esp32c61/sleep_clock_icg.c | 4 +- .../lowpower/port/esp32h2/sleep_clock_icg.c | 4 +- .../lowpower/port/esp32h21/sleep_clock_icg.c | 99 +++++++++++++- .../lowpower/port/esp32h4/sleep_clock_icg.c | 104 +++++++++++++- .../lowpower/port/esp32p4/sleep_clock_icg.c | 4 +- .../lowpower/port/esp32s31/sleep_clock_icg.c | 128 +++++++++++++++++- .../esp_hw_support/port/esp32c5/pmu_init.c | 8 +- .../esp_hw_support/port/esp32c6/pmu_init.c | 10 +- .../esp_hw_support/port/esp32c61/pmu_init.c | 8 +- .../esp_hw_support/port/esp32h2/pmu_init.c | 10 +- .../esp_hw_support/port/esp32h21/pmu_init.c | 11 +- .../esp_hw_support/port/esp32h21/pmu_sleep.c | 10 +- .../port/esp32h21/private_include/pmu_param.h | 24 +++- .../esp_hw_support/port/esp32h4/pmu_init.c | 12 +- .../esp_hw_support/port/esp32h4/pmu_sleep.c | 8 +- .../port/esp32h4/pmu_sleep_power.c | 10 +- .../port/esp32h4/private_include/pmu_param.h | 32 ++++- .../esp_hw_support/port/esp32p4/pmu_init.c | 13 +- .../port/esp32p4/pmu_sleep_clock_icg.c | 14 +- .../port/esp32p4/private_include/pmu_param.h | 18 ++- .../esp_hw_support/port/esp32s31/pmu_init.c | 11 +- .../esp_hw_support/port/esp32s31/pmu_sleep.c | 14 +- .../port/esp32s31/private_include/pmu_param.h | 20 ++- components/esp_hw_support/sleep_modes.c | 2 +- components/esp_hw_support/sleep_retention.c | 21 ++- .../esp32h21/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32h21/include/soc/soc_caps.h | 1 + .../esp32h4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32h4/include/soc/soc_caps.h | 1 + .../esp32s31/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32s31/include/soc/soc_caps.h | 1 + 37 files changed, 612 insertions(+), 71 deletions(-) diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index 50b2c369672..78ebad614e8 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -18,7 +18,6 @@ #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 e7c4c6c3175..7cb20a3becf 100644 --- a/components/esp_driver_uart/src/uart_wakeup.c +++ b/components/esp_driver_uart/src/uart_wakeup.c @@ -15,7 +15,6 @@ #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/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index d0aec962be9..3d199798615 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -188,7 +188,7 @@ extern "C" { typedef struct { pmu_hal_context_t *hal; void *mc; -#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA || CONFIG_PM_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT +#if PMU_SLEEP_PRIV_ENABLED void *priv; #endif #if SOC_SPI_FLASH_HAS_DEDICATED_LDO 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 index 71a4d227492..a8fec66ec72 100644 --- a/components/esp_hw_support/include/esp_private/sleep_clock_icg.h +++ b/components/esp_hw_support/include/esp_private/sleep_clock_icg.h @@ -9,8 +9,10 @@ #include #include "esp_err.h" +#include "esp_macros.h" #include "sdkconfig.h" #include "soc/soc_caps.h" +#include "esp_private/esp_pmu.h" #if SOC_PM_SUPPORT_PMU_CLK_ICG #include "soc/pmu_icg_mapping.h" #endif @@ -21,13 +23,64 @@ extern "C" { #if SOC_PM_SUPPORT_PMU_CLK_ICG +#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG + +#include "esp_private/sleep_retention.h" + +/** + * @brief Convert one or more PMU_ICG_FUNC_ENA_xxx cells into an ICG bitmask + */ +#define PMU_CLK_ICG(clock) PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_##clock) +#define PMU_CLK_ICGS_1(a) PMU_CLK_ICG(a) +#define PMU_CLK_ICGS_2(a, b) PMU_CLK_ICG(a) | PMU_CLK_ICG(b) +#define PMU_CLK_ICGS_3(a, b, c) PMU_CLK_ICG(a) | PMU_CLK_ICGS_2(b, c) +#define PMU_CLK_ICGS_4(a, b, c, d) PMU_CLK_ICG(a) | PMU_CLK_ICGS_3(b, c, d) +#define PMU_CLK_ICGS_5(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_1(__VA_ARGS__) +#define PMU_CLK_ICGS_6(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_2(__VA_ARGS__) +#define PMU_CLK_ICGS_7(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_3(__VA_ARGS__) +#define PMU_CLK_ICGS_8(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_4(__VA_ARGS__) +#define PMU_CLK_ICGS_9(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_5(__VA_ARGS__) +#define PMU_CLK_ICGS_10(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_6(__VA_ARGS__) +#define PMU_CLK_ICGS_11(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_7(__VA_ARGS__) +#define PMU_CLK_ICGS_12(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_8(__VA_ARGS__) +#define PMU_CLK_ICGS_13(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_9(__VA_ARGS__) +#define PMU_CLK_ICGS_14(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_10(__VA_ARGS__) + +#define PMU_CLK_ICGS_N(n) PMU_CLK_ICGS_##n +#define PMU_CLK_ICGS_DISPATCH(n, ...) PMU_CLK_ICGS_N(n)(__VA_ARGS__) +#define PMU_CLK_ICGS(...) \ + PMU_CLK_ICGS_DISPATCH(ESP_VA_NARG(__VA_ARGS__), __VA_ARGS__) + +/** + * @brief Program HP backup ICG registers from PMU sleep data + * + * @param data pointer to pmu_sleep_data_t + * @param ctx pointer to pmu_context_t + */ +void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx); + +/** + * @brief Recompute the backup clock ICG mask from the current retention module bitmap + * + * Called whenever the REGDMA retention module bitmap changes (module created/destroyed/ + * attached/detached), so that the backup ICG flags always reflect which peripherals + * currently participate in retention. + * + * @param module_bitmap pointer to current retention module bitmap + */ +void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap); + +#endif /* SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG */ + /** * @brief Convert sleep clock ICG reference counts to PMU ICG flags for HP sleep mode * + * Caller must zero-initialize both outputs; this function only ORs bits into them. + * * @param clk_icg0_flags ICG flags bits[31:0] - * @param clk_icg1_flags ICG flags bits[63:32] (0 if the target only has 32-bit ICG) + * @param clk_icg1_flags ICG flags bits[63:32] (untouched if the target only has 32-bit ICG) */ -void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags); +void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags); #endif /* SOC_PM_SUPPORT_PMU_CLK_ICG */ 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 index e98a79acaef..82822c5cf2a 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock_icg.c @@ -23,7 +23,7 @@ static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); @@ -38,7 +38,7 @@ SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); } - *clk_icg1_flags = 0; + (void)clk_icg1_flags; } esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) 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 index a020ca98609..51e97e6ba36 100644 --- a/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_clock_icg.c @@ -23,7 +23,7 @@ static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); @@ -47,7 +47,7 @@ SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg } #endif - *clk_icg1_flags = 0; + (void)clk_icg1_flags; } esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) 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 index ccd8f0bd665..9fdd2e68129 100644 --- a/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock_icg.c @@ -23,7 +23,7 @@ static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); @@ -43,7 +43,7 @@ SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg } #endif - *clk_icg1_flags = 0; + (void)clk_icg1_flags; } esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) 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 index e98a79acaef..82822c5cf2a 100644 --- a/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32h2/sleep_clock_icg.c @@ -23,7 +23,7 @@ static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); @@ -38,7 +38,7 @@ SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); } - *clk_icg1_flags = 0; + (void)clk_icg1_flags; } esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) 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 index e98a79acaef..f6696a44b5e 100644 --- a/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock_icg.c @@ -12,6 +12,9 @@ #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_clock_icg.h" +#include "esp_private/sleep_retention.h" +#include "hal/pmu_ll.h" +#include "pmu_param.h" #include "sdkconfig.h" #include "soc/soc_caps.h" @@ -23,7 +26,99 @@ static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +#if CONFIG_ESP_CONSOLE_UART +#if CONFIG_ESP_CONSOLE_UART_NUM == 0 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART0 ) +#elif CONFIG_ESP_CONSOLE_UART_NUM == 1 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART1 ) +#else +#define RETENTION_CONSOLE_UART 0 +#endif +#else +#define RETENTION_CONSOLE_UART 0 +#endif + +#define RETENTION_SYS_CLK PMU_CLK_ICGS( HPBUS ) + +#define RETENTION_COMMON PMU_CLK_ICGS( REGDMA, HPCORE ) | RETENTION_SYS_CLK + +static const uint32_t s_retention_module_retention_clocks[SLEEP_RETENTION_MODULE_MAX + 1] = { + [SLEEP_RETENTION_MODULE_NULL] = 0, + [SLEEP_RETENTION_MODULE_CLOCK_SYSTEM] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_SYS_PERIPH] = RETENTION_COMMON | PMU_CLK_ICGS( IOMUX, SYSTIMER, SEC, MSPI ) | RETENTION_CONSOLE_UART, + [SLEEP_RETENTION_MODULE_TG0_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ), + [SLEEP_RETENTION_MODULE_TG1_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ), + [SLEEP_RETENTION_MODULE_TG0_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ), + [SLEEP_RETENTION_MODULE_TG1_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ), + [SLEEP_RETENTION_MODULE_GDMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_GDMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_GDMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_ADC] = RETENTION_COMMON | PMU_CLK_ICG ( SARADC ), + [SLEEP_RETENTION_MODULE_I2C0] = RETENTION_COMMON | PMU_CLK_ICG ( I2C0 ), + [SLEEP_RETENTION_MODULE_I2C1] = RETENTION_COMMON | PMU_CLK_ICG ( I2C0 ), + [SLEEP_RETENTION_MODULE_RMT0] = RETENTION_COMMON | PMU_CLK_ICG ( RMT ), + [SLEEP_RETENTION_MODULE_UART0] = RETENTION_COMMON | PMU_CLK_ICG ( UART0 ), + [SLEEP_RETENTION_MODULE_UART1] = RETENTION_COMMON | PMU_CLK_ICG ( UART1 ), + [SLEEP_RETENTION_MODULE_I2S0] = RETENTION_COMMON | PMU_CLK_ICGS( I2S_RX, I2S_TX ), + [SLEEP_RETENTION_MODULE_ETM0] = RETENTION_COMMON | PMU_CLK_ICG ( SOC_ETM ), + [SLEEP_RETENTION_MODULE_TEMP_SENSOR] = RETENTION_COMMON | PMU_CLK_ICG ( TSENS ), + [SLEEP_RETENTION_MODULE_TWAI0] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI0 ), + [SLEEP_RETENTION_MODULE_PARLIO0] = RETENTION_COMMON | PMU_CLK_ICGS( PARL_TX, PARL_RX ), + [SLEEP_RETENTION_MODULE_GPSPI2] = RETENTION_COMMON | PMU_CLK_ICG ( SPI2 ), + [SLEEP_RETENTION_MODULE_LEDC] = RETENTION_COMMON | PMU_CLK_ICG ( LEDC0 ), + [SLEEP_RETENTION_MODULE_MCPWM0] = RETENTION_COMMON | PMU_CLK_ICG ( PWM ), + [SLEEP_RETENTION_MODULE_SDM0] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_CLOCK_MODEM] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_BLE_MAC] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_BT_BB] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_802154_MAC] = RETENTION_COMMON, +}; + +void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap) +{ + static DRAM_ATTR uint32_t s_retention_icg_flags = 0; + pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv; + if (data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] == NULL) { + data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] = &s_retention_icg_flags; + } + + /* Check if the last word holds bit above MODULE_MAX. */ + assert(!module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1] || + ((31 - __builtin_clz(module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1])) + + ((SLEEP_RETENTION_MODULE_BITMAP_SZ - 1) << 5)) <= SLEEP_RETENTION_MODULE_MAX); + + uint32_t clocks_mask = 0; + sleep_retention_module_t module = 0; + for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) { + for (uint32_t remain = module_bitmap->bitmap[i]; remain; remain &= (remain - 1)) { + module = (__builtin_ctz(remain) + (i << 5)); + clocks_mask |= s_retention_module_retention_clocks[module]; + } + } + +#if !CONFIG_SECURE_ENABLE_TEE + clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_SEC); +#endif + + esp_sleep_enter_critical_safe(); + s_retention_icg_flags = clocks_mask; + esp_sleep_exit_critical_safe(); +} + +FORCE_IRAM_ATTR void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx) +{ + pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data; + if (!data_ctx || !ctx || !data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]) { + return; + } + + uint32_t *flags = (uint32_t *)data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]; + for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) { + pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, *flags); + } +} + +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); @@ -38,7 +133,7 @@ SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); } - *clk_icg1_flags = 0; + (void)clk_icg1_flags; } esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) 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 index e98a79acaef..7460590ca21 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_clock_icg.c @@ -12,6 +12,9 @@ #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_clock_icg.h" +#include "esp_private/sleep_retention.h" +#include "hal/pmu_ll.h" +#include "pmu_param.h" #include "sdkconfig.h" #include "soc/soc_caps.h" @@ -23,7 +26,104 @@ static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +#if CONFIG_ESP_CONSOLE_UART +#if CONFIG_ESP_CONSOLE_UART_NUM == 0 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART0 ) +#elif CONFIG_ESP_CONSOLE_UART_NUM == 1 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART1 ) +#else +#define RETENTION_CONSOLE_UART 0 +#endif +#else +#define RETENTION_CONSOLE_UART 0 +#endif + +#define RETENTION_SYS_CLK PMU_CLK_ICGS( HPBUS ) + +#define RETENTION_COMMON PMU_CLK_ICGS( HPCORE ) | RETENTION_SYS_CLK + +static const uint32_t s_retention_module_retention_clocks[SLEEP_RETENTION_MODULE_MAX + 1] = { + [SLEEP_RETENTION_MODULE_NULL] = 0, + [SLEEP_RETENTION_MODULE_CLOCK_SYSTEM] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_SYS_PERIPH] = RETENTION_COMMON | PMU_CLK_ICGS( IOMUX, SYSTIMER, SEC, MSPI ) | RETENTION_CONSOLE_UART, + [SLEEP_RETENTION_MODULE_TG0_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ), + [SLEEP_RETENTION_MODULE_TG1_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ), + [SLEEP_RETENTION_MODULE_TG0_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ), + [SLEEP_RETENTION_MODULE_TG1_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ), + [SLEEP_RETENTION_MODULE_GDMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_GDMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_GDMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_GDMA_CH3] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_GDMA_CH4] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ), + [SLEEP_RETENTION_MODULE_ADC] = RETENTION_COMMON | PMU_CLK_ICG ( SARADC ), + [SLEEP_RETENTION_MODULE_I2C0] = RETENTION_COMMON | PMU_CLK_ICG ( I2C ), + [SLEEP_RETENTION_MODULE_I2C1] = RETENTION_COMMON | PMU_CLK_ICG ( I2C ), + [SLEEP_RETENTION_MODULE_RMT0] = RETENTION_COMMON | PMU_CLK_ICG ( RMT ), + [SLEEP_RETENTION_MODULE_UART0] = RETENTION_COMMON | PMU_CLK_ICGS( UART0 ), + [SLEEP_RETENTION_MODULE_UART1] = RETENTION_COMMON | PMU_CLK_ICGS( UART1 ), + [SLEEP_RETENTION_MODULE_I2S0] = RETENTION_COMMON | PMU_CLK_ICGS( I2S_RX, I2S_TX ), + [SLEEP_RETENTION_MODULE_ETM0] = RETENTION_COMMON | PMU_CLK_ICG ( SOC_ETM ), + [SLEEP_RETENTION_MODULE_TEMP_SENSOR] = RETENTION_COMMON | PMU_CLK_ICG ( TSENS ), + [SLEEP_RETENTION_MODULE_TWAI0] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI0 ), + [SLEEP_RETENTION_MODULE_PARLIO0] = RETENTION_COMMON | PMU_CLK_ICGS( PARL_TX, PARL_RX ), + [SLEEP_RETENTION_MODULE_GPSPI2] = RETENTION_COMMON | PMU_CLK_ICG ( SPI2 ), + [SLEEP_RETENTION_MODULE_GPSPI3] = RETENTION_COMMON | PMU_CLK_ICGS( SPI2 ), + [SLEEP_RETENTION_MODULE_LEDC] = RETENTION_COMMON | PMU_CLK_ICGS( LEDC0 ), + [SLEEP_RETENTION_MODULE_MCPWM0] = RETENTION_COMMON | PMU_CLK_ICG ( PWM ), + [SLEEP_RETENTION_MODULE_MCPWM1] = RETENTION_COMMON | PMU_CLK_ICG ( PWM ), + [SLEEP_RETENTION_MODULE_SDM0] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_CLOCK_MODEM] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_BLE_MAC] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_BT_BB] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_802154_MAC] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_POWER] = RETENTION_COMMON, +}; + +void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap) +{ + static DRAM_ATTR uint32_t s_retention_icg_flags = 0; + pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv; + if (data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] == NULL) { + data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] = &s_retention_icg_flags; + } + + /* Check if the last word holds bit above MODULE_MAX. */ + assert(!module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1] || + ((31 - __builtin_clz(module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1])) + + ((SLEEP_RETENTION_MODULE_BITMAP_SZ - 1) << 5)) <= SLEEP_RETENTION_MODULE_MAX); + + uint32_t clocks_mask = 0; + sleep_retention_module_t module = 0; + for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) { + for (uint32_t remain = module_bitmap->bitmap[i]; remain; remain &= (remain - 1)) { + module = (__builtin_ctz(remain) + (i << 5)); + clocks_mask |= s_retention_module_retention_clocks[module]; + } + } + +#if !CONFIG_SECURE_ENABLE_TEE + clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_SEC); +#endif + + esp_sleep_enter_critical_safe(); + s_retention_icg_flags = clocks_mask; + esp_sleep_exit_critical_safe(); +} + +FORCE_IRAM_ATTR void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx) +{ + pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data; + if (!data_ctx || !ctx || !data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]) { + return; + } + + uint32_t *flags = (uint32_t *)data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]; + for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) { + pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, *flags); + } +} + +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); @@ -38,7 +138,7 @@ SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1); } - *clk_icg1_flags = 0; + (void)clk_icg1_flags; } esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) 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 index 59f02852f8c..6b91b5aa56b 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_clock_icg.c @@ -26,7 +26,7 @@ ESP_LOG_ATTR_TAG(TAG, "sleep_clock_icg"); static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX); @@ -56,7 +56,7 @@ SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg } #endif - *clk_icg1_flags = 0; + (void)clk_icg1_flags; } esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option) 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 index b04e25cafe1..3950ed0b963 100644 --- a/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock_icg.c +++ b/components/esp_hw_support/lowpower/port/esp32s31/sleep_clock_icg.c @@ -12,6 +12,9 @@ #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_clock_icg.h" +#include "esp_private/sleep_retention.h" +#include "hal/pmu_ll.h" +#include "pmu_param.h" #include "sdkconfig.h" #include "soc/soc_caps.h" @@ -23,7 +26,130 @@ static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX]; -SLEEP_CLOCK_ICG_FN_ATTR void esp_sleep_clock_get_clk_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) +#if CONFIG_ESP_CONSOLE_UART +#if CONFIG_ESP_CONSOLE_UART_NUM == 0 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART0 ) +#elif CONFIG_ESP_CONSOLE_UART_NUM == 1 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART1 ) +#elif CONFIG_ESP_CONSOLE_UART_NUM == 2 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART2 ) +#elif CONFIG_ESP_CONSOLE_UART_NUM == 3 +#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART3 ) +#else +#define RETENTION_CONSOLE_UART 0 +#endif +#else +#define RETENTION_CONSOLE_UART 0 +#endif + +#define RETENTION_SYS_CLK PMU_CLK_ICGS( BUS ) + +#define RETENTION_COMMON PMU_CLK_ICGS( REGDMA, HPCORE0, HPCORE1 ) | RETENTION_SYS_CLK + +static const uint64_t s_retention_module_retention_clocks[SLEEP_RETENTION_MODULE_MAX + 1] = { + [SLEEP_RETENTION_MODULE_NULL] = 0, + [SLEEP_RETENTION_MODULE_CLOCK_SYSTEM] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_SYS_PERIPH] = RETENTION_COMMON | PMU_CLK_ICGS( IOMUX, SYSTIMER, SEC, MSPI_FLASH, MSPI_PSRAM ) | RETENTION_CONSOLE_UART, + [SLEEP_RETENTION_MODULE_TG0_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ), + [SLEEP_RETENTION_MODULE_TG1_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ), + [SLEEP_RETENTION_MODULE_TG0_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ), + [SLEEP_RETENTION_MODULE_TG0_TIMER1] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ), + [SLEEP_RETENTION_MODULE_TG1_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ), + [SLEEP_RETENTION_MODULE_TG1_TIMER1] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ), + [SLEEP_RETENTION_MODULE_AHB_DMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ), + [SLEEP_RETENTION_MODULE_AHB_DMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ), + [SLEEP_RETENTION_MODULE_AHB_DMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ), + [SLEEP_RETENTION_MODULE_AHB_DMA_CH3] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ), + [SLEEP_RETENTION_MODULE_AHB_DMA_CH4] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ), + [SLEEP_RETENTION_MODULE_AXI_DMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( AXI_GDMA ), + [SLEEP_RETENTION_MODULE_AXI_DMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( AXI_GDMA ), + [SLEEP_RETENTION_MODULE_AXI_DMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( AXI_GDMA ), + [SLEEP_RETENTION_MODULE_LP_AHB_DMA_CH0] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_LP_AHB_DMA_CH1] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_UART0] = RETENTION_COMMON | PMU_CLK_ICG ( UART0 ), + [SLEEP_RETENTION_MODULE_UART1] = RETENTION_COMMON | PMU_CLK_ICG ( UART1 ), + [SLEEP_RETENTION_MODULE_UART2] = RETENTION_COMMON | PMU_CLK_ICG ( UART2 ), + [SLEEP_RETENTION_MODULE_UART3] = RETENTION_COMMON | PMU_CLK_ICG ( UART3 ), + [SLEEP_RETENTION_MODULE_RMT0] = RETENTION_COMMON | PMU_CLK_ICG ( RMT ), + [SLEEP_RETENTION_MODULE_I2S0] = RETENTION_COMMON | PMU_CLK_ICG ( I2S0 ), + [SLEEP_RETENTION_MODULE_I2S1] = RETENTION_COMMON | PMU_CLK_ICG ( I2S1 ), + [SLEEP_RETENTION_MODULE_I2C0] = RETENTION_COMMON | PMU_CLK_ICG ( I2C0 ), + [SLEEP_RETENTION_MODULE_I2C1] = RETENTION_COMMON | PMU_CLK_ICG ( I2C1 ), + [SLEEP_RETENTION_MODULE_ETM0] = RETENTION_COMMON | PMU_CLK_ICG ( ETM ), + [SLEEP_RETENTION_MODULE_TWAI0] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI0 ), + [SLEEP_RETENTION_MODULE_TWAI1] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI1 ), + [SLEEP_RETENTION_MODULE_PARLIO0] = RETENTION_COMMON | PMU_CLK_ICG ( PARL ), + [SLEEP_RETENTION_MODULE_GPSPI2] = RETENTION_COMMON | PMU_CLK_ICG ( SPI2 ), + [SLEEP_RETENTION_MODULE_GPSPI3] = RETENTION_COMMON | PMU_CLK_ICG ( SPI3 ), + [SLEEP_RETENTION_MODULE_LEDC0] = RETENTION_COMMON | PMU_CLK_ICG ( LEDC0 ), + [SLEEP_RETENTION_MODULE_LEDC1] = RETENTION_COMMON | PMU_CLK_ICG ( LEDC1 ), + [SLEEP_RETENTION_MODULE_MCPWM0] = RETENTION_COMMON | PMU_CLK_ICG ( PWM0 ), + [SLEEP_RETENTION_MODULE_MCPWM1] = RETENTION_COMMON | PMU_CLK_ICG ( PWM1 ), + [SLEEP_RETENTION_MODULE_MCPWM2] = RETENTION_COMMON | PMU_CLK_ICG ( PWM2 ), + [SLEEP_RETENTION_MODULE_MCPWM3] = RETENTION_COMMON | PMU_CLK_ICG ( PWM3 ), + [SLEEP_RETENTION_MODULE_SDM0] = RETENTION_COMMON | PMU_CLK_ICG ( SDMMC ), + [SLEEP_RETENTION_MODULE_LCDCAM] = RETENTION_COMMON | PMU_CLK_ICG ( LCDCAM ), + [SLEEP_RETENTION_MODULE_JPEG] = RETENTION_COMMON | PMU_CLK_ICG ( JPEG ), + [SLEEP_RETENTION_MODULE_DMA2D] = RETENTION_COMMON | PMU_CLK_ICG ( 2DDMA ), + [SLEEP_RETENTION_MODULE_PPA] = RETENTION_COMMON | PMU_CLK_ICG ( PPA ), + [SLEEP_RETENTION_MODULE_WIFI_MAC] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_WIFI_BB] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_BLE_MAC] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_BT_BB] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_802154_MAC] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_CLOCK_MODEM] = RETENTION_COMMON, + [SLEEP_RETENTION_MODULE_MODEM_PHY] = RETENTION_COMMON, +}; + +void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap) +{ + static DRAM_ATTR uint32_t s_retention_icg_flags[2] = {0, 0}; + pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv; + if (data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] == NULL) { + data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] = s_retention_icg_flags; + } + + /* Check if the last word holds bit above MODULE_MAX. */ + assert(!module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1] || + ((31 - __builtin_clz(module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1])) + + ((SLEEP_RETENTION_MODULE_BITMAP_SZ - 1) << 5)) <= SLEEP_RETENTION_MODULE_MAX); + + uint64_t clocks_mask = 0; + sleep_retention_module_t module = 0; + for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) { + for (uint32_t remain = module_bitmap->bitmap[i]; remain; remain &= (remain - 1)) { + module = (__builtin_ctz(remain) + (i << 5)); + clocks_mask |= s_retention_module_retention_clocks[module]; + } + } + +#if !CONFIG_SPIRAM + clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_MSPI_PSRAM); +#endif +#if !CONFIG_SECURE_ENABLE_TEE + clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_SEC); +#endif + + esp_sleep_enter_critical_safe(); + s_retention_icg_flags[0] = PMU_SLEEP_CLK_ICG_FUNC_LO(clocks_mask); + s_retention_icg_flags[1] = PMU_SLEEP_CLK_ICG_FUNC_HI(clocks_mask); + esp_sleep_exit_critical_safe(); +} + +FORCE_IRAM_ATTR void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx) +{ + pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data; + if (!data_ctx || !ctx || !data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]) { + return; + } + + uint32_t *flags = (uint32_t *)data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]; + for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) { + pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, flags[0], flags[1]); + } +} + +SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags) { if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) { *clk_icg0_flags |= PMU_SLEEP_CLK_ICG_FUNC_LO(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX)); diff --git a/components/esp_hw_support/port/esp32c5/pmu_init.c b/components/esp_hw_support/port/esp32c5/pmu_init.c index 7bcd277f006..0d76e498e19 100644 --- a/components/esp_hw_support/port/esp32c5/pmu_init.c +++ b/components/esp_hw_support/port/esp32c5/pmu_init.c @@ -44,7 +44,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; + static DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = NULL, +#endif + }; return &pmu_context; } diff --git a/components/esp_hw_support/port/esp32c6/pmu_init.c b/components/esp_hw_support/port/esp32c6/pmu_init.c index 7b254d30028..19bde3a633a 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_init.c +++ b/components/esp_hw_support/port/esp32c6/pmu_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -45,7 +45,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; + static DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = NULL, +#endif + }; return &pmu_context; } diff --git a/components/esp_hw_support/port/esp32c61/pmu_init.c b/components/esp_hw_support/port/esp32c61/pmu_init.c index 26f8ade0f1f..08ec9d352a0 100644 --- a/components/esp_hw_support/port/esp32c61/pmu_init.c +++ b/components/esp_hw_support/port/esp32c61/pmu_init.c @@ -45,7 +45,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; + static DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = NULL, +#endif + }; return &pmu_context; } diff --git a/components/esp_hw_support/port/esp32h2/pmu_init.c b/components/esp_hw_support/port/esp32h2/pmu_init.c index 34502e93c36..c4042a6e7fe 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_init.c +++ b/components/esp_hw_support/port/esp32h2/pmu_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,7 +40,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; + static DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = NULL, +#endif + }; return &pmu_context; } diff --git a/components/esp_hw_support/port/esp32h21/pmu_init.c b/components/esp_hw_support/port/esp32h21/pmu_init.c index 4642a2b3e2b..4108e24cd05 100644 --- a/components/esp_hw_support/port/esp32h21/pmu_init.c +++ b/components/esp_hw_support/port/esp32h21/pmu_init.c @@ -40,7 +40,16 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; +#if PMU_SLEEP_PRIV_ENABLED + static DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 }; +#endif + static DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = &pmu_data, +#endif + }; return &pmu_context; } diff --git a/components/esp_hw_support/port/esp32h21/pmu_sleep.c b/components/esp_hw_support/port/esp32h21/pmu_sleep.c index eea58b5be06..b3933eca5da 100644 --- a/components/esp_hw_support/port/esp32h21/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h21/pmu_sleep.c @@ -16,6 +16,7 @@ #include "soc/pmu_struct.h" #include "hal/lp_aon_hal.h" #include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" #include "pmu_param.h" #include "hal/efuse_ll.h" #include "hal/efuse_hal.h" @@ -150,7 +151,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, p config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args); if (dslp) { - pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags); + pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags); config->digital = digital_default; pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags); @@ -206,11 +207,12 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig, bool dslp) { - pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0)); - pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func); + pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->sleep_icg_func != 0)); + pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->sleep_icg_func); pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt); if (!dslp) { - pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel); + pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel); + pmu_sleep_retention_clock_icg_config(ctx->priv, ctx); } } diff --git a/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h index be6a2c2285f..456a135068a 100644 --- a/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h @@ -9,6 +9,8 @@ #include #include #include +#include "sdkconfig.h" +#include "soc/soc_caps.h" #include "soc/pmu_struct.h" #include "hal/pmu_hal.h" @@ -54,6 +56,7 @@ extern "C" { uint32_t get_act_hp_drvb(void); uint32_t get_act_lp_dbias(void); + typedef struct { pmu_hp_dig_power_reg_t dig_power; pmu_hp_clk_power_reg_t clk_power; @@ -108,7 +111,20 @@ typedef struct { const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode); +/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */ +#define PMU_SLEEP_PRIV_ENABLED (SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG) +#if PMU_SLEEP_PRIV_ENABLED +enum { +#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG + PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK, +#endif + PMU_SLEEP_PRIV_MAX, +}; +typedef struct { + void *func[PMU_SLEEP_PRIV_MAX]; +} pmu_sleep_data_t; +#endif /* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/ typedef union { @@ -348,7 +364,7 @@ typedef struct { typedef struct { pmu_hp_sys_cntl_reg_t syscntl; - uint32_t icg_func; + uint32_t sleep_icg_func; } pmu_sleep_digital_config_t; #define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ @@ -356,15 +372,15 @@ typedef struct { .dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ }, \ - .icg_func = (clk_flags)[0] \ + .sleep_icg_func = (uint32_t)((clk_flags)[0]), \ } -#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ +#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 1, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ }, \ - .icg_func = 0 \ + .sleep_icg_func = 0, \ } diff --git a/components/esp_hw_support/port/esp32h4/pmu_init.c b/components/esp_hw_support/port/esp32h4/pmu_init.c index 797999909db..625b549c00b 100644 --- a/components/esp_hw_support/port/esp32h4/pmu_init.c +++ b/components/esp_hw_support/port/esp32h4/pmu_init.c @@ -43,7 +43,17 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; +#if PMU_SLEEP_PRIV_ENABLED + static DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 }; +#endif + static DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = &pmu_data, +#endif + }; + return &pmu_context; } diff --git a/components/esp_hw_support/port/esp32h4/pmu_sleep.c b/components/esp_hw_support/port/esp32h4/pmu_sleep.c index 6ccea386ab4..6b8127e247d 100644 --- a/components/esp_hw_support/port/esp32h4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h4/pmu_sleep.c @@ -17,6 +17,7 @@ #include "hal/lp_aon_hal.h" #include "hal/efuse_ll.h" #include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" #include "pmu_param.h" #if !SOC_APM_SUPPORTED #include "hal/apm_hal.h" @@ -137,7 +138,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, p if (dslp) { config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, args->slowclk_period); - pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags); + pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags); config->digital = digital_default; @@ -196,10 +197,11 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig, bool dslp) { pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt); - pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0)); - pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func); + pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->sleep_icg_func != 0)); + pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->sleep_icg_func); if (!dslp) { pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel); + pmu_sleep_retention_clock_icg_config(ctx->priv, ctx); } } diff --git a/components/esp_hw_support/port/esp32h4/pmu_sleep_power.c b/components/esp_hw_support/port/esp32h4/pmu_sleep_power.c index b14e0f309b7..123dd01b9ba 100644 --- a/components/esp_hw_support/port/esp32h4/pmu_sleep_power.c +++ b/components/esp_hw_support/port/esp32h4/pmu_sleep_power.c @@ -101,19 +101,21 @@ ESP_SYSTEM_INIT_FN(sleep_power_startup_init, SECONDARY, BIT(0), 108) if (err != ESP_OK) { ESP_LOGW(TAG, "failed to init power retention module, err=%d", err); } else { - PMU_instance()->priv = &ana_wait_ctx; + pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv; + data->func[PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT] = &ana_wait_ctx; } return ESP_OK; } -void pmu_sleep_power_analog_wait_config(void *ana_wait_context, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM]) +void pmu_sleep_power_analog_wait_config(void *data, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM]) { - if (!ana_wait_context) { + pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data; + if (!data_ctx || !data_ctx->func[PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT]) { return; } - pmu_sleep_power_ana_wait_context_t *ana_wait_ctx = (pmu_sleep_power_ana_wait_context_t *)ana_wait_context; + pmu_sleep_power_ana_wait_context_t *ana_wait_ctx = (pmu_sleep_power_ana_wait_context_t *)data_ctx->func[PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT]; for (int i = 0; i < ANALOG_WAIT_CTRL_NUM; i++) { if (!ana_wait_ctx->regdma_desc[i]) { continue; diff --git a/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h index 9eb38fc98b6..ed749b6c43e 100644 --- a/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h4/private_include/pmu_param.h @@ -9,6 +9,8 @@ #include #include #include +#include "sdkconfig.h" +#include "soc/soc_caps.h" #include "soc/pmu_struct.h" #include "hal/pmu_hal.h" @@ -115,10 +117,28 @@ const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mo /** * @brief Update content of selected analog wait ctrl REGDMA links. * - * @param ana_wait_context Analog wait ctrl context. + * @param data PMU sleep data context. * @param analog_wait Update analog wait values at S2M, M2S, M2A retention links. */ -void pmu_sleep_power_analog_wait_config(void *ana_wait_context, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM]); +void pmu_sleep_power_analog_wait_config(void *data, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM]); +#endif + +/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */ +#define PMU_SLEEP_PRIV_ENABLED (CONFIG_PM_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT || SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG) +#if PMU_SLEEP_PRIV_ENABLED +enum { +#if CONFIG_PM_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT + PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT, +#endif +#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG + PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK, +#endif + PMU_SLEEP_PRIV_MAX, +}; + +typedef struct { + void *func[PMU_SLEEP_PRIV_MAX]; +} pmu_sleep_data_t; #endif /* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/ @@ -361,7 +381,7 @@ typedef struct { typedef struct { pmu_hp_sys_cntl_reg_t syscntl; - uint32_t icg_func; + uint32_t sleep_icg_func; } pmu_sleep_digital_config_t; #define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ @@ -369,15 +389,15 @@ typedef struct { .dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ }, \ - .icg_func = (clk_flags)[0] \ + .sleep_icg_func = (uint32_t)((clk_flags)[0]), \ } -#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ +#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \ .syscntl = { \ .dig_pad_slp_sel = 1, \ .dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \ }, \ - .icg_func = 0 \ + .sleep_icg_func = 0, \ } typedef struct { diff --git a/components/esp_hw_support/port/esp32p4/pmu_init.c b/components/esp_hw_support/port/esp32p4/pmu_init.c index f791f57be9d..f3b10a338f1 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_init.c +++ b/components/esp_hw_support/port/esp32p4/pmu_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -45,7 +45,16 @@ pmu_context_t * __attribute__((weak)) SPM_IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static SPM_DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; static SPM_DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static SPM_DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; +#if PMU_SLEEP_PRIV_ENABLED + static SPM_DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 }; +#endif + static SPM_DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = &pmu_data, +#endif + }; return &pmu_context; } diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c b/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c index b17b1ba2678..55babb08a3f 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep_clock_icg.c @@ -9,6 +9,7 @@ #include "soc/hp_sys_clkrst_reg.h" #include "esp_private/sleep_retention.h" #include "esp_private/startup_internal.h" +#include "pmu_param.h" ESP_LOG_ATTR_TAG(TAG, "sleep_clock"); @@ -166,17 +167,22 @@ ESP_SYSTEM_INIT_FN(sleep_clock_icg_startup_init, SECONDARY, BIT(0), 106) } } if (err == ESP_OK) { - PMU_instance()->priv = (void *)&clock_icg_context; + pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv; + data->func[PMU_SLEEP_PRIV_SW_ICG_CLK] = (void *)&clock_icg_context; } ESP_RETURN_ON_ERROR(err, TAG, "failed to initialize system sleep clock ICG context"); return ESP_OK; } -void pmu_sleep_clock_icg_config(void *icg_context, const uint32_t icg_func) +void pmu_sleep_clock_icg_config(void *data, const uint32_t icg_func) { - assert(icg_context); - pmu_sleep_clock_icg_context_t *clock_icg = (pmu_sleep_clock_icg_context_t *)icg_context; + pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data; + if (!data_ctx || !data_ctx->func[PMU_SLEEP_PRIV_SW_ICG_CLK]) { + return; + } + + pmu_sleep_clock_icg_context_t *clock_icg = (pmu_sleep_clock_icg_context_t *)data_ctx->func[PMU_SLEEP_PRIV_SW_ICG_CLK]; /* Locking is not required here because this function is always invoked * within esp_light_sleep_start(), where the necessary lock has already been acquired. */ if (icg_func & BIT(PMU_ICG_FUNC_ENA_IOMUX)) { diff --git a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h index 64946aefbbb..f3ef108e2b4 100644 --- a/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32p4/private_include/pmu_param.h @@ -9,6 +9,7 @@ #include #include #include +#include "soc/soc_caps.h" #include "soc/pmu_struct.h" #include "hal/pmu_hal.h" #include "sdkconfig.h" @@ -21,6 +22,21 @@ extern "C" { #endif +/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */ +#define PMU_SLEEP_PRIV_ENABLED (SOC_PM_SLEEP_CLK_ICG_USE_REGDMA) +#if PMU_SLEEP_PRIV_ENABLED +enum { +#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA + PMU_SLEEP_PRIV_SW_ICG_CLK, +#endif + PMU_SLEEP_PRIV_MAX, +}; + +typedef struct { + void *func[PMU_SLEEP_PRIV_MAX]; +} pmu_sleep_data_t; +#endif + #define HP_CALI_ACTIVE_DCM_VSET_DEFAULT 27 // For DCDC, about 1.25v #define HP_CALI_ACTIVE_DBIAS_DEFAULT 24 // For HP regulator #define LP_CALI_ACTIVE_DBIAS_DEFAULT 29 // For LP regulator @@ -117,7 +133,7 @@ const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mo #if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !defined(CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) -void pmu_sleep_clock_icg_config(void *icg_context, const uint32_t icg_func); +void pmu_sleep_clock_icg_config(void *data, const uint32_t icg_func); #endif diff --git a/components/esp_hw_support/port/esp32s31/pmu_init.c b/components/esp_hw_support/port/esp32s31/pmu_init.c index 5cbaf821e74..1ece660d905 100644 --- a/components/esp_hw_support/port/esp32s31/pmu_init.c +++ b/components/esp_hw_support/port/esp32s31/pmu_init.c @@ -44,7 +44,16 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) * instance will be used in pmu_sleep.c */ static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = NULL }; static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); - static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; +#if PMU_SLEEP_PRIV_ENABLED + static DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 }; +#endif + static DRAM_ATTR pmu_context_t pmu_context = { + .hal = &pmu_hal, + .mc = (void *)&pmu_mc, +#if PMU_SLEEP_PRIV_ENABLED + .priv = &pmu_data, +#endif + }; if (pmu_hal.dev == NULL) { pmu_hal.dev = &PMU; diff --git a/components/esp_hw_support/port/esp32s31/pmu_sleep.c b/components/esp_hw_support/port/esp32s31/pmu_sleep.c index f13986afd19..a07bd8439bd 100644 --- a/components/esp_hw_support/port/esp32s31/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32s31/pmu_sleep.c @@ -15,6 +15,7 @@ #include "soc/rtc.h" #include "soc/pmu_struct.h" #include "esp_private/esp_pmu.h" +#include "esp_private/sleep_clock_icg.h" #include "pmu_param.h" #include "hal/clk_tree_hal.h" #include "hal/lp_aon_hal.h" @@ -277,16 +278,19 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].xtal.xpd_xtal); } -static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig) +static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig, bool dslp) { - 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_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); pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt); pmu_ll_hp_set_c_channel_enable (ctx->hal->dev, HP(SLEEP), dig->syscntl.c_channel); + if (!dslp) { + 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_sleep_retention_clock_icg_config(ctx->priv, ctx); + } } static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp) @@ -336,7 +340,7 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp) { assert(PMU_instance()); pmu_sleep_power_init(PMU_instance(), &config->power, dslp); - pmu_sleep_digital_init(PMU_instance(), &config->digital); + pmu_sleep_digital_init(PMU_instance(), &config->digital, dslp); pmu_sleep_analog_init(PMU_instance(), &config->analog, dslp); pmu_sleep_param_init(PMU_instance(), &config->param, dslp); } 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 717ca32d30c..831ccc0ac4c 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 @@ -9,6 +9,8 @@ #include #include #include +#include "sdkconfig.h" +#include "soc/soc_caps.h" #include "soc/pmu_struct.h" #include "hal/pmu_hal.h" #include "soc/pmu_icg_mapping.h" @@ -111,6 +113,20 @@ typedef struct { const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode); +/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */ +#define PMU_SLEEP_PRIV_ENABLED (SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG) +#if PMU_SLEEP_PRIV_ENABLED +enum { +#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG + PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK, +#endif + PMU_SLEEP_PRIV_MAX, +}; + +typedef struct { + void *func[PMU_SLEEP_PRIV_MAX]; +} pmu_sleep_data_t; +#endif /* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/ typedef union { @@ -342,7 +358,7 @@ typedef struct { .icg_func = { .clock = { 0, 0 } }, \ } -#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ +#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \ .syscntl = { \ .dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \ .lp_pad_hold_all = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \ @@ -351,7 +367,7 @@ typedef struct { .c_channel = (sleep_flags & PMU_SLEEP_PD_TOP) ? 0 : 1 \ }, \ .icg_func = { \ - .clock = { (clk_flags)[0], (clk_flags)[1] } \ + .clock = { (clk_flags)[0], (clk_flags)[1] } \ }, \ } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index efb6c2ac96a..34af7e70954 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1608,7 +1608,7 @@ esp_err_t esp_light_sleep_start(void) uint32_t sleep_flags = get_sleep_flags(pd_flags, false); esp_sleep_extra_args_t extra_args = { 0 }; #if SOC_PM_SUPPORT_PMU_CLK_ICG - esp_sleep_clock_get_clk_icg_flags(&extra_args.clk_flags[0], &extra_args.clk_flags[1]); + sleep_clock_icg_get_icg_flags(&extra_args.clk_flags[0], &extra_args.clk_flags[1]); #endif // Re-calibrate the RTC clock sleep_low_power_clock_calibration(false); diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 88398a6164b..22bf85061d0 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -21,6 +21,10 @@ #include "sdkconfig.h" #include "esp_pmu.h" +#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG +#include "esp_private/sleep_clock_icg.h" +#endif + #if SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE #include "soc/pmu_reg.h" // for PMU_DATE_REG, it can provide full 32 bit read and write access #endif @@ -620,6 +624,8 @@ static void entries_do_destroy(sleep_retention_module_t module) memset(&next_entries, 0, sizeof(sleep_retention_entries_t)); _lock_acquire_recursive(&s_retention.lock); + s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); + s_retention.created_modules.bitmap[module >> 5] &= ~BIT(module % 32); int index = module_runtime_attach(instance(module)) ? 1 : 0; struct module_sleep_retention_context *ctx = &s_retention.context[index]; regdma_link_priority_t priority = 0; @@ -636,8 +642,6 @@ static void entries_do_destroy(sleep_retention_module_t module) priority++; } } while (priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES); - s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); - s_retention.created_modules.bitmap[module >> 5] &= ~BIT(module % 32); _lock_release_recursive(&s_retention.lock); } @@ -780,6 +784,11 @@ static void retention_entries_join(void) pmu_sleep_disable_regdma_backup(); #endif } + +#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG + sleep_clock_icg_retention_clock_config(&s_retention.retention_modules); +#endif + _lock_release_recursive(&s_retention.lock); } @@ -1160,9 +1169,9 @@ static esp_err_t passive_module_attach(sleep_retention_module_t module) assert(module_runtime_attach(instance(module)) && "Illegal dependency"); assert(module_is_inited(module) && "All passive module must be inited first!"); if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) { - module_entries_move(module, &s_retention.context[1], &s_retention.retention); s_retention.attached_modules.bitmap[module >> 5] |= BIT(module % 32); s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); + module_entries_move(module, &s_retention.context[1], &s_retention.retention); err = module_action_wrapper(module, (BIT(31) | action(3)), passive_module_attach); } _lock_release_recursive(&s_retention.lock); @@ -1180,9 +1189,9 @@ esp_err_t sleep_retention_module_attach(sleep_retention_module_t module) if (!module_is_passive(instance(module))) { if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) { if (module_runtime_attach(instance(module))) { - module_entries_move(module, &s_retention.context[1], &s_retention.retention); s_retention.attached_modules.bitmap[module >> 5] |= BIT(module % 32); s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32); + module_entries_move(module, &s_retention.context[1], &s_retention.retention); err = module_action_wrapper(module, action(3), passive_module_attach); } else { err = ESP_ERR_NOT_SUPPORTED; @@ -1208,9 +1217,9 @@ static esp_err_t passive_module_detach(sleep_retention_module_t module) assert(module_is_inited(module) && "All passive module must be inited first!"); if (module_is_inited(module) && module_is_created(module) && module_is_retained(module)) { if (refarray_zero(instance(module), 1)) { - module_entries_move(module, &s_retention.retention, &s_retention.context[1]); s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); s_retention.attached_modules.bitmap[module >> 5] &= ~BIT(module % 32); + module_entries_move(module, &s_retention.retention, &s_retention.context[1]); err = module_action_wrapper(module, (BIT(31) | action(4)), passive_module_detach); } } @@ -1229,9 +1238,9 @@ esp_err_t sleep_retention_module_detach(sleep_retention_module_t module) if (!module_is_passive(instance(module))) { if (module_is_inited(module) && module_is_created(module) && module_is_retained(module)) { if (module_runtime_attach(instance(module))) { - module_entries_move(module, &s_retention.retention, &s_retention.context[1]); s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32); s_retention.attached_modules.bitmap[module >> 5] &= ~BIT(module % 32); + module_entries_move(module, &s_retention.retention, &s_retention.context[1]); err = module_action_wrapper(module, action(4), passive_module_detach); } else { err = ESP_ERR_NOT_SUPPORTED; diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index afa3ae00885..62c21765617 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -1039,6 +1039,10 @@ config SOC_PM_SUPPORT_PMU_CLK_ICG bool default y +config SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG + bool + default y + config SOC_PM_FLASH_KEEP_POWER_IN_LSLP bool default y diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index fbc18642dc1..f4856d657db 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -456,6 +456,7 @@ #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!