Merge branch 'feature/support_esp32p4_dcdc_always_on' into 'master'

feat(esp_hw_support): support esp32p4 dcdc always on during lightsleep

Closes PM-104 and PM-131

See merge request espressif/esp-idf!30449
This commit is contained in:
Wu Zheng Hui 2024-06-24 11:46:34 +08:00
commit e254647b0a
14 changed files with 106 additions and 37 deletions

View File

@ -281,6 +281,8 @@ menu "Hardware Settings"
endmenu
orsource "./port/$IDF_TARGET/Kconfig.dcdc"
orsource "./port/$IDF_TARGET/Kconfig.ldo"
# Invisible bringup bypass options for esp_hw_support component

View File

@ -277,7 +277,7 @@ void pmu_sleep_shutdown_dcdc(void);
* @brief DCDC has taken over power supply, shut down LDO to save power consumption
*/
void pmu_sleep_shutdown_ldo(void);
#endif
#endif // SOC_DCDC_SUPPORTED
/**
* @brief Enter deep or light sleep mode
@ -309,9 +309,10 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
/**
* @brief Finish sleep process settings and get sleep reject status
* @param dslp True if sleep requests id deep-sleep
* @return return sleep reject status
*/
bool pmu_sleep_finish(void);
bool pmu_sleep_finish(bool dslp);
/**
* @brief Initialize PMU related power/clock/digital parameters and functions

View File

@ -435,7 +435,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
}
#endif
return pmu_sleep_finish();
return pmu_sleep_finish(dslp);
}
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),

View File

@ -475,7 +475,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
}
#endif
return pmu_sleep_finish();
return pmu_sleep_finish(dslp);
}
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),

View File

@ -475,7 +475,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
}
#endif
return pmu_sleep_finish();
return pmu_sleep_finish(dslp);
}
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),

View File

@ -429,7 +429,7 @@ static TCM_IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
}
#endif
return pmu_sleep_finish();
return pmu_sleep_finish(dslp);
}
esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),

View File

@ -274,11 +274,12 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
;
}
return pmu_sleep_finish();
return pmu_sleep_finish(dslp);
}
bool pmu_sleep_finish(void)
bool pmu_sleep_finish(bool dslp)
{
(void)dslp;
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
}

View File

@ -341,11 +341,12 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
;
}
return pmu_sleep_finish();
return pmu_sleep_finish(dslp);
}
bool pmu_sleep_finish(void)
bool pmu_sleep_finish(bool dslp)
{
(void)dslp;
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
}

View File

@ -258,11 +258,12 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
;
}
return ESP_OK;
return pmu_sleep_finish(dslp);
}
bool pmu_sleep_finish(void)
bool pmu_sleep_finish(bool dslp)
{
(void)dslp;
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
}

View File

@ -0,0 +1,30 @@
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.
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
value according to the model of external DCDC selected in your hardware solution.
For the DCDC chip model recommended by ESP, the recommended configuration
values are listed below:
- TI-TLV62569/TLV62569P: 14
endmenu

View File

@ -79,7 +79,6 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa
pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias);
pmu_ll_hp_set_dcm_mode (ctx->hal->dev, mode, anlg->bias.dcm_mode);
pmu_ll_hp_set_dcm_vset (ctx->hal->dev, mode, anlg->bias.dcm_vset);
pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias);
pmu_ll_hp_set_dbg_atten (ctx->hal->dev, mode, anlg->bias.dbg_atten);
pmu_ll_hp_set_current_power_off (ctx->hal->dev, mode, anlg->bias.pd_cur);
pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep);

View File

@ -149,26 +149,35 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0;
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0;
config->power = power_default;
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period);
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_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags);
config->analog = analog_default;
} else {
// Get light sleep digital_default
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags);
config->digital = digital_default;
// Get light sleep analog default
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
#if CONFIG_SPIRAM
analog_default.hp_sys.analog.pd_cur = 1;
analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = 1;
#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
config->analog = analog_default;
}
config->power = power_default;
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period);
return config;
}
@ -194,6 +203,8 @@ 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);
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);
pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep);
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd);
@ -250,10 +261,10 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp)
}
void pmu_sleep_increase_ldo_volt(void) {
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 30);
REG_SET_BIT(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD);
pmu_ll_hp_set_regulator_dbias(&PMU, PMU_MODE_HP_ACTIVE, 30);
pmu_ll_hp_set_regulator_xpd(&PMU, PMU_MODE_HP_ACTIVE, 1);
// Decrease the DCDC voltage to reduce the voltage difference between the DCDC and the LDO to avoid overshooting the DCDC voltage during wake-up.
REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, 24);
pmu_ll_hp_set_dcm_vset(&PMU, PMU_MODE_HP_ACTIVE, 24);
}
void pmu_sleep_shutdown_dcdc(void) {
@ -301,19 +312,26 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
;
}
return pmu_sleep_finish();
return pmu_sleep_finish(dslp);
}
TCM_IRAM_ATTR bool pmu_sleep_finish(void)
TCM_IRAM_ATTR bool pmu_sleep_finish(bool dslp)
{
REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, 27);
if (pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
// If sleep is rejected, the hardware wake-up process that turns on DCDC
// is skipped, and software is used to enable DCDC here.
pmu_sleep_enable_dcdc();
esp_rom_delay_us(950);
#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
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, 27);
if (pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
// If sleep is rejected, the hardware wake-up process that turns on DCDC
// is skipped, and software is used to enable DCDC here.
pmu_sleep_enable_dcdc();
esp_rom_delay_us(950);
}
pmu_sleep_shutdown_ldo();
}
pmu_sleep_shutdown_ldo();
unsigned chip_version = efuse_hal_chip_revision();
if (!ESP_CHIP_REV_ABOVE(chip_version, 1)) {

View File

@ -105,7 +105,7 @@ const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mo
typedef union {
struct {
uint32_t reserved0 : 21;
uint32_t dcdc_switch_pd_en: 1;
uint32_t dcdc_switch_pd_en: 1;
uint32_t mem_dslp : 1;
uint32_t mem_pd_en : 1;
uint32_t reserved1 : 6;
@ -153,7 +153,9 @@ typedef union {
typedef struct {
struct {
uint32_t reserved0 : 25;
uint32_t reserved0 : 18;
uint32_t dcm_vset : 5;
uint32_t dcm_mode : 2;
uint32_t xpd_bias : 1;
uint32_t dbg_atten : 4;
uint32_t pd_cur : 1;

View File

@ -905,8 +905,15 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#if SOC_PMU_SUPPORTED
#if SOC_DCDC_SUPPORTED
s_config.rtc_ticks_at_ldo_prepare = rtc_time_get();
pmu_sleep_increase_ldo_volt();
#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
{
s_config.rtc_ticks_at_ldo_prepare = rtc_time_get();
pmu_sleep_increase_ldo_volt();
}
#endif
pmu_sleep_config_t config;
@ -991,11 +998,18 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
#if SOC_DCDC_SUPPORTED
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);
#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
{
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();
}
pmu_sleep_shutdown_dcdc();
#endif
#if SOC_PMU_SUPPORTED