feat(esp_hw_support): support runtime clock for peripherals to be ungated during sleep

This commit is contained in:
Li Shuai
2025-02-28 11:40:11 +08:00
parent 87024c3da1
commit 157faa3344
21 changed files with 228 additions and 52 deletions

View File

@@ -239,6 +239,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk
* @brief Get default sleep configuration
* @param config pmu_sleep_config instance
* @param sleep_flags flags indicates the power domain that will be powered down and the sleep submode
* @param clk_flags indicates the clock ICG cell that will be ungated
* @param adjustment total software and hardware time overhead
* @param slowclk_period re-calibrated slow clock period in microseconds,
* Q13.19 fixed point format
@@ -248,7 +249,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk
* @return hardware time overhead in us
*/
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, uint32_t sleep_flags, uint32_t adjustment, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp);
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, uint32_t sleep_flags, uint32_t clk_flags, uint32_t adjustment, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp);
/**
* @brief Prepare the chip to enter sleep mode

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -83,6 +83,40 @@ int32_t* esp_sleep_sub_mode_dump_config(FILE *stream);
void esp_sleep_isolate_digital_gpio(void);
#endif
#if SOC_PM_SUPPORT_PMU_CLK_ICG
/**
* @brief Clock ICG cells which can be gated in sleep mode
*/
typedef enum {
ESP_SLEEP_CLOCK_IOMUX, //!< The clock ICG cell mapping of IOMUX
ESP_SLEEP_CLOCK_LEDC, //!< The clock ICG cell mapping of LEDC
ESP_SLEEP_CLOCK_UART0, //!< The clock ICG cell mapping of UART0
ESP_SLEEP_CLOCK_UART1, //!< The clock ICG cell mapping of UART1
ESP_SLEEP_CLOCK_MAX //!< Number of ICG cells
} esp_sleep_clock_t;
/**
* @brief Clock ICG options
*/
typedef enum {
ESP_SLEEP_CLOCK_OPTION_GATE, //!< Gate the clock in sleep mode
ESP_SLEEP_CLOCK_OPTION_UNGATE //!< Ungate the clock in sleep mode
} esp_sleep_clock_option_t;
/**
* @brief Gate or Ungate the specified clock in sleep mode
*
* If not set set using this API, all clock default to ESP_SLEEP_CLOCK_OPTION_GATE.
*
* @param clock the specified clock to configure
* @param option clock gate option (ESP_SLEEP_CLOCK_OPTION_GATE or ESP_SLEEP_CLOCK_OPTION_UNGATE)
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
*/
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option);
#endif
#if CONFIG_ESP_PHY_ENABLED
/**
* Register a callback to be called from the deep sleep prepare for maintain the PHY state

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -151,6 +151,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t sleep_flags,
uint32_t clk_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
@@ -165,10 +166,15 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
if (dslp) {
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
@@ -204,9 +210,13 @@ 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)
{
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
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);
if (!dslp) {
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
}
}
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
@@ -258,9 +268,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);
if(!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);
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -324,12 +324,21 @@ typedef struct {
typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
uint32_t icg_func;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_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, \
} \
}, \
.icg_func = clk_flags \
}
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 1, \
}, \
.icg_func = 0 \
}
typedef struct {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -199,6 +199,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t sleep_flags,
uint32_t clk_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
@@ -213,12 +214,16 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
if (dslp) {
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
analog_default.lp_sys[LP(SLEEP)].analog.dbg_atten = get_dslp_dbg();
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_dslp_lp_dbias();
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
@@ -271,9 +276,13 @@ 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)
{
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
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);
if (!dslp) {
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
}
}
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
@@ -322,9 +331,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);
if(!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);
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -320,12 +320,21 @@ typedef struct {
typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
uint32_t icg_func;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_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, \
} \
}, \
.icg_func = clk_flags \
}
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 1, \
}, \
.icg_func = 0 \
}
typedef struct {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -151,6 +151,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t sleep_flags,
uint32_t clk_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
@@ -165,10 +166,14 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
if (dslp) {
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
@@ -204,9 +209,13 @@ 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)
{
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
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);
if (!dslp) {
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
}
}
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
@@ -258,9 +267,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);
if(!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);
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -322,12 +322,21 @@ typedef struct {
typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
uint32_t icg_func;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_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, \
} \
}, \
.icg_func = clk_flags \
}
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 1, \
}, \
.icg_func = 0 \
}
typedef struct {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -131,6 +131,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t sleep_flags,
uint32_t clk_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
@@ -144,11 +145,14 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
if (dslp) {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
@@ -186,9 +190,13 @@ 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)
{
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
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);
if (!dslp) {
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
}
}
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
@@ -229,9 +237,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);
if (!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);
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -310,12 +310,21 @@ typedef struct {
typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
uint32_t icg_func;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_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, \
} \
}, \
.icg_func = clk_flags \
}
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 1, \
}, \
.icg_func = 0 \
}
typedef struct {

View File

@@ -149,6 +149,7 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
const pmu_sleep_config_t* pmu_sleep_config_default(
pmu_sleep_config_t *config,
uint32_t sleep_flags,
uint32_t clk_flags,
uint32_t adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,

View File

@@ -116,6 +116,10 @@
#include "hal/gpio_ll.h"
#endif
#if SOC_PM_SUPPORT_PMU_CLK_ICG
#include "soc/pmu_icg_mapping.h"
#endif
#if SOC_LP_TIMER_SUPPORTED
#include "hal/lp_timer_hal.h"
#endif
@@ -225,6 +229,9 @@ 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];
#endif
portMUX_TYPE lock;
uint64_t sleep_duration;
uint32_t wakeup_triggers : 20;
@@ -274,6 +281,9 @@ 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,
#endif
.lock = portMUX_INITIALIZER_UNLOCKED,
.ccount_ticks_record = 0,
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
@@ -295,6 +305,7 @@ static RTC_FAST_ATTR int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0
static uint32_t get_power_down_flags(void);
static uint32_t get_sleep_flags(uint32_t pd_flags, bool deepsleep);
static uint32_t get_sleep_clock_icg_flags(void);
#if SOC_PM_SUPPORT_EXT0_WAKEUP
static void ext0_wakeup_prepare(void);
#endif
@@ -790,7 +801,7 @@ static IRAM_ATTR void sleep_low_power_clock_calibration(bool is_dslp)
inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp);
static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection)
static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t clk_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection)
{
// Stop UART output so that output is not lost due to APB frequency change.
// For light sleep, suspend UART output — it will resume after wakeup.
@@ -944,9 +955,8 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_mode_
#endif
pmu_sleep_config_t config;
pmu_sleep_init(pmu_sleep_config_default(&config, sleep_flags, s_config.sleep_time_adjustment,
s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period,
deep_sleep), deep_sleep);
pmu_sleep_init(pmu_sleep_config_default(&config, sleep_flags, clk_flags, s_config.sleep_time_adjustment,
s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period, deep_sleep), deep_sleep);
#else
rtc_sleep_config_t config;
rtc_sleep_get_default_config(sleep_flags, &config);
@@ -1206,7 +1216,7 @@ static esp_err_t IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
uint32_t sleep_flags = get_sleep_flags(force_pd_flags | pd_flags, true);
// Enter sleep
esp_err_t err = ESP_OK;
if (esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_DEEP_SLEEP, allow_sleep_rejection) == ESP_ERR_SLEEP_REJECT) {
if (esp_sleep_start(sleep_flags, 0, ESP_SLEEP_MODE_DEEP_SLEEP, allow_sleep_rejection) == ESP_ERR_SLEEP_REJECT) {
err = ESP_ERR_SLEEP_REJECT;
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
/* Cache Resume 2: if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is enabled, cache has been suspended in esp_sleep_start */
@@ -1243,10 +1253,10 @@ esp_err_t IRAM_ATTR esp_deep_sleep_try_to_start(void)
* Helper function which handles entry to and exit from light sleep
* Placed into IRAM as flash may need some time to be powered on.
*/
static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags,
static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags, uint32_t clk_flags,
uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline));
static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags,
static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags, uint32_t clk_flags,
uint32_t flash_enable_time_us)
{
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
@@ -1254,7 +1264,7 @@ static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags,
#endif
// Enter sleep
esp_err_t reject = esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, true);
esp_err_t reject = esp_sleep_start(sleep_flags, clk_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, true);
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
// If VDDSDIO regulator was controlled by RTC registers before sleep,
@@ -1387,6 +1397,8 @@ 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 whicn clock can be ungate during sleep
uint32_t clk_flags = get_sleep_clock_icg_flags();
// Re-calibrate the RTC clock
sleep_low_power_clock_calibration(false);
@@ -1487,7 +1499,7 @@ esp_err_t esp_light_sleep_start(void)
err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION;
} else {
// Enter sleep, then wait for flash to be ready on wakeup
err = esp_light_sleep_inner(sleep_flags, flash_enable_time_us);
err = esp_light_sleep_inner(sleep_flags, clk_flags, flash_enable_time_us);
}
// light sleep wakeup flag only makes sense after a successful light sleep
@@ -2262,6 +2274,24 @@ 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 (clock > ESP_SLEEP_CLOCK_MAX || option > ESP_SLEEP_CLOCK_OPTION_UNGATE) {
return ESP_ERR_INVALID_ARG;
}
int __attribute__((unused)) refs;
portENTER_CRITICAL_SAFE(&s_config.lock);
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];
portEXIT_CRITICAL_SAFE(&s_config.lock);
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
@@ -2519,6 +2549,27 @@ static uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsleep)
return sleep_flags;
}
static uint32_t get_sleep_clock_icg_flags(void)
{
uint32_t clk_flags = 0;
#if SOC_PM_SUPPORT_PMU_CLK_ICG
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
clk_flags |= BIT(PMU_ICG_FUNC_ENA_IOMUX);
}
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_LEDC] > 0) {
clk_flags |= BIT(PMU_ICG_FUNC_ENA_LEDC);
}
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
clk_flags |= BIT(PMU_ICG_FUNC_ENA_UART0);
}
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
clk_flags |= BIT(PMU_ICG_FUNC_ENA_UART1);
}
#endif /* SOC_PM_SUPPORT_PMU_CLK_ICG */
return clk_flags;
}
#if CONFIG_IDF_TARGET_ESP32
/* APP core of esp32 can't access to RTC FAST MEMORY, do not define it with RTC_IRAM_ATTR */
void

