Merge branch 'fix/controll_dcdc_switch_by_pmu_in_dslp' into 'master'

fix(esp_hw_support): control DCDC switch by PMU FSM while control DCDC_EN by software

See merge request espressif/esp-idf!41310
This commit is contained in:
Jiang Jiang Jian
2025-09-30 11:50:55 +08:00
5 changed files with 16 additions and 48 deletions

View File

@@ -1,23 +1,10 @@
menu "DCDC Regulator Configurations" menu "DCDC Regulator Configurations"
depends on SOC_GP_LDO_SUPPORTED depends on SOC_DCDC_SUPPORTED
config ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
bool "Keep DC-DC power always on during light-sleep"
default y
help
ESP32P4 will switch the power supply to LDO before sleeping, and switch to DCDC after waking up.
These two processes take a long time and may bring some risks for some short duration
light sleep. (DCDC -> LDO: 2.5ms (max), LDO -> DCDC: 1.2 ms)
Enabling this option will make chip powered by DCDC during light sleep to reduce some power switch
risks, this will also increase the power consumption during the light sleep.
DO NOT DISABLE UNLESS YOU KNOW WHAT YOU ARE DOING.
config ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP config ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP
int "DCDC voltage parameter during sleep" int "DCDC voltage parameter during sleep"
default 14 default 14
range 0 31 range 0 31
depends on ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
help help
This value determines the voltage of the DCDC chip during sleep. The same parameter value may This value determines the voltage of the DCDC chip during sleep. The same parameter value may
correspond to different voltage values on different models of DCDC chips. Please update this correspond to different voltage values on different models of DCDC chips. Please update this

View File

