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"
depends on SOC_GP_LDO_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.
depends on SOC_DCDC_SUPPORTED
config ESP_SLEEP_DCM_VSET_VAL_IN_SLEEP
int "DCDC voltage parameter during sleep"
default 14
range 0 31
depends on ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
help
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

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() { \
.bias = { \
.dcm_vset = 0, \
.dcm_mode = 0, \
.dcm_mode = 1, \
.xpd_bias = 0, \
.dbg_atten = 0x0, \
.pd_cur = 1, \

View File

@@ -43,6 +43,7 @@
#define HP(state) (PMU_MODE_HP_ ## state)
#define LP(state) (PMU_MODE_LP_ ## state)
#define DCDC_STARTUP_TIME_US (950)
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.bias_sleep = PMU_BIASSLP_SLEEP_ON;
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;
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) {
analog_default.hp_sys.analog.xpd_0p1a = 0;
} 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)
{
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_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);
@@ -346,7 +344,7 @@ void pmu_sleep_increase_ldo_volt(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);
// Decrease hp_ldo voltage.
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)
{
#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
if (!dslp) {
// Keep DCDC always on during light sleep, no need to adjust LDO.
} else
#endif
{
if (dslp) {
pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, HP_CALI_ACTIVE_DCM_VSET_DEFAULT);
pmu_sleep_enable_dcdc();
if (pmu_ll_hp_is_sleep_reject(&PMU)) {
// If sleep is rejected, the hardware wake-up process that turns on DCDC
// is skipped, and wait DCDC volt rise up by software here.
esp_rom_delay_us(950);
// If sleep is rejected or regdma restore is skipped, the hardware wake-up process that
// turns on DCDC is skipped, and wait DCDC volt rise up by software here.
esp_rom_delay_us(DCDC_STARTUP_TIME_US);
}
pmu_sleep_shutdown_ldo();
}

View File

@@ -351,6 +351,7 @@ typedef struct {
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.dcm_mode = 1, \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
@@ -385,6 +386,7 @@ typedef struct {
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.dcm_mode = 0, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.xpd = PMU_HP_XPD_DEEPSLEEP, \
@@ -503,7 +505,7 @@ typedef struct pmu_sleep_machine_constant {
.system_dfs_up_work_time_us = 124, \
.analog_wait_time_us = PMU_HP_ANA_WAIT_TIME_PD_TOP_US, \
.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_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_US, \
.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
#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_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU
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
esp_err_t result;
#if SOC_PMU_SUPPORTED
#if SOC_DCDC_SUPPORTED
#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
if (!deep_sleep) {
// Keep DCDC always on during light sleep, no need to adjust LDO voltage.
} else
#endif
{
if (deep_sleep) {
s_config.rtc_ticks_at_ldo_prepare = rtc_time_get();
pmu_sleep_increase_ldo_volt();
}