View File

@@ -17,6 +17,7 @@ entries:
sleep_modes:timer_wakeup_prepare (noflash)
sleep_modes:get_power_down_flags (noflash)
sleep_modes:get_sleep_flags (noflash)
sleep_modes:get_sleep_clock_icg_flags (noflash)
esp_clk:esp_clk_slowclk_cal_set (noflash)
esp_clk:esp_clk_slowclk_cal_get (noflash)
esp_clk:esp_rtc_get_time_us (noflash)

View File

@@ -1507,6 +1507,10 @@ config SOC_PM_SUPPORT_PMU_MODEM_STATE
bool
default y
config SOC_PM_SUPPORT_PMU_CLK_ICG
bool
default y
config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
bool
default y

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -605,6 +605,8 @@
/* macro redefine for pass esp_wifi headers md5sum check */
#define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
#define SOC_PM_CPU_RETENTION_BY_SW (1)

View File

@@ -1451,6 +1451,10 @@ config SOC_PM_SUPPORT_PMU_MODEM_STATE
bool
default y
config SOC_PM_SUPPORT_PMU_CLK_ICG
bool
default y
config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
bool
default y

View File

@@ -566,6 +566,8 @@
/* macro redefine for pass esp_wifi headers md5sum check */
#define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
#define SOC_PM_CPU_RETENTION_BY_SW (1)

View File

@@ -1123,6 +1123,10 @@ config SOC_PM_SUPPORT_PMU_MODEM_STATE
bool
default y
config SOC_PM_SUPPORT_PMU_CLK_ICG
bool
default y
config SOC_PM_CPU_RETENTION_BY_SW
bool
default y

View File

@@ -463,6 +463,8 @@
/* macro redefine for pass esp_wifi headers md5sum check */
#define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
#define SOC_PM_CPU_RETENTION_BY_SW (1)
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (1)
#define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1)

View File

@@ -1467,6 +1467,10 @@ config SOC_PM_RETENTION_SW_TRIGGER_REGDMA
bool
default y
config SOC_PM_SUPPORT_PMU_CLK_ICG
bool
default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y

View File

@@ -586,6 +586,8 @@
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
#define SOC_PM_RETENTION_SW_TRIGGER_REGDMA (1) /*!< In esp32H2, regdma will power off when entering sleep */
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)