@@ -169,7 +169,7 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp
#define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ #define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \
.bias = { \ .bias = { \
.dcm_vset = 0, \ .dcm_vset = 0, \
.dcm_mode = 0, \ .dcm_mode = 1, \
.xpd_bias = 0, \ .xpd_bias = 0, \
.dbg_atten = 0x0, \ .dbg_atten = 0x0, \
.pd_cur = 1, \ .pd_cur = 1, \

View File

@@ -43,6 +43,7 @@
#define HP(state) (PMU_MODE_HP_ ## state) #define HP(state) (PMU_MODE_HP_ ## state)
#define LP(state) (PMU_MODE_LP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state)
#define DCDC_STARTUP_TIME_US (950)
static bool s_pmu_sleep_regdma_backup_enabled; static bool s_pmu_sleep_regdma_backup_enabled;
@@ -200,16 +201,9 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON; analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON; analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
analog_default.lp_sys[LP(SLEEP)].analog.dbg_atten = PMU_DBG_ATTEN_ACTIVE_DEFAULT; analog_default.lp_sys[LP(SLEEP)].analog.dbg_atten = PMU_DBG_ATTEN_ACTIVE_DEFAULT;
#if !CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_ACTIVE_DBIAS_DEFAULT;
#endif
} }
#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
power_default.hp_sys.dig_power.dcdc_switch_pd_en = 0; power_default.hp_sys.dig_power.dcdc_switch_pd_en = 0;
analog_default.hp_sys.analog.dcm_vset = CONFIG_ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP; analog_default.hp_sys.analog.dcm_vset = CONFIG_ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP;
analog_default.hp_sys.analog.dcm_mode = 1;
#endif
if (sleep_flags & PMU_SLEEP_PD_VDDSDIO) { if (sleep_flags & PMU_SLEEP_PD_VDDSDIO) {
analog_default.hp_sys.analog.xpd_0p1a = 0; analog_default.hp_sys.analog.xpd_0p1a = 0;
} else { } else {
@@ -281,6 +275,10 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp) static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
{ {
assert(ctx->hal); assert(ctx->hal);
/* For deepsleep, DCDC_EN will be controlled by software to avoid DCDC working in a non-feedback state,
which may cause input glitch voltage when waking up and switching to LDO. After chip wake up from deepsleep,
set DCDC_EN in rtc_clk_init. */
pmu_ll_hp_set_dcm_mode (ctx->hal->dev, HP(ACTIVE), dslp ? 0 : 1);
pmu_ll_hp_set_dcm_mode (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dcm_mode); pmu_ll_hp_set_dcm_mode (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dcm_mode);
pmu_ll_hp_set_dcm_vset (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dcm_vset); pmu_ll_hp_set_dcm_vset (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dcm_vset);
pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur); pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur);
@@ -346,7 +344,7 @@ void pmu_sleep_increase_ldo_volt(void) {
} }
void pmu_sleep_shutdown_dcdc(void) { void pmu_sleep_shutdown_dcdc(void) {
pmu_ll_set_dcdc_switch_force_power_down(&PMU, true); // Keep dcdc_switch on, will be disabled by PMU when entered sleep.
pmu_ll_set_dcdc_en(&PMU, false); pmu_ll_set_dcdc_en(&PMU, false);
// Decrease hp_ldo voltage. // Decrease hp_ldo voltage.
pmu_ll_hp_set_regulator_dbias(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DBIAS_DEFAULT); pmu_ll_hp_set_regulator_dbias(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DBIAS_DEFAULT);
@@ -448,18 +446,13 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
TCM_IRAM_ATTR bool pmu_sleep_finish(bool dslp) TCM_IRAM_ATTR bool pmu_sleep_finish(bool dslp)
{ {
#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON if (dslp) {
if (!dslp) {
// Keep DCDC always on during light sleep, no need to adjust LDO.
} else
#endif
{
pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DCM_VSET_DEFAULT); pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DCM_VSET_DEFAULT);
pmu_sleep_enable_dcdc(); pmu_sleep_enable_dcdc();
if (pmu_ll_hp_is_sleep_reject(&PMU)) { if (pmu_ll_hp_is_sleep_reject(&PMU)) {
// If sleep is rejected, the hardware wake-up process that turns on DCDC // If sleep is rejected or regdma restore is skipped, the hardware wake-up process that
// is skipped, and wait DCDC volt rise up by software here. // turns on DCDC is skipped, and wait DCDC volt rise up by software here.
esp_rom_delay_us(950); esp_rom_delay_us(DCDC_STARTUP_TIME_US);
} }
pmu_sleep_shutdown_ldo(); pmu_sleep_shutdown_ldo();
} }

View File

@@ -351,6 +351,7 @@ typedef struct {
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \ #define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \ .hp_sys = { \
.analog = { \ .analog = { \
.dcm_mode = 1, \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \ .drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
@@ -385,6 +386,7 @@ typedef struct {
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \ #define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \ .hp_sys = { \
.analog = { \ .analog = { \
.dcm_mode = 0, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \ .pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \ .bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.xpd = PMU_HP_XPD_DEEPSLEEP, \ .xpd = PMU_HP_XPD_DEEPSLEEP, \
@@ -503,7 +505,7 @@ typedef struct pmu_sleep_machine_constant {
.system_dfs_up_work_time_us = 124, \ .system_dfs_up_work_time_us = 124, \
.analog_wait_time_us = PMU_HP_ANA_WAIT_TIME_PD_TOP_US, \ .analog_wait_time_us = PMU_HP_ANA_WAIT_TIME_PD_TOP_US, \
.power_supply_wait_time_us = 2, \ .power_supply_wait_time_us = 2, \
.power_up_wait_time_us = 2, \ .power_up_wait_time_us = 26, \
.regdma_s2m_work_time_us = 172, \ .regdma_s2m_work_time_us = 172, \
.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_US, \ .regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_US, \
.regdma_m2a_work_time_us = 278, \ .regdma_m2a_work_time_us = 278, \

View File

@@ -931,14 +931,6 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
} }
#endif #endif
#if SOC_DCDC_SUPPORTED && !CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
uint64_t ldo_increased_us = rtc_time_slowclk_to_us(rtc_time_get() - s_config.rtc_ticks_at_ldo_prepare, s_config.rtc_clk_cal_period);
if (ldo_increased_us < LDO_POWER_TAKEOVER_PREPARATION_TIME_US) {
esp_rom_delay_us(LDO_POWER_TAKEOVER_PREPARATION_TIME_US - ldo_increased_us);
}
pmu_sleep_shutdown_dcdc();
#endif
#if SOC_PMU_SUPPORTED #if SOC_PMU_SUPPORTED
#if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU #if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0); esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0);
@@ -1114,14 +1106,8 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl
// Enter sleep // Enter sleep
esp_err_t result; esp_err_t result;
#if SOC_PMU_SUPPORTED #if SOC_PMU_SUPPORTED
#if SOC_DCDC_SUPPORTED #if SOC_DCDC_SUPPORTED
#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON if (deep_sleep) {
if (!deep_sleep) {
// Keep DCDC always on during light sleep, no need to adjust LDO voltage.
} else
#endif
{
s_config.rtc_ticks_at_ldo_prepare = rtc_time_get(); s_config.rtc_ticks_at_ldo_prepare = rtc_time_get();
pmu_sleep_increase_ldo_volt(); pmu_sleep_increase_ldo_volt();
} }