feat(esp_hw_support): esp32s31 PMU basic support

This commit is contained in:
wuzhenghui
2026-01-28 20:26:46 +08:00
parent 0b27301a09
commit 3ac387a2d6
17 changed files with 2651 additions and 19 deletions
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -636,8 +636,8 @@ static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in
static inline void gpio_ll_force_hold_all(void)
{
// WT flag, it gets self-cleared after the configuration is done
PMU.imm_pad_hold_all.tie_high_hp_pad_hold_all = 1;
PMU.imm_pad_hold_all.tie_high_lp_pad_hold_all = 1;
PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1;
PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
}
/**
@@ -647,8 +647,8 @@ static inline void gpio_ll_force_hold_all(void)
static inline void gpio_ll_force_unhold_all(void)
{
// WT flag, it gets self-cleared after the configuration is done
PMU.imm_pad_hold_all.tie_low_hp_pad_hold_all = 1;
PMU.imm_pad_hold_all.tie_low_lp_pad_hold_all = 1;
PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1;
PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
}
/**
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -16,7 +16,29 @@
extern "C" {
#endif
// TODO: ["ESP32S31"] IDF-14653
typedef struct {
pmu_dev_t *dev;
} pmu_hal_context_t;
void pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle);
uint32_t pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal);
void pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle);
uint32_t pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal);
void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal);
#ifdef __cplusplus
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -16,13 +16,782 @@
#include "soc/pmu_struct.h"
#include "hal/pmu_types.h"
#include "hal/misc.h"
#include "hal/config.h"
#ifdef __cplusplus
extern "C" {
#endif
// TODO: ["ESP32S31"] IDF-14642
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_interrupt_raw(pmu_dev_t *hw)
{
return hw->lp_ext.int_raw.val;
}
FORCE_INLINE_ATTR void pmu_ll_lp_clear_intsts_mask(pmu_dev_t *hw, uint32_t mask)
{
hw->lp_ext.int_clr.val = mask;
}
FORCE_INLINE_ATTR void pmu_ll_lp_clear_sw_intr_status(pmu_dev_t *hw)
{
hw->lp_ext.int_clr.hp_sw_trigger = 1;
}
FORCE_INLINE_ATTR void pmu_ll_lp_enable_sw_intr(pmu_dev_t *hw, bool enable)
{
hw->lp_ext.int_ena.hp_sw_trigger = enable;
}
FORCE_INLINE_ATTR void pmu_ll_lp_trigger_sw_intr(pmu_dev_t *hw)
{
hw->hp_lp_cpu_comm.lp_trigger_hp = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_trigger_sw_intr(pmu_dev_t *hw)
{
hw->hp_lp_cpu_comm.hp_trigger_lp = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t flag)
{
hw->hp_sys[mode].dig_power.val = flag;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func0, uint32_t icg_func1)
{
hw->hp_sys[mode].icg[0].icg_func = icg_func0;
hw->hp_sys[mode].icg[1].icg_func = icg_func1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_apb(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t bitmap0, uint32_t bitmap1)
{
hw->hp_sys[mode].icg[0].icg_apb = bitmap0;
hw->hp_sys[mode].icg[1].icg_apb = bitmap1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_modem(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t code)
{
hw->hp_sys[mode].icg_modem.code = code;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_c_channel_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool ena)
{
hw->hp_sys[mode].syscntl.c_channel = ena ? 1 : 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_uart_wakeup_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool wakeup_en)
{
hw->hp_sys[mode].syscntl.uart_wakeup_en = wakeup_en;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_lp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all)
{
hw->hp_sys[mode].syscntl.lp_pad_hold_all = hold_all;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_hp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all)
{
hw->hp_sys[mode].syscntl.hp_pad_hold_all = hold_all;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_pad_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel)
{
hw->hp_sys[mode].syscntl.dig_pad_slp_sel = slp_sel;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_pause_watchdog(pmu_dev_t *hw, pmu_hp_mode_t mode, bool pause_wdt)
{
hw->hp_sys[mode].syscntl.dig_pause_wdt = pause_wdt;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_cpu_stall(pmu_dev_t *hw, pmu_hp_mode_t mode, bool cpu_stall)
{
hw->hp_sys[mode].syscntl.dig_cpu_stall = cpu_stall;
}
/**
* @brief Set the power domain that needs to be powered down in the clock power
*
* @param hw Beginning address of the peripheral registers.
* @param mode The pmu mode
* @param flag Clock power domain flag
*
* @return None
*/
FORCE_INLINE_ATTR void pmu_ll_hp_set_clk_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t xpd_flag)
{
hw->hp_sys[mode].clk_power.val = xpd_flag;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_xtal_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_xtal)
{
hw->hp_sys[mode].xtal.xpd_xtal = xpd_xtal;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_bias)
{
hw->hp_sys[mode].bias.xpd_bias = xpd_bias;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dbg_atten(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t value)
{
hw->hp_sys[mode].bias.dbg_atten = value;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_current_power_off(pmu_dev_t *hw, pmu_hp_mode_t mode, bool off)
{
hw->hp_sys[mode].bias.pd_cur = off;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool en)
{
hw->hp_sys[mode].bias.bias_sleep = en;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_retention_param(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t param)
{
hw->hp_sys[mode].backup_cfg.val = param;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_enable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup_cfg.hp_sleep2active_backup_en = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_disable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup_cfg.hp_sleep2active_backup_en = 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_enable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup_cfg.hp_modem2active_backup_en = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_disable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup_cfg.hp_modem2active_backup_en = 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_enable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_MODEM].backup_cfg.hp_sleep2modem_backup_en = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_disable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_MODEM].backup_cfg.hp_sleep2modem_backup_en = 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_enable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_SLEEP].backup_cfg.hp_active2sleep_backup_en = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_disable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_SLEEP].backup_cfg.hp_active2sleep_backup_en = 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_enable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_SLEEP].backup_cfg.hp_modem2sleep_backup_en = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_disable(pmu_dev_t *hw)
{
hw->hp_sys[PMU_MODE_HP_SLEEP].backup_cfg.hp_modem2sleep_backup_en = 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_backup_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func0, uint32_t icg_func1)
{
hw->hp_sys[mode].backup_clock[0] = icg_func0;
hw->hp_sys[mode].backup_clock[1] = icg_func1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_nodiv(pmu_dev_t *hw, pmu_hp_mode_t mode, bool sysclk_nodiv)
{
hw->hp_sys[mode].sysclk.dig_sysclk_nodiv = sysclk_nodiv;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool icg_sysclk_en)
{
hw->hp_sys[mode].sysclk.icg_sysclk_en = icg_sysclk_en;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel)
{
hw->hp_sys[mode].sysclk.sysclk_slp_sel = slp_sel;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel)
{
hw->hp_sys[mode].sysclk.icg_slp_sel = slp_sel;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_sysclk(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t sysclk_sel)
{
hw->hp_sys[mode].sysclk.dig_sysclk_sel = sysclk_sel;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_lp_dbias_voltage(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t voltage)
{
HAL_ASSERT(mode == PMU_MODE_HP_ACTIVE);
hw->hp_sys[mode].regulator0.lp_dbias_vol = voltage;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_hp_dbias_voltage(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t voltage)
{
HAL_ASSERT(mode == PMU_MODE_HP_ACTIVE);
hw->hp_sys[mode].regulator0.hp_dbias_vol = voltage;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias_select(pmu_dev_t *hw, pmu_hp_mode_t mode, bool sel)
{
HAL_ASSERT(mode == PMU_MODE_HP_ACTIVE);
hw->hp_sys[mode].regulator0.dbias_sel = sel;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias_init(pmu_dev_t *hw, pmu_hp_mode_t mode, bool init)
{
HAL_ASSERT(mode == PMU_MODE_HP_ACTIVE);
hw->hp_sys[mode].regulator0.dig_dbias_init = init;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd)
{
hw->hp_sys[mode].regulator0.slp_logic_xpd = slp_xpd;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd)
{
hw->hp_sys[mode].regulator0.slp_mem_xpd = slp_xpd;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd)
{
hw->hp_sys[mode].regulator0.xpd = xpd;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias)
{
hw->hp_sys[mode].regulator0.slp_logic_dbias = slp_dbias;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias)
{
hw->hp_sys[mode].regulator0.slp_mem_dbias = slp_dbias;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dbias)
{
hw->hp_sys[mode].regulator0.dbias = dbias;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t drv_b)
{
hw->hp_sys[mode].regulator1.drv_b = drv_b;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_slp_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool slp_xpd)
{
hw->lp_sys[mode].regulator0.slp_xpd = slp_xpd;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd)
{
hw->lp_sys[mode].regulator0.xpd = xpd;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_sleep_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t slp_dbias)
{
hw->lp_sys[mode].regulator0.slp_dbias = slp_dbias;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t dbias)
{
hw->lp_sys[mode].regulator0.dbias = dbias;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t drv_b)
{
hw->lp_sys[mode].regulator1.drv_b = drv_b;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_xtal_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_xtal)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].xtal.xpd_xtal = xpd_xtal;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_dig_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t flag)
{
hw->lp_sys[mode].dig_power.val = flag;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t xpd_flag)
{
hw->lp_sys[mode].clk_power.val = xpd_flag;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode)
{
return hw->lp_sys[mode].clk_power.val;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_bias)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.xpd_bias = xpd_bias;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_dbg_atten(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t value)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.dbg_atten = value;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_current_power_off(pmu_dev_t *hw, pmu_lp_mode_t mode, bool off)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.pd_cur = off;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_lp_mode_t mode, bool en)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.bias_sleep = en;
}
FORCE_INLINE_ATTR void pmu_ll_imm_set_clk_power(pmu_dev_t *hw, uint32_t flag0, uint32_t flag1)
{
hw->imm.clk_power_0.val = flag0;
hw->imm.clk_power_1.val = flag1;
}
FORCE_INLINE_ATTR void pmu_ll_imm_set_icg_slp_sel(pmu_dev_t *hw, bool slp_sel)
{
if (slp_sel) {
hw->imm.sleep_sysclk.tie_high_icg_slp_sel = 1;
} else {
hw->imm.sleep_sysclk.tie_low_icg_slp_sel = 1;
}
}
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_sysclk_sel(pmu_dev_t *hw, bool update)
{
hw->imm.sleep_sysclk.update_dig_sysclk_sel = update;
}
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_switch(pmu_dev_t *hw, bool update)
{
hw->imm.sleep_sysclk.update_dig_icg_switch = update;
}
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_func(pmu_dev_t *hw, bool icg_func_update)
{
hw->imm.hp_func_icg.update_dig_icg_func_en = icg_func_update;
}
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_apb(pmu_dev_t *hw, bool icg_apb_update)
{
hw->imm.hp_apb_icg.update_dig_icg_apb_en = icg_apb_update;
}
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_modem_code(pmu_dev_t *hw, bool icg_modem_update)
{
hw->imm.modem_icg.update_dig_icg_modem_en = icg_modem_update;
}
FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_rootclk_sel(pmu_dev_t *hw, bool rootclk_sel)
{
if (rootclk_sel) {
hw->imm.lp_icg.tie_high_lp_rootclk_sel = 1;
} else {
hw->imm.lp_icg.tie_low_lp_rootclk_sel = 1;
}
}
FORCE_INLINE_ATTR void pmu_ll_imm_set_hp_pad_hold_all(pmu_dev_t *hw, bool hold_all)
{
if (hold_all) {
hw->imm.pad_hold_all.tie_high_hp_pad_hold_all = 1;
} else {
hw->imm.pad_hold_all.tie_low_hp_pad_hold_all = 1;
}
}
FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_pad_hold_all(pmu_dev_t *hw, bool hold_all)
{
if (hold_all) {
hw->imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
} else {
hw->imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
}
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool rst)
{
hw->power.hp_pd[domain].force_top_reset = rst;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool iso)
{
hw->power.hp_pd[domain].force_top_iso = iso;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_up(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpu)
{
hw->power.hp_pd[domain].force_top_pu = fpu;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_rst)
{
hw->power.hp_pd[domain].force_top_no_reset = no_rst;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_iso)
{
hw->power.hp_pd[domain].force_top_no_iso = no_iso;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_down(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpd)
{
hw->power.hp_pd[domain].force_top_pd = fpd;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_reset(pmu_dev_t *hw, bool rst)
{
hw->power.lp_peri.force_lp_peri_reset = rst;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_isolate(pmu_dev_t *hw, bool iso)
{
hw->power.lp_peri.force_lp_peri_iso = iso;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_up(pmu_dev_t *hw, bool fpu)
{
hw->power.lp_peri.force_lp_peri_pu = fpu;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_reset(pmu_dev_t *hw, bool no_rst)
{
hw->power.lp_peri.force_lp_peri_no_reset = no_rst;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_isolate(pmu_dev_t *hw, bool no_iso)
{
hw->power.lp_peri.force_lp_peri_no_iso = no_iso;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_down(pmu_dev_t *hw, bool fpd)
{
hw->power.lp_peri.force_lp_peri_pd = fpd;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_isolate(pmu_dev_t *hw, uint32_t iso)
{
hw->power.mem_cntl.force_hp_mem_iso = iso;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_down(pmu_dev_t *hw, uint32_t fpd)
{
hw->power.mem_cntl.force_hp_mem_pd = fpd;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_no_isolate(pmu_dev_t *hw, uint32_t no_iso)
{
hw->power.mem_cntl.force_hp_mem_no_iso = no_iso;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_up(pmu_dev_t *hw, uint32_t fpu)
{
hw->power.mem_cntl.force_hp_mem_pu = fpu;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_enable(pmu_dev_t *hw)
{
hw->wakeup.cntl0.sleep_req = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_enable(pmu_dev_t *hw, uint32_t reject)
{
hw->wakeup.cntl1.sleep_reject_ena = reject;
hw->wakeup.cntl0.slp_reject_en = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_disable(pmu_dev_t *hw)
{
hw->wakeup.cntl0.slp_reject_en = 0;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_wakeup_enable(pmu_dev_t *hw, uint32_t wakeup)
{
hw->wakeup.cntl2 = wakeup;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_protect_mode(pmu_dev_t *hw, int mode)
{
hw->wakeup.cntl3.sleep_prt_sel = mode;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl3, hp_min_slp_val, slow_clk_cycle);
}
FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_cause(pmu_dev_t *hw)
{
hw->wakeup.cntl4.slp_reject_cause_clr = 1;
}
FORCE_INLINE_ATTR void pmu_ll_set_modem_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle)
{
hw->wakeup.cntl5.modem_wait_target = cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_get_modem_wait_target_cycle(pmu_dev_t *hw)
{
return hw->wakeup.cntl5.modem_wait_target;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl7, ana_wait_target, cycle);
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_analog_wait_target_cycle(pmu_dev_t *hw)
{
return HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl7, ana_wait_target);
}
FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_wakeup(pmu_dev_t *hw)
{
return (hw->hp_ext.int_raw.soc_wakeup == 1);
}
FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_reject(pmu_dev_t *hw)
{
return (hw->hp_ext.int_raw.soc_sleep_reject == 1);
}
FORCE_INLINE_ATTR void pmu_ll_hp_clear_sw_intr_status(pmu_dev_t *hw)
{
hw->hp_ext.int_clr.sw = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_clear_wakeup_intr_status(pmu_dev_t *hw)
{
hw->hp_ext.int_clr.soc_wakeup = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw)
{
hw->hp_ext.int_clr.soc_sleep_reject = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_enable_sw_intr(pmu_dev_t *hw, bool enable)
{
hw->hp_ext.int_ena.sw = enable;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw)
{
return hw->wakeup.status0;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_reject_cause(pmu_dev_t *hw)
{
return hw->wakeup.status1;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl3, lp_min_slp_val, slow_clk_cycle);
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_modify_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hp_ext.clk_cntl, modify_icg_cntl_wait, cycle);
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_modify_icg_cntl_wait_cycle(pmu_dev_t *hw)
{
return HAL_FORCE_READ_U32_REG_FIELD(hw->hp_ext.clk_cntl, modify_icg_cntl_wait);
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_switch_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hp_ext.clk_cntl, switch_icg_cntl_wait, cycle);
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_switch_icg_cntl_wait_cycle(pmu_dev_t *hw)
{
return HAL_FORCE_READ_U32_REG_FIELD(hw->hp_ext.clk_cntl, switch_icg_cntl_wait);
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
hw->power.wait_timer0.powerdown_timer = cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_down_wait_cycle(pmu_dev_t *hw)
{
return hw->power.wait_timer0.powerdown_timer;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
hw->power.wait_timer1.powerdown_timer = cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_down_wait_cycle(pmu_dev_t *hw)
{
return hw->power.wait_timer1.powerdown_timer;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target, slow_clk_cycle);
}
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw)
{
return HAL_FORCE_READ_U32_REG_FIELD(hw->wakeup.cntl5, lp_ana_wait_target);
}
FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->power.clk_wait, wait_xtal_stable, cycle);
}
FORCE_INLINE_ATTR uint32_t pmu_ll_get_xtal_stable_wait_cycle(pmu_dev_t *hw)
{
return HAL_FORCE_READ_U32_REG_FIELD(hw->power.clk_wait, wait_xtal_stable);
}
FORCE_INLINE_ATTR void pmu_ll_set_pll_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->power.clk_wait, wait_pll_stable, cycle);
}
FORCE_INLINE_ATTR uint32_t pmu_ll_get_pll_stable_wait_cycle(pmu_dev_t *hw)
{
return HAL_FORCE_READ_U32_REG_FIELD(hw->power.clk_wait, wait_pll_stable);
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
hw->power.wait_timer1.wait_timer = cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw)
{
return hw->power.wait_timer1.wait_timer;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
hw->power.wait_timer1.powerup_timer = cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_up_wait_cycle(pmu_dev_t *hw)
{
return hw->power.wait_timer1.powerup_timer;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
hw->power.wait_timer0.wait_timer = cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw)
{
return hw->power.wait_timer0.wait_timer;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
{
hw->power.wait_timer0.powerup_timer = cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t *hw)
{
return hw->power.wait_timer0.powerup_timer;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_isolate_wait_cycle(pmu_dev_t *hw, uint32_t isolate_wait_cycle)
{
hw->power.wait_timer2.dg_lp_iso_wait_timer = isolate_wait_cycle;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_reset_wait_cycle(pmu_dev_t *hw, uint32_t reset_wait_cycle)
{
hw->power.wait_timer2.dg_lp_rst_wait_timer = reset_wait_cycle;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_isolate_wait_cycle(pmu_dev_t *hw, uint32_t isolate_wait_cycle)
{
hw->power.wait_timer2.dg_hp_iso_wait_timer = isolate_wait_cycle;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_reset_wait_cycle(pmu_dev_t *hw, uint32_t reset_wait_cycle)
{
hw->power.wait_timer2.dg_hp_rst_wait_timer = reset_wait_cycle;
}
FORCE_INLINE_ATTR uint32_t pmu_ll_get_sysclk_sleep_select_state(pmu_dev_t *hw)
{
return hw->clk_state0.sysclk_slp_sel;
}
/**
* @brief Get ext1 wakeup source status
* @return The lower 8 bits of the returned value are the bitmap of
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
*/
static inline uint32_t pmu_ll_ext1_get_wakeup_status(void)
{
return REG_GET_FIELD(PMU_EXT_WAKEUP_ST_REG, PMU_EXT_WAKEUP_STATUS);
}
/**
* @brief Clear the ext1 wakeup source status
*/
static inline void pmu_ll_ext1_clear_wakeup_status(void)
{
REG_SET_BIT(PMU_EXT_WAKEUP_CNTL_REG, PMU_EXT_WAKEUP_STATUS_CLR);
}
/**
* @brief Set the wake-up LP_IO of the ext1 wake-up source
* @param io_mask wakeup LP_IO bitmap, bit 0~7 corresponds to LP_IO 0~7
* @param level_mask 0: Wake the chip when all selected GPIOs go low
* 1: Wake the chip when any of the selected GPIOs go high
*/
static inline void pmu_ll_ext1_set_wakeup_pins(uint32_t io_mask, int level_mask)
{
REG_SET_FIELD(PMU_EXT_WAKEUP_SEL_REG, PMU_EXT_WAKEUP_SEL, io_mask);
REG_SET_FIELD(PMU_EXT_WAKEUP_LV_REG, PMU_EXT_WAKEUP_LV, level_mask);
}
/**
* @brief Clear all ext1 wakup-source setting
*/
static inline void pmu_ll_ext1_clear_wakeup_pins(void)
{
REG_SET_FIELD(PMU_EXT_WAKEUP_SEL_REG, PMU_EXT_WAKEUP_SEL, 0);
}
/**
* @brief Get ext1 wakeup source setting
* @return The lower 8 bits of the returned value are the bitmap of
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
*/
static inline uint32_t pmu_ll_ext1_get_wakeup_pins(void)
{
return REG_GET_FIELD(PMU_EXT_WAKEUP_SEL_REG, PMU_EXT_WAKEUP_SEL);
}
#ifdef __cplusplus
}
+75 -2
View File
@@ -1,9 +1,82 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for PMU (ESP32-S31 specific part)
// TODO: ["ESP32S31"] IDF-14653
#include "soc/soc.h"
#include "esp_attr.h"
#include "hal/pmu_hal.h"
#include "hal/pmu_types.h"
void IRAM_ATTR pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle)
{
pmu_ll_hp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle);
pmu_ll_hp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle);
}
uint32_t IRAM_ATTR pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal)
{
uint32_t power_supply_wait_cycle = pmu_ll_hp_get_digital_power_supply_wait_cycle(hal->dev);
uint32_t power_up_wait_cycle = pmu_ll_hp_get_digital_power_up_wait_cycle(hal->dev);
return power_supply_wait_cycle + power_up_wait_cycle;
}
void IRAM_ATTR pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle)
{
pmu_ll_lp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle);
pmu_ll_lp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle);
}
uint32_t IRAM_ATTR pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal)
{
uint32_t power_supply_wait_cycle = pmu_ll_lp_get_digital_power_supply_wait_cycle(hal->dev);
uint32_t power_up_wait_cycle = pmu_ll_lp_get_digital_power_up_wait_cycle(hal->dev);
return power_supply_wait_cycle + power_up_wait_cycle;
}
void IRAM_ATTR pmu_hal_hp_set_control_ready_wait_cycle(pmu_hal_context_t *hal, uint32_t isolate_wait_cycle, uint32_t reset_wait_cycle)
{
pmu_ll_hp_set_isolate_wait_cycle(hal->dev, isolate_wait_cycle);
pmu_ll_hp_set_reset_wait_cycle(hal->dev, reset_wait_cycle);
}
void IRAM_ATTR pmu_hal_lp_set_control_ready_wait_cycle(pmu_hal_context_t *hal, uint32_t isolate_wait_cycle, uint32_t reset_wait_cycle)
{
pmu_ll_lp_set_isolate_wait_cycle(hal->dev, isolate_wait_cycle);
pmu_ll_lp_set_reset_wait_cycle(hal->dev, reset_wait_cycle);
}
void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal)
{
pmu_ll_hp_set_active_to_sleep_backup_enable(hal->dev);
pmu_ll_hp_set_sleep_to_active_backup_enable(hal->dev);
}
void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal)
{
pmu_ll_hp_set_sleep_to_active_backup_disable(hal->dev);
pmu_ll_hp_set_active_to_sleep_backup_disable(hal->dev);
}
void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal)
{
pmu_ll_hp_set_sleep_to_modem_backup_enable(hal->dev);
}
void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal)
{
pmu_ll_hp_set_sleep_to_modem_backup_disable(hal->dev);
}
void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal)
{
pmu_ll_hp_set_modem_to_active_backup_enable(hal->dev);
}
void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal)
{
pmu_ll_hp_set_modem_to_active_backup_disable(hal->dev);
}
+10 -1
View File
@@ -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
*/
@@ -43,6 +43,15 @@ typedef enum {
PMU_HP_PD_HPMEM = 2,
PMU_HP_PD_CPU = 3,
} pmu_hp_power_domain_t;
#elif SOC_IS(ESP32S31)
typedef enum {
PMU_HP_PD_TOP = 0, /*!< Power domain of digital top */
PMU_HP_PD_HPALIVE,
PMU_HP_PD_MODEMPWR,
PMU_HP_PD_HPCPU,
PMU_HP_PD_HPCNNT,
PMU_HP_PD_MODEM
} pmu_hp_power_domain_t;
#else
typedef enum {
PMU_HP_PD_TOP = 0, /*!< Power domain of digital top */
@@ -4,6 +4,9 @@ set(srcs
"rtc_clk.c"
"rtc_time.c"
"chip_info.c"
"pmu_param.c"
"pmu_init.c"
"pmu_sleep.c"
)
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
@@ -0,0 +1,208 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdlib.h>
#include <esp_types.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "soc/chip_revision.h"
#include "soc/soc.h"
#include "soc/pmu_struct.h"
#include "hal/efuse_hal.h"
#include "hal/pmu_hal.h"
#include "pmu_param.h"
#include "esp_private/esp_pmu.h"
#include "esp_hw_log.h"
ESP_HW_LOG_ATTR_TAG(TAG, "pmu_init");
typedef struct {
const pmu_hp_system_power_param_t *power;
const pmu_hp_system_clock_param_t *clock;
const pmu_hp_system_digital_param_t *digital;
const pmu_hp_system_analog_param_t *analog;
const pmu_hp_system_retention_param_t *retent;
} pmu_hp_system_param_t;
typedef struct {
const pmu_lp_system_power_param_t *power;
const pmu_lp_system_analog_param_t *analog;
} pmu_lp_system_param_t;
pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
{
/* It should be explicitly defined in the internal RAM, because this
* 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 };
return &pmu_context;
}
void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
{
const pmu_hp_system_power_param_t *power = param->power;
const pmu_hp_system_clock_param_t *clock = param->clock;
const pmu_hp_system_digital_param_t *dig = param->digital;
const pmu_hp_system_analog_param_t *anlg = param->analog;
const pmu_hp_system_retention_param_t *ret = param->retent;
assert(ctx->hal);
/* Default configuration of hp-system power in active, modem and sleep modes */
pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val);
pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val);
pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal);
/* Default configuration of hp-system clock in active, modem and sleep modes */
pmu_ll_hp_set_icg_func (ctx->hal->dev, mode, clock->icg_func.clock[0], clock->icg_func.clock[1]);
pmu_ll_hp_set_icg_apb (ctx->hal->dev, mode, clock->icg_apb.clock[0], clock->icg_apb.clock[1]);
pmu_ll_hp_set_icg_modem (ctx->hal->dev, mode, clock->icg_modem.code);
pmu_ll_hp_set_sysclk_nodiv (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_nodiv);
pmu_ll_hp_set_icg_sysclk_enable (ctx->hal->dev, mode, clock->sysclk.icg_sysclk_en);
pmu_ll_hp_set_sysclk_slp_sel (ctx->hal->dev, mode, clock->sysclk.sysclk_slp_sel);
pmu_ll_hp_set_icg_sysclk_slp_sel(ctx->hal->dev, mode, clock->sysclk.icg_slp_sel);
pmu_ll_hp_set_dig_sysclk (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_sel);
/* Default configuration of hp-system digital sub-system in active, modem
* and sleep modes */
pmu_ll_hp_set_c_channel_enable (ctx->hal->dev, mode, dig->syscntl.c_channel);
pmu_ll_hp_set_uart_wakeup_enable(ctx->hal->dev, mode, dig->syscntl.uart_wakeup_en);
pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, mode, dig->syscntl.lp_pad_hold_all);
pmu_ll_hp_set_hold_all_hp_pad (ctx->hal->dev, mode, dig->syscntl.hp_pad_hold_all);
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, mode, dig->syscntl.dig_pad_slp_sel);
pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, mode, dig->syscntl.dig_pause_wdt);
pmu_ll_hp_set_cpu_stall (ctx->hal->dev, mode, dig->syscntl.dig_cpu_stall);
/* Default configuration of hp-system analog sub-system in active, modem and
* sleep modes */
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);
if (mode == PMU_MODE_HP_ACTIVE) {
pmu_ll_hp_set_regulator_lp_dbias_voltage(ctx->hal->dev, mode, anlg->regulator0.lp_dbias_vol);
pmu_ll_hp_set_regulator_hp_dbias_voltage(ctx->hal->dev, mode, anlg->regulator0.hp_dbias_vol);
pmu_ll_hp_set_regulator_dbias_select (ctx->hal->dev, mode, anlg->regulator0.dbias_sel);
pmu_ll_hp_set_regulator_dbias_init (ctx->hal->dev, mode, anlg->regulator0.dig_dbias_init);
}
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd);
pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias);
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd);
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias);
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias);
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
/* Default configuration of hp-system retention sub-system in active, modem
* and sleep modes */
pmu_ll_hp_set_retention_param(ctx->hal->dev, mode, ret->retention.val);
pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, ret->backup_clk[0], ret->backup_clk[1]);
/* Some PMU initial parameter configuration */
pmu_ll_imm_update_dig_icg_modem_code(ctx->hal->dev, true);
pmu_ll_imm_update_dig_icg_switch(ctx->hal->dev, true);
pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP);
}
void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
{
const pmu_lp_system_power_param_t *power = param->power;
const pmu_lp_system_analog_param_t *anlg = param->analog;
assert(ctx->hal);
/* Default configuration of lp-system power in active and sleep modes */
pmu_ll_lp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val);
pmu_ll_lp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val);
pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, power->xtal.xpd_xtal);
/* Default configuration of lp-system analog sub-system in active and
* sleep modes */
pmu_ll_lp_set_bias_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.xpd_bias);
pmu_ll_lp_set_dbg_atten (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.dbg_atten);
pmu_ll_lp_set_current_power_off (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.pd_cur);
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.bias_sleep);
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias);
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_xpd);
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_dbias);
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
}
static inline void pmu_power_domain_force_default(pmu_context_t *ctx)
{
assert(ctx);
// for bypass reserved power domain
const pmu_hp_power_domain_t pmu_hp_domains[] = {
PMU_HP_PD_TOP,
PMU_HP_PD_HPALIVE,
PMU_HP_PD_MODEMPWR,
PMU_HP_PD_HPCPU,
PMU_HP_PD_HPCNNT,
PMU_HP_PD_MODEM
};
for (uint8_t idx = 0; idx < (sizeof(pmu_hp_domains) / sizeof(pmu_hp_power_domain_t)); idx++) {
pmu_ll_hp_set_power_force_power_up (ctx->hal->dev, pmu_hp_domains[idx], false);
pmu_ll_hp_set_power_force_no_reset (ctx->hal->dev, pmu_hp_domains[idx], false);
pmu_ll_hp_set_power_force_no_isolate(ctx->hal->dev, pmu_hp_domains[idx], false);
pmu_ll_hp_set_power_force_power_down(ctx->hal->dev, pmu_hp_domains[idx], false);
pmu_ll_hp_set_power_force_isolate (ctx->hal->dev, pmu_hp_domains[idx], false);
pmu_ll_hp_set_power_force_reset (ctx->hal->dev, pmu_hp_domains[idx], false);
}
/* Isolate all memory banks while sleeping, avoid memory leakage current */
pmu_ll_hp_set_memory_no_isolate (ctx->hal->dev, 0);
pmu_ll_lp_set_power_force_power_up (ctx->hal->dev, false);
pmu_ll_lp_set_power_force_no_reset (ctx->hal->dev, false);
pmu_ll_lp_set_power_force_no_isolate(ctx->hal->dev, false);
pmu_ll_lp_set_power_force_power_down(ctx->hal->dev, false);
pmu_ll_lp_set_power_force_isolate (ctx->hal->dev, false);
pmu_ll_lp_set_power_force_reset (ctx->hal->dev, false);
}
static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
{
param->power = pmu_hp_system_power_param_default(mode);
param->clock = pmu_hp_system_clock_param_default(mode);
param->digital = pmu_hp_system_digital_param_default(mode);
param->analog = pmu_hp_system_analog_param_default(mode);
param->retent = pmu_hp_system_retention_param_default(mode);
}
static void pmu_hp_system_init_default(pmu_context_t *ctx)
{
assert(ctx);
pmu_hp_system_param_t param = { 0 };
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
pmu_hp_system_param_default(mode, &param);
pmu_hp_system_init(ctx, mode, &param);
}
}
static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
{
param->power = pmu_lp_system_power_param_default(mode);
param->analog = pmu_lp_system_analog_param_default(mode);
}
static void pmu_lp_system_init_default(pmu_context_t *ctx)
{
assert(ctx);
pmu_lp_system_param_t param;
for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) {
pmu_lp_system_param_default(mode, &param);
pmu_lp_system_init(ctx, mode, &param);
}
}
void pmu_init(void)
{
pmu_hp_system_init_default(PMU_instance());
pmu_lp_system_init_default(PMU_instance());
pmu_power_domain_force_default(PMU_instance());
}
@@ -0,0 +1,431 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdlib.h>
#include <esp_types.h>
#include "sdkconfig.h"
#include "soc/soc.h"
#include "pmu_param.h"
#include "soc/pmu_icg_mapping.h"
#include "esp_private/esp_pmu.h"
#include "hal/efuse_ll.h"
#include "hal/efuse_hal.h"
#include "esp_hw_log.h"
#include "soc/clk_tree_defs.h"
ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif
#define PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.vdd_spi_pd_en = 0, \
.pd_hp_alive_pd_en = 0, \
.hp_mem_dslp = 0, \
.hp_mem_pd_en = 0, \
.modem_top_pd_en = 0, \
.hp_cnnt_pd_en = 0, \
.hp_cpu_pd_en = 0, \
.modem_pwr_pd_en = 0, \
.top_pd_en = 0 \
}, \
.clk_power = { \
.i2c_iso_en = 0, \
.i2c_retention = 0, \
.xpd_bb_i2c = 1, \
.xpd_pll_i2c = 0xf, \
.xpd_pll = 0xf \
}, \
.xtal = { \
.xpd_xtal = 1 \
} \
}
#define PMU_HP_MODEM_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.vdd_spi_pd_en = 0, \
.pd_hp_alive_pd_en = 0, \
.hp_mem_dslp = 0, \
.hp_mem_pd_en = 0, \
.modem_top_pd_en = 0, \
.hp_cnnt_pd_en = 0, \
.hp_cpu_pd_en = 1, \
.modem_pwr_pd_en = 0, \
.top_pd_en = 0 \
}, \
.clk_power = { \
.i2c_iso_en = 0, \
.i2c_retention = 0, \
.xpd_bb_i2c = 1, \
.xpd_pll_i2c = 0xf, \
.xpd_pll = 0xf \
}, \
.xtal = { \
.xpd_xtal = 1 \
} \
}
#define PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.vdd_spi_pd_en = 1, \
.pd_hp_alive_pd_en = 1, \
.hp_mem_dslp = 1, \
.hp_mem_pd_en = 0, \
.modem_top_pd_en = 1, \
.hp_cnnt_pd_en = 1, \
.hp_cpu_pd_en = 1, \
.modem_pwr_pd_en = 0, \
.top_pd_en = 1 \
}, \
.clk_power = { \
.i2c_iso_en = 0, \
.i2c_retention = 0, \
.xpd_bb_i2c = 1, \
.xpd_pll_i2c = 0xf, \
.xpd_pll = 0xf \
}, \
.xtal = { \
.xpd_xtal = 0 \
} \
}
const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mode_t mode)
{
static const pmu_hp_system_power_param_t hp_power[] = {
PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT(),
PMU_HP_MODEM_POWER_CONFIG_DEFAULT(),
PMU_HP_SLEEP_POWER_CONFIG_DEFAULT()
};
assert(mode < ARRAY_SIZE(hp_power));
return &hp_power[mode];
}
#define PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT() { \
.icg_func.clock[0] = 0xffffffff, \
.icg_func.clock[1] = 0xffffffff, \
.icg_apb.clock[0] = 0xffffffff, \
.icg_apb.clock[1] = 0xffffffff, \
.icg_modem.code = PMU_HP_ICG_MODEM_CODE_ACTIVE, \
.sysclk = { \
.dig_sysclk_nodiv = 0, \
.icg_sysclk_en = 1, \
.sysclk_slp_sel = 0, \
.icg_slp_sel = 0, \
.dig_sysclk_sel = SOC_CPU_CLK_SRC_XTAL \
} \
}
#define PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT() { \
.icg_func.clock[0] = 0, \
.icg_func.clock[1] = 0, \
.icg_apb.clock[0] = 0, \
.icg_apb.clock[1] = 0, \
.icg_modem.code = PMU_HP_ICG_MODEM_CODE_MODEM, \
.sysclk = { \
.dig_sysclk_nodiv = 0, \
.icg_sysclk_en = 1, \
.sysclk_slp_sel = 1, \
.icg_slp_sel = 1, \
.dig_sysclk_sel = SOC_CPU_CLK_SRC_XTAL \
} \
}
#define PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() { \
.icg_func.clock[0] = 0, \
.icg_func.clock[1] = 0, \
.icg_apb.clock[0] = 0, \
.icg_apb.clock[1] = 0, \
.icg_modem.code = PMU_HP_ICG_MODEM_CODE_SLEEP, \
.sysclk = { \
.dig_sysclk_nodiv = 0, \
.icg_sysclk_en = 0, \
.sysclk_slp_sel = 1, \
.icg_slp_sel = 1, \
.dig_sysclk_sel = SOC_CPU_CLK_SRC_XTAL \
} \
}
const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mode_t mode)
{
static const pmu_hp_system_clock_param_t hp_clock[] = {
PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT(),
PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT(),
PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT()
};
assert(mode < ARRAY_SIZE(hp_clock));
return &hp_clock[mode];
}
#define PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT() { \
.syscntl = { \
.c_channel = 1, \
.uart_wakeup_en = 0, \
.lp_pad_hold_all = 0, \
.hp_pad_hold_all = 0, \
.dig_pad_slp_sel = 0, \
.dig_pause_wdt = 0, \
.dig_cpu_stall = 0 \
} \
}
#define PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT() { \
.syscntl = { \
.c_channel = 1, \
.uart_wakeup_en = 0, \
.lp_pad_hold_all = 0, \
.hp_pad_hold_all = 0, \
.dig_pad_slp_sel = 1, \
.dig_pause_wdt = 1, \
.dig_cpu_stall = 1 \
} \
}
#define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \
.syscntl = { \
.c_channel = 1, \
.uart_wakeup_en = 1, \
.lp_pad_hold_all = 0, \
.hp_pad_hold_all = 0, \
.dig_pad_slp_sel = 0, \
.dig_pause_wdt = 1, \
.dig_cpu_stall = 1 \
} \
}
const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp_mode_t mode)
{
static const pmu_hp_system_digital_param_t hp_digital[] = {
PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT(),
PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT(),
PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT()
};
assert(mode < ARRAY_SIZE(hp_digital));
return &hp_digital[mode];
}
#define PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \
.bias = { \
.xpd_bias = 1, \
.dbg_atten = 0x0, \
.pd_cur = 0, \
.bias_sleep = 0 \
}, \
.regulator0 = { \
.dig_dbias_init = 1, \
.lp_dbias_vol = 0xd, \
.hp_dbias_vol = 0x1c, \
.dbias_sel = 1, \
.slp_connect_en = 0, \
.slp_mem_xpd = 0, \
.slp_logic_xpd = 0, \
.xpd = 1, \
.slp_mem_dbias = 0, \
.slp_logic_dbias = 0, \
.dbias = HP_CALI_DBIAS_DEFAULT\
}, \
.regulator1 = { \
.drv_b = 0x0 \
} \
}
#define PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT() { \
.bias = { \
.xpd_bias = 0, \
.dbg_atten = 0x0, \
.pd_cur = 0, \
.bias_sleep = 0 \
}, \
.regulator0 = { \
.slp_connect_en = 0, \
.slp_mem_xpd = 0, \
.slp_logic_xpd = 0, \
.xpd = 1, \
.slp_mem_dbias = 0, \
.slp_logic_dbias = 0, \
.dbias = HP_CALI_DBIAS_DEFAULT\
}, \
.regulator1 = { \
.drv_b = 0x0 \
} \
}
#define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \
.bias = { \
.xpd_bias = 0, \
.dbg_atten = 0x0, \
.pd_cur = 0, \
.bias_sleep = 0 \
}, \
.regulator0 = { \
.slp_connect_en = 0, \
.slp_mem_xpd = 0, \
.slp_logic_xpd = 0, \
.xpd = 1, \
.slp_mem_dbias = 1, \
.slp_logic_dbias = 0, \
.dbias = 1 \
}, \
.regulator1 = { \
.drv_b = 0x0 \
} \
}
const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_mode_t mode)
{
static const pmu_hp_system_analog_param_t hp_analog[] = {
PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT(),
PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT(),
PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT()
};
assert(mode < ARRAY_SIZE(hp_analog));
return &hp_analog[mode];
}
#define PMU_HP_RETENTION_REGDMA_CONFIG(dir, entry) ((((dir)<<4) | (entry & 0xf)) & 0x1f)
#define PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT() { \
.retention = { \
.hp_sleep2active_backup_modem_clk_code = 2, \
.hp_modem2active_backup_modem_clk_code = 2, \
.hp_active_retention_mode = 0, \
.hp_sleep2active_retention_en = 0, \
.hp_modem2active_retention_en = 0, \
.hp_sleep2active_backup_clk_sel = 0, \
.hp_modem2active_backup_clk_sel = 0, \
.hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \
.hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \
.hp_sleep2active_backup_en = 0, \
.hp_modem2active_backup_en = 0, \
}, \
.backup_clk[0] = 0xffffffff, \
.backup_clk[1] = 0xffffffff, \
}
#define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \
.retention = { \
.hp_sleep2modem_backup_modem_clk_code = 1, \
.hp_modem_retention_mode = 0, \
.hp_sleep2modem_retention_en = 0, \
.hp_sleep2modem_backup_clk_sel = SOC_CPU_CLK_SRC_XTAL, \
.hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \
.hp_sleep2modem_backup_en = 0, \
}, \
.backup_clk[0] = 0xffffffff, \
.backup_clk[1] = 0xffffffff, \
}
#define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \
.retention = { \
.hp_modem2sleep_backup_modem_clk_code = 0, \
.hp_active2sleep_backup_modem_clk_code = 2, \
.hp_sleep_retention_mode = 0, \
.hp_modem2sleep_retention_en = 0, \
.hp_active2sleep_retention_en = 0, \
.hp_modem2sleep_backup_clk_sel = 0, \
.hp_active2sleep_backup_clk_sel = 0, \
.hp_modem2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 1), \
.hp_active2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 0), \
.hp_modem2sleep_backup_en = 0, \
.hp_active2sleep_backup_en = 0, \
}, \
.backup_clk[0] = 0xffffffff, \
.backup_clk[1] = 0xffffffff, \
}
const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode)
{
static const pmu_hp_system_retention_param_t hp_retention[] = {
PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT(),
PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT(),
PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT()
};
assert(mode < ARRAY_SIZE(hp_retention));
return &hp_retention[mode];
}
/** LP system default parameter */
#define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.mem_dslp = 0, \
.peri_pd_en = 0, \
}, \
.clk_power = { \
.xpd_xtal32k = 1, \
.xpd_rc32k = 1, \
.xpd_fosc = 1, \
.pd_osc = 0 \
} \
}
#define PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.mem_dslp = 0, \
.peri_pd_en = 0, \
}, \
.clk_power = { \
.xpd_xtal32k = 0, \
.xpd_rc32k = 0, \
.xpd_fosc = 0, \
.pd_osc = 0 \
}, \
.xtal = { \
.xpd_xtal = 0 \
} \
}
const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mode_t mode)
{
static const pmu_lp_system_power_param_t lp_power[] = {
PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT(),
PMU_LP_SLEEP_POWER_CONFIG_DEFAULT()
};
assert(mode < ARRAY_SIZE(lp_power));
return &lp_power[mode];
}
#define PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \
.regulator0 = { \
.slp_xpd = 0, \
.xpd = 1, \
.slp_dbias = 0, \
.dbias = LP_CALI_DBIAS_DEFAULT \
}, \
.regulator1 = { \
.drv_b = 0x0 \
} \
}
#define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \
.bias = { \
.xpd_bias = 0, \
.dbg_atten = 0, \
.pd_cur = 1, \
.bias_sleep = 1, \
}, \
.regulator0 = { \
.slp_xpd = 0, \
.xpd = 1, \
.slp_dbias = 0, \
.dbias = 12 \
}, \
.regulator1 = { \
.drv_b = 0x0 \
} \
}
const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode)
{
static const pmu_lp_system_analog_param_t lp_analog[] = {
PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT(),
PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT()
};
assert(mode < ARRAY_SIZE(lp_analog));
return &lp_analog[mode];
}
@@ -0,0 +1,361 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdlib.h>
#include <sys/param.h>
#include <esp_types.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/pmu_struct.h"
#include "esp_private/esp_pmu.h"
#include "pmu_param.h"
#include "hal/lp_aon_hal.h"
#include "hal/efuse_ll.h"
#include "hal/efuse_hal.h"
#include "esp_hw_log.h"
ESP_HW_LOG_ATTR_TAG(TAG, "pmu_sleep");
#define HP(state) (PMU_MODE_HP_ ## state)
#define LP(state) (PMU_MODE_LP_ ## state)
static bool s_pmu_sleep_regdma_backup_enabled;
void pmu_sleep_enable_regdma_backup(void)
{
if(!s_pmu_sleep_regdma_backup_enabled){
assert(PMU_instance()->hal);
/* entry 0, 1, 2 is used by pmu HP_SLEEP and HP_ACTIVE, HP_SLEEP
* and HP_MODEM or HP_MODEM and HP_ACTIVE states switching,
* respectively. entry 3 is reserved, not used yet! */
pmu_hal_hp_set_sleep_active_backup_enable(PMU_instance()->hal);
pmu_hal_hp_set_sleep_modem_backup_enable(PMU_instance()->hal);
pmu_hal_hp_set_modem_active_backup_enable(PMU_instance()->hal);
s_pmu_sleep_regdma_backup_enabled = true;
}
}
void pmu_sleep_disable_regdma_backup(void)
{
if(s_pmu_sleep_regdma_backup_enabled){
assert(PMU_instance()->hal);
pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal);
pmu_hal_hp_set_sleep_modem_backup_disable(PMU_instance()->hal);
pmu_hal_hp_set_modem_active_backup_disable(PMU_instance()->hal);
s_pmu_sleep_regdma_backup_enabled = false;
}
}
uint32_t pmu_sleep_calculate_lp_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* LP core hardware wait time, microsecond */
const int lp_wakeup_wait_time_us = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period);
const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
/* If XTAL is used as RTC_FAST clock source, it is started in LP_SLEEP -> LP_ACTIVE stage and the clock waiting time is counted into lp_hw_wait_time */
const int lp_clk_power_on_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && (sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->lp.xtal_wait_stable_time_us \
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
const int lp_control_wait_time_us = mc->lp.isolate_wait_time_us + mc->lp.reset_wait_time_us;
const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
+ lp_wakeup_wait_time_us + lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us \
+ mc->lp.power_up_wait_time_us + lp_control_wait_time_us;
return (uint32_t)lp_hw_wait_time_us;
}
uint32_t pmu_sleep_calculate_hp_hw_wait_time(uint32_t sleep_flags, uint32_t slowclk_period, uint32_t fastclk_period)
{
pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
/* HP core hardware wait time, microsecond */
const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us;
const int hp_control_wait_time_us = mc->hp.isolate_wait_time_us + mc->hp.reset_wait_time_us;
const int hp_regdma_wait_time_us = s_pmu_sleep_regdma_backup_enabled ? mc->hp.regdma_s2a_work_time_us : 0;
/* If XTAL is not used as RTC_FAST clock source, it is started in HP_SLEEP -> HP_ACTIVE stage and the clock waiting time is counted into hp_hw_wait_time */
const int hp_clock_wait_time_us = ((sleep_flags & PMU_SLEEP_PD_XTAL) && !(sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST)) \
? mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us \
: mc->hp.pll_wait_stable_time_us;
const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us \
+ hp_clock_wait_time_us + hp_control_wait_time_us;
return (uint32_t)hp_hw_wait_time_us;
}
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk_src_t slowclk_src, uint32_t slowclk_period, uint32_t fastclk_period)
{
const uint32_t lp_hw_wait_time_us = pmu_sleep_calculate_lp_hw_wait_time(sleep_flags, slowclk_period, fastclk_period);
const uint32_t hp_hw_wait_time_us = pmu_sleep_calculate_hp_hw_wait_time(sleep_flags, slowclk_period, fastclk_period);
/* When the SOC wakeup (lp timer or GPIO wakeup) and Modem wakeup (Beacon wakeup) complete, the soc
* wakeup will be delayed until the RF is turned on in Modem state.
*
* modem wakeup TBTT, RF on by HW
* | |
* \|/ \|/
* PMU_HP_ACTIVE /------
* PMU_HP_MODEM /------------//////////////////
* PMU_HP_SLEEP ----------------------//////////////////
* /|\ /|\ /|\ /|\ /|\ /|\
* |<- some hw wait ->| | | |<- M2A switch ->|
* | slow cycles & | soc wakeup | |
* | FOSC cycles |<- S2M switch ->| |
* | |
* |<-- PMU guard time, also the maximum time for the SOC -->|
* | wake-up delay |
*/
#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP
pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
int min_slp_time_adjustment_us = 0;
#if SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED
if (slowclk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
const uint32_t slowclk_period_fixed = rtc_clk_freq_to_period(SOC_CLK_RC_SLOW_FREQ_APPROX);
const int min_slp_cycle_fixed = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period_fixed);
const int min_slp_cycle_calib = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period);
const int min_slp_cycle_diff = (min_slp_cycle_calib > min_slp_cycle_fixed) ? \
(min_slp_cycle_calib - min_slp_cycle_fixed) : (min_slp_cycle_fixed - min_slp_cycle_calib);
const int min_slp_time_diff = rtc_time_slowclk_to_us(min_slp_cycle_diff, slowclk_period_fixed);
min_slp_time_adjustment_us = (min_slp_cycle_calib > min_slp_cycle_fixed) ? min_slp_time_diff : -min_slp_time_diff;
}
#endif
const int rf_on_protect_time_us = mc->hp.regdma_rf_on_work_time_us;
const int total_hw_wait_time_us = lp_hw_wait_time_us + hp_hw_wait_time_us + mc->hp.clock_domain_sync_time_us + min_slp_time_adjustment_us;
#else
const int rf_on_protect_time_us = 0;
const int total_hw_wait_time_us = lp_hw_wait_time_us + hp_hw_wait_time_us;
#endif
return total_hw_wait_time_us + rf_on_protect_time_us;
}
#define rtc_time_us_to_fastclk(time_us, period) rtc_time_us_to_slowclk((time_us), (period))
static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
pmu_sleep_param_config_t *param,
pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
const uint32_t sleep_flags,
const uint32_t adjustment,
soc_rtc_slow_clk_src_t slowclk_src,
const uint32_t slowclk_period,
const uint32_t fastclk_period
)
{
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period);
param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_us, fastclk_period);
param->hp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_supply_wait_time_us, fastclk_period);
param->hp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_up_wait_time_us, fastclk_period);
param->hp_sys.pll_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.pll_wait_stable_time_us, fastclk_period);
param->hp_sys.isolate_wait_cycle = rtc_time_us_to_fastclk(mc->hp.isolate_wait_time_us, fastclk_period);
param->hp_sys.reset_wait_cycle = rtc_time_us_to_fastclk(mc->hp.reset_wait_time_us, fastclk_period);
param->lp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.min_slp_time_us, slowclk_period);
param->lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(mc->lp.analog_wait_time_us, slowclk_period);
param->lp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_supply_wait_time_us, fastclk_period);
param->lp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_up_wait_time_us, fastclk_period);
param->lp_sys.isolate_wait_cycle = rtc_time_us_to_fastclk(mc->lp.isolate_wait_time_us, fastclk_period);
param->lp_sys.reset_wait_cycle = rtc_time_us_to_fastclk(mc->lp.reset_wait_time_us, fastclk_period);
if (power->hp_sys.xtal.xpd_xtal) {
param->hp_lp.xtal_stable_wait_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.xtal_wait_stable_time_us, slowclk_period);
} else {
param->hp_lp.xtal_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_us, fastclk_period);
}
return param;
}
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,
soc_rtc_slow_clk_src_t slowclk_src,
uint32_t slowclk_period,
uint32_t fastclk_period,
bool dslp
)
{
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
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);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
config->analog = analog_default;
} else {
// Get light sleep digital_default
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
config->digital = digital_default;
// Get light sleep analog default
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
if (!(sleep_flags & PMU_SLEEP_PD_XTAL))
{
// Analog parameters in HP_SLEEP
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
analog_default.hp_sys.analog.dbg_atten = PMU_DBG_ATTEN_ACTIVE_DEFAULT;
analog_default.hp_sys.analog.dbias = HP_CALI_ACTIVE_DBIAS_DEFAULT;
// Analog parameters in LP_SLEEP
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;
}
config->analog = analog_default;
}
if (sleep_flags & RTC_SLEEP_XTAL_AS_RTC_FAST) {
// Keep XTAL on in HP_SLEEP state if it is the clock source of RTC_FAST
power_default.hp_sys.xtal.xpd_xtal = 1;
config->analog.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
config->analog.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
config->analog.hp_sys.analog.dbg_atten = PMU_DBG_ATTEN_ACTIVE_DEFAULT;
config->analog.hp_sys.analog.dbias = HP_CALI_ACTIVE_DBIAS_DEFAULT;
}
config->power = power_default;
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
config->param = *pmu_sleep_param_config_default(&param_default, &power_default, sleep_flags, adjustment, slowclk_src, slowclk_period, fastclk_period);
return config;
}
static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_config_t *power, bool dslp)
{
pmu_ll_hp_set_dig_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.dig_power.val);
pmu_ll_hp_set_clk_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.clk_power.val);
pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, HP(SLEEP), power->hp_sys.xtal.xpd_xtal);
pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].dig_power.val);
pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].clk_power.val);
pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].dig_power.val);
pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].clk_power.val);
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)
{
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_lp_pad (ctx->hal->dev, HP(SLEEP), dig->syscntl.lp_pad_hold_all);
pmu_ll_hp_set_c_channel_enable (ctx->hal->dev, HP(SLEEP), dig->syscntl.c_channel);
}
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_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);
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd);
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias);
pmu_ll_hp_set_dbg_atten (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbg_atten);
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias);
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias);
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b);
pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep);
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd);
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_xpd);
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_dbias);
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias);
pmu_ll_lp_set_dbg_atten (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbg_atten);
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.drv_b);
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_xpd);
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.xpd);
}
static void pmu_sleep_param_init(pmu_context_t *ctx, const pmu_sleep_param_config_t *param, bool dslp)
{
assert(ctx->hal);
pmu_ll_hp_set_min_sleep_cycle(ctx->hal->dev, param->hp_sys.min_slp_slow_clk_cycle);
pmu_ll_lp_set_min_sleep_cycle(ctx->hal->dev, param->lp_sys.min_slp_slow_clk_cycle);
pmu_ll_hp_set_analog_wait_target_cycle(ctx->hal->dev, param->hp_sys.analog_wait_target_cycle);
pmu_ll_lp_set_analog_wait_target_cycle(ctx->hal->dev, param->lp_sys.analog_wait_target_cycle);
pmu_hal_hp_set_digital_power_up_wait_cycle(ctx->hal, param->hp_sys.digital_power_supply_wait_cycle, param->hp_sys.digital_power_up_wait_cycle);
pmu_hal_lp_set_digital_power_up_wait_cycle(ctx->hal, param->lp_sys.digital_power_supply_wait_cycle, param->lp_sys.digital_power_up_wait_cycle);
pmu_hal_hp_set_control_ready_wait_cycle(ctx->hal, param->hp_sys.isolate_wait_cycle, param->hp_sys.reset_wait_cycle);
pmu_hal_lp_set_control_ready_wait_cycle(ctx->hal, param->lp_sys.isolate_wait_cycle, param->lp_sys.reset_wait_cycle);
pmu_ll_set_xtal_stable_wait_cycle(ctx->hal->dev, param->hp_lp.xtal_stable_wait_slow_clk_cycle);
pmu_ll_set_pll_stable_wait_cycle(ctx->hal->dev, param->hp_sys.pll_stable_wait_cycle);
}
bool pmu_sleep_pll_already_enabled(void)
{
return (pmu_ll_get_sysclk_sleep_select_state(PMU_instance()->hal->dev) != 0);
}
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_analog_init(PMU_instance(), &config->analog, dslp);
pmu_sleep_param_init(PMU_instance(), &config->param, dslp);
}
IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
{
lp_aon_hal_inform_wakeup_type(dslp);
pmu_ll_hp_set_wakeup_enable(&PMU, wakeup_opt);
pmu_ll_hp_set_reject_enable(&PMU, reject_opt);
pmu_ll_hp_clear_wakeup_intr_status(&PMU);
pmu_ll_hp_clear_reject_intr_status(&PMU);
pmu_ll_hp_clear_reject_cause(&PMU);
/* Start entry into sleep mode */
pmu_ll_hp_set_sleep_enable(&PMU);
while (!pmu_ll_hp_is_sleep_wakeup(&PMU) &&
!pmu_ll_hp_is_sleep_reject(&PMU)) {
;
}
return pmu_sleep_finish(dslp);
}
IRAM_ATTR uint32_t pmu_sleep_get_wakeup_cause(void)
{
return pmu_ll_hp_get_wakeup_cause(PMU_instance()->hal->dev);
}
IRAM_ATTR uint32_t pmu_sleep_get_reject_cause(void)
{
return pmu_ll_hp_get_reject_cause(PMU_instance()->hal->dev);
}
IRAM_ATTR bool pmu_sleep_finish(bool dslp)
{
#ifndef CONFIG_IDF_ENV_FPGA
// Wait eFuse memory update done.
while(efuse_ll_get_controller_state() != EFUSE_CONTROLLER_STATE_IDLE);
#endif
return pmu_ll_hp_is_sleep_reject(&PMU);
}
uint32_t pmu_sleep_get_wakup_retention_cost(void)
{
return 685;
}
@@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define PMU_SDIO_WAKEUP_EN BIT(0)
#define PMU_LP_CORE_WAKEUP_EN BIT(1)
#define PMU_GPIO_WAKEUP_EN BIT(2)
#define PMU_USB_WAKEUP_EN BIT(3)
#define PMU_UART4_WAKEUP_EN BIT(4)
#define PMU_UART3_WAKEUP_EN BIT(5)
#define PMU_UART2_WAKEUP_EN BIT(6)
#define PMU_UART1_WAKEUP_EN BIT(7)
#define PMU_UART0_WAKEUP_EN BIT(8)
#define PMU_LP_GPIO_WAKEUP_EN BIT(9)
#define PMU_LP_UART_WAKEUP_EN BIT(10)
#define PMU_TOUCH_WAKEUP_EN BIT(11)
#define PMU_EXT1_WAKEUP_EN BIT(12)
#define PMU_LP_TIMER_WAKEUP_EN BIT(13)
#define PMU_BOD_WAKEUP_EN BIT(14)
#define PMU_VBAT_UNDERVOLT_WAKEUP_EN BIT(15)
#define PMU_LP_CORE_TRAP_WAKEUP_EN BIT(16)
#define PMU_ETM_WAKEUP_EN BIT(17)
#define PMU_LP_TIMER1_WAKEUP_EN BIT(18)
#define PMU_LP_I2S_WAKEUP_EN BIT(19)
#define PMU_WIFI_SOC_WAKEUP_EN BIT(22)
#define PMU_WIFI_BEACON_WAKEUP_EN BIT(23)
#define PMU_BLE_SOC_WAKEUP_EN BIT(24)
// BIT order in PLL control registers in PMU
#define PMU_CPLL_CTRL BIT(0)
#define PMU_SPLL_CTRL BIT(1)
#define PMU_APLL_CTRL BIT(2)
#define PMU_SDIOPLL_CTRL BIT(3)
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,526 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <esp_types.h>
#include "soc/pmu_struct.h"
#include "hal/pmu_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
#define HP_CALI_DBIAS_DEFAULT 28
#define LP_CALI_DBIAS_DEFAULT 28
#define HP_CALI_DBIAS_SLP_1V1 22
#define LP_CALI_DBIAS_SLP_1V1 22
#define HP_CALI_ACTIVE_DBIAS_DEFAULT 24 // For HP regulator
// FOR XTAL FORCE PU IN SLEEP
#define PMU_PD_CUR_SLEEP_ON 0
#define PMU_BIASSLP_SLEEP_ON 0
// FOR BOTH LIGHTSLEEP & DEEPSLEEP
#define PMU_PD_CUR_SLEEP_DEFAULT 1
#define PMU_BIASSLP_SLEEP_DEFAULT 1
#define PMU_LP_XPD_SLEEP_DEFAULT 1
#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0
#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0
// FOR LIGHTSLEEP
#define PMU_HP_DRVB_LIGHTSLEEP 0
#define PMU_LP_DRVB_LIGHTSLEEP 0
#define PMU_HP_XPD_LIGHTSLEEP 1
#define PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT 0
#define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1
#define PMU_LP_DBIAS_LIGHTSLEEP_0V7 12
// FOR LIGHTSLEEP: XTAL FORCE PU
#define PMU_DBG_ATTEN_ACTIVE_DEFAULT 0
// FOR DEEPSLEEP
#define PMU_DBG_HP_DEEPSLEEP 0
#define PMU_HP_XPD_DEEPSLEEP 0
#define PMU_LP_DRVB_DEEPSLEEP 0
#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12
#define PMU_LP_DBIAS_DEEPSLEEP_0V7 23
typedef struct {
pmu_hp_dig_power_reg_t dig_power;
pmu_hp_clk_power_reg_t clk_power;
pmu_hp_xtal_reg_t xtal;
} pmu_hp_system_power_param_t;
const pmu_hp_system_power_param_t* pmu_hp_system_power_param_default(pmu_hp_mode_t mode);
typedef struct {
struct {
uint32_t clock[2];
} icg_func;
struct {
uint32_t clock[2];
} icg_apb;
pmu_hp_icg_modem_reg_t icg_modem;
pmu_hp_sysclk_reg_t sysclk;
} pmu_hp_system_clock_param_t;
const pmu_hp_system_clock_param_t* pmu_hp_system_clock_param_default(pmu_hp_mode_t mode);
typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
} pmu_hp_system_digital_param_t;
const pmu_hp_system_digital_param_t* pmu_hp_system_digital_param_default(pmu_hp_mode_t mode);
typedef struct {
pmu_hp_bias_reg_t bias;
pmu_hp_regulator0_reg_t regulator0;
pmu_hp_regulator1_reg_t regulator1;
} pmu_hp_system_analog_param_t;
const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mode_t mode);
typedef struct {
pmu_hp_backup_reg_t retention;
uint32_t backup_clk[2];
} pmu_hp_system_retention_param_t;
const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode);
typedef struct {
pmu_lp_dig_power_reg_t dig_power;
pmu_lp_clk_power_reg_t clk_power;
pmu_lp_xtal_reg_t xtal;
} pmu_lp_system_power_param_t;
const pmu_lp_system_power_param_t* pmu_lp_system_power_param_default(pmu_lp_mode_t mode);
typedef struct {
pmu_lp_bias_reg_t bias;
pmu_lp_regulator0_reg_t regulator0;
pmu_lp_regulator1_reg_t regulator1;
} pmu_lp_system_analog_param_t;
const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode);
/* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/
typedef union {
struct {
uint32_t reserved_0 : 20;
uint32_t vdd_spi_pd_en : 1;
uint32_t pd_hp_alive_pd_en : 1;
uint32_t mem_dslp : 1;
uint32_t pd_hp_mem_pd_en : 4;
uint32_t pd_modem_top_pd_en: 1;
uint32_t pd_hp_cnnt_pd_en : 1;
uint32_t pd_hp_cpu_pd_en : 1;
uint32_t pd_modem_pwr_pd_en: 1;
uint32_t pd_top_pd_en : 1;
};
struct {
uint32_t reserved_1 : 19;
uint32_t xpd_xtalx2 : 1;
uint32_t i2c_iso_en : 1;
uint32_t i2c_retention : 1;
uint32_t xpd_bb_i2c : 1;
uint32_t xpd_pll_i2c : 4;
uint32_t xpd_pll : 4;
uint32_t reserved_2 : 1;
};
struct {
uint32_t reserved_3 : 31;
uint32_t xpd_xtal : 1;
};
uint32_t val;
} pmu_hp_power_t;
typedef union {
struct {
uint32_t reserved_0 : 30;
uint32_t mem_dslp : 1;
uint32_t peri_pd_en : 1;
};
struct {
uint32_t reserved_1 : 28;
uint32_t xpd_xtal32k: 1;
uint32_t xpd_rc32k : 1;
uint32_t xpd_fosc : 1;
uint32_t pd_osc : 1;
};
struct {
uint32_t reserved_2 : 31;
uint32_t xpd_xtal : 1;
};
uint32_t val;
} pmu_lp_power_t;
typedef struct {
struct {
uint32_t reserved_0 : 25;
uint32_t xpd_bias : 1;
uint32_t dbg_atten : 4;
uint32_t pd_cur : 1;
uint32_t bias_sleep : 1;
};
struct {
uint32_t reserved_1 : 15;
uint32_t slp_connect_en : 1;
uint32_t slp_mem_xpd : 1;
uint32_t slp_logic_xpd : 1;
uint32_t xpd : 1;
uint32_t slp_mem_dbias : 4;
uint32_t slp_logic_dbias: 4;
uint32_t dbias : 5;
};
struct {
uint32_t reserved_2 : 8;
uint32_t drv_b : 24;
};
} pmu_hp_analog_t;
typedef struct {
struct {
uint32_t reserved_0: 25;
uint32_t xpd_bias : 1;
uint32_t dbg_atten : 4;
uint32_t pd_cur : 1;
uint32_t bias_sleep: 1;
};
struct {
uint32_t reserved_1: 21;
uint32_t slp_xpd : 1;
uint32_t xpd : 1;
uint32_t slp_dbias : 4;
uint32_t dbias : 5;
};
struct {
uint32_t reserved_2: 28;
uint32_t drv_b : 4;
};
} pmu_lp_analog_t;
typedef struct {
uint32_t modem_wakeup_wait_cycle;
uint16_t analog_wait_target_cycle;
uint16_t digital_power_down_wait_cycle;
uint16_t digital_power_supply_wait_cycle;
uint16_t digital_power_up_wait_cycle;
uint16_t pll_stable_wait_cycle;
uint8_t modify_icg_cntl_wait_cycle;
uint8_t switch_icg_cntl_wait_cycle;
uint8_t min_slp_slow_clk_cycle;
uint8_t isolate_wait_cycle;
uint8_t reset_wait_cycle;
} pmu_hp_param_t;
typedef struct {
uint16_t digital_power_supply_wait_cycle;
uint8_t min_slp_slow_clk_cycle;
uint8_t analog_wait_target_cycle;
uint8_t digital_power_down_wait_cycle;
uint8_t digital_power_up_wait_cycle;
uint8_t isolate_wait_cycle;
uint8_t reset_wait_cycle;
} pmu_lp_param_t;
typedef struct {
union {
uint16_t xtal_stable_wait_slow_clk_cycle;
uint16_t xtal_stable_wait_cycle;
};
} pmu_hp_lp_param_t;
#define PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES (10)
#define PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES (10)
#define PMU_HP_WAKEUP_DELAY_CYCLES (0)
#define PMU_HP_XTAL_STABLE_WAIT_CYCLES (3155) /* Not used, Fast OSC as PMU work clock source is about 201 us, corresponding to PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES */
#define PMU_HP_PLL_STABLE_WAIT_CYCLES (2)
#define PMU_HP_ANALOG_WAIT_TARGET_CYCLES (23) /* Slow OSC as PMU work clock source is about 400 us */
#define PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32)
#define PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES (32)
#define PMU_HP_MODEM_WAKEUP_WAIT_CYCLES (20700) /* Fast OSC as PMU work clock source is about 1318.6 us */
#define PMU_LP_WAKEUP_DELAY_CYCLES (0)
#define PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES (30) /* Slow OSC as PMU slow clock source is about 201 us */
#define PMU_LP_ANALOG_WAIT_TARGET_CYCLES (23) /* Slow OSC as PMU slow clock source is about 154 us */
#define PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */
#define PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */
#define PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US (500) /* Slow OSC as PMU slow clock source in deepsleep is about 500 us */
typedef struct {
struct {
pmu_hp_power_t dig_power;
pmu_hp_power_t clk_power;
pmu_hp_power_t xtal;
} hp_sys;
struct {
pmu_lp_power_t dig_power;
pmu_lp_power_t clk_power;
pmu_lp_power_t xtal;
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_power_config_t;
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.dig_power = { \
.vdd_spi_pd_en = ((sleep_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \
.pd_hp_alive_pd_en = 0, \
.pd_modem_top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
.pd_hp_cnnt_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CNNT) ? 1 : 0, \
.pd_hp_cpu_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
.pd_modem_pwr_pd_en = 0, \
.pd_top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
.pd_hp_mem_pd_en = 0, \
.mem_dslp = 0, \
}, \
.clk_power = { \
.xpd_xtalx2 = 0, \
.i2c_iso_en = 1, \
.i2c_retention = 1, \
.xpd_bb_i2c = 0, \
.xpd_pll_i2c = 0, \
.xpd_pll = 0 \
}, \
.xtal = { \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.dig_power = { \
.peri_pd_en = 0, \
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = 1 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.dig_power = { \
.peri_pd_en = ((sleep_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_xtal32k = ((sleep_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((sleep_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((sleep_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
}, \
.xtal = { \
.xpd_xtal = ((sleep_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
} \
}
typedef struct {
pmu_hp_sys_cntl_reg_t syscntl;
} pmu_sleep_digital_config_t;
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 0, \
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.c_channel = (sleep_flags & PMU_SLEEP_PD_TOP) ? 0 : 1 \
} \
}
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.syscntl = { \
.dig_pad_slp_sel = 0, \
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
.c_channel = (sleep_flags & PMU_SLEEP_PD_TOP) ? 0 : 1 \
} \
}
typedef struct {
struct {
pmu_hp_analog_t analog;
} hp_sys;
struct {
pmu_lp_analog_t analog;
} lp_sys[PMU_MODE_LP_MAX];
} pmu_sleep_analog_config_t;
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.xpd = PMU_HP_XPD_LIGHTSLEEP, \
.dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \
.dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6 \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.analog = { \
.slp_xpd = 0, \
.slp_dbias = 0, \
.xpd = 1, \
.dbias = 29, \
.drv_b = 0x0 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.analog = { \
.drv_b = PMU_LP_DRVB_LIGHTSLEEP, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \
.slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \
.xpd = PMU_LP_XPD_SLEEP_DEFAULT, \
.dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \
.dbias = PMU_LP_DBIAS_LIGHTSLEEP_0V7 \
} \
} \
}
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.analog = { \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.xpd = PMU_HP_XPD_DEEPSLEEP, \
.dbg_atten = PMU_DBG_HP_DEEPSLEEP \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.analog = { \
.xpd = 1, \
.dbias = 0x1a, \
.slp_xpd = 0, \
.slp_dbias = 0, \
.drv_b = 0x7 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.analog = { \
.drv_b = PMU_LP_DRVB_DEEPSLEEP, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \
.slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \
.xpd = PMU_LP_XPD_SLEEP_DEFAULT, \
.dbg_atten = PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT, \
.dbias = PMU_LP_DBIAS_DEEPSLEEP_0V7 \
} \
} \
}
typedef struct {
pmu_hp_param_t hp_sys;
pmu_lp_param_t lp_sys;
pmu_hp_lp_param_t hp_lp;
} pmu_sleep_param_config_t;
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags) { \
.hp_sys = { \
.min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \
.analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \
.digital_power_supply_wait_cycle = PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \
.digital_power_up_wait_cycle = PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES, \
.modem_wakeup_wait_cycle = PMU_HP_MODEM_WAKEUP_WAIT_CYCLES, \
.pll_stable_wait_cycle = PMU_HP_PLL_STABLE_WAIT_CYCLES \
}, \
.lp_sys = { \
.min_slp_slow_clk_cycle = PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES, \
.analog_wait_target_cycle = PMU_LP_ANALOG_WAIT_TARGET_CYCLES, \
.digital_power_supply_wait_cycle = PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \
.digital_power_up_wait_cycle = PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES \
}, \
.hp_lp = { \
.xtal_stable_wait_slow_clk_cycle = PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES \
} \
}
typedef struct {
pmu_sleep_power_config_t power;
pmu_sleep_digital_config_t digital;
pmu_sleep_analog_config_t analog;
pmu_sleep_param_config_t param;
} pmu_sleep_config_t;
typedef struct pmu_sleep_machine_constant {
struct {
uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */
uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */
uint8_t reserved0;
uint16_t reserved1;
uint16_t analog_wait_time_us; /* LP LDO power up wait time (unit: microsecond) */
uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */
uint8_t clk_switch_cycle; /* Clock switch to FOSC (unit: slow clock cycle) */
uint8_t clk_power_on_wait_cycle; /* Clock power on wait cycle (unit: slow clock cycle) */
uint8_t isolate_wait_time_us; /* Waiting for all isolate signals to be ready (unit: microsecond) */
uint8_t reset_wait_time_us; /* Waiting for all reset signals to be ready (unit: microsecond) */
uint16_t power_supply_wait_time_us; /* (unit: microsecond) */
uint16_t power_up_wait_time_us; /* (unit: microsecond) */
} lp;
struct {
uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */
uint16_t clock_domain_sync_time_us; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */
uint16_t system_dfs_up_work_time_us; /* System DFS up scaling work time (unit: microsecond) */
uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */
uint8_t isolate_wait_time_us; /* Waiting for all isolate signals to be ready (unit: microsecond) */
uint8_t reset_wait_time_us; /* Waiting for all reset signals to be ready (unit: microsecond) */
uint16_t power_supply_wait_time_us; /* (unit: microsecond) */
uint16_t power_up_wait_time_us; /* (unit: microsecond) */
uint16_t regdma_s2m_work_time_us; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */
uint16_t regdma_s2a_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */
uint16_t regdma_m2a_work_time_us; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */
uint16_t regdma_a2s_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */
uint16_t regdma_rf_on_work_time_us; /* The REGDMA work time of RF enable (unit: microsecond) */
uint16_t regdma_rf_off_work_time_us; /* The REGDMA work time of RF disable (unit: microsecond) */
uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */
uint16_t pll_wait_stable_time_us; /* PLL stabilization wait time (unit: microsecond) */
} hp;
} pmu_sleep_machine_constant_t;
#define PMU_SLEEP_MC_DEFAULT() { \
.lp = { \
.min_slp_time_us = 450, \
.wakeup_wait_cycle = 4, \
.analog_wait_time_us = 154, \
.xtal_wait_stable_time_us = 250, \
.clk_switch_cycle = 1, \
.clk_power_on_wait_cycle = 1, \
.isolate_wait_time_us = 1, \
.reset_wait_time_us = 1, \
.power_supply_wait_time_us = 2, \
.power_up_wait_time_us = 2 \
}, \
.hp = { \
.min_slp_time_us = 450, \
.clock_domain_sync_time_us = 150, \
.system_dfs_up_work_time_us = 124, \
.analog_wait_time_us = 154, \
.isolate_wait_time_us = 1, \
.reset_wait_time_us = 1, \
.power_supply_wait_time_us = 2, \
.power_up_wait_time_us = 2, \
.regdma_s2m_work_time_us = 172, \
.regdma_s2a_work_time_us = 685, \
.regdma_m2a_work_time_us = 278, \
.regdma_a2s_work_time_us = 382, \
.regdma_rf_on_work_time_us = 70, \
.regdma_rf_off_work_time_us = 23, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 50 \
} \
}
#ifdef __cplusplus
}
#endif
@@ -33,6 +33,7 @@
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h"
#include "esp_private/esp_pmu.h"
#include "esp_rom_serial_output.h"
#include "esp_rom_sys.h"
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for PMU
#pragma once
#include "soc/soc_caps.h"
#include "hal/pmu_ll.h"
#include "hal/pmu_types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
pmu_dev_t *dev;
} pmu_hal_context_t;
void pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle);
uint32_t pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal);
void pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle);
uint32_t pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal);
void pmu_hal_hp_set_control_ready_wait_cycle(pmu_hal_context_t *hal, uint32_t isolate_wait_cycle, uint32_t reset_wait_cycle);
void pmu_hal_lp_set_control_ready_wait_cycle(pmu_hal_context_t *hal, uint32_t isolate_wait_cycle, uint32_t reset_wait_cycle);
void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal);
void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal);
#ifdef __cplusplus
}
#endif
@@ -1703,10 +1703,6 @@ config SOC_PM_EXT1_WAKEUP_BY_PMU
bool
default y
config SOC_PM_SUPPORT_WIFI_WAKEUP
bool
default y
config SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP
bool
default y
@@ -653,7 +653,6 @@
#define SOC_PM_SUPPORT_EXT1_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (1) /*!<Supports one bit per pin to configure the EXT1 trigger level */
#define SOC_PM_EXT1_WAKEUP_BY_PMU (1)
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
#define SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP (1) /*!<Supports waking up from touch pad trigger */
#define SOC_PM_SUPPORT_LP_UART_WAKEUP (1)
#define SOC_PM_SUPPORT_CPU_PD (1)
@@ -51,6 +51,10 @@ config SOC_SYSTIMER_SUPPORTED
bool
default y
config SOC_PMU_SUPPORTED
bool
default y
config SOC_RTC_TIMER_SUPPORTED
bool
default y
@@ -415,6 +419,106 @@ config SOC_RCC_IS_INDEPENDENT
bool
default y
config SOC_PM_SUPPORT_EXT1_WAKEUP
bool
default y
config SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN
bool
default y
config SOC_PM_EXT1_WAKEUP_BY_PMU
bool
default y
config SOC_PM_SUPPORT_WIFI_WAKEUP
bool
default y
config SOC_PM_SUPPORT_BEACON_WAKEUP
bool
default y
config SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP
bool
default y
config SOC_PM_SUPPORT_XTAL32K_PD
bool
default y
config SOC_PM_SUPPORT_RC32K_PD
bool
default y
config SOC_PM_SUPPORT_RC_FAST_PD
bool
default y
config SOC_PM_SUPPORT_VDDSDIO_PD
bool
default y
config SOC_PM_SUPPORT_TOP_PD
bool
default y
config SOC_PM_SUPPORT_HP_AON_PD
bool
default y
config SOC_PM_SUPPORT_CNNT_PD
bool
default y
config SOC_PM_SUPPORT_RTC_PERIPH_PD
bool
default y
config SOC_PM_SUPPORT_MODEM_PD
bool
default y
config SOC_PM_SUPPORT_MAC_BB_PD
bool
default y
config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
bool
default y
config SOC_PM_CPU_RETENTION_BY_SW
bool
default y
config SOC_PM_CACHE_RETENTION_BY_PAU
bool
default y
config SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN
bool
default y
config SOC_PM_PAU_LINK_NUM
int
default 5
config SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE
bool
default y
config SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC
int
default 4
config SOC_PM_MODEM_RETENTION_BY_REGDMA
bool
default y
config SOC_PM_RETENTION_MODULE_NUM
int
default 64
config SOC_LP_TIMER_BIT_WIDTH_LO
int
default 32
+36 -1
View File
@@ -72,7 +72,8 @@
// #define SOC_SECURE_BOOT_SUPPORTED 1 // TODO: [ESP32S31] IDF-14629
// #define SOC_BOD_SUPPORTED 1 // TODO: [ESP32S31] IDF-14658
// #define SOC_APM_SUPPORTED 1 // TODO: [ESP32S31] IDF-14620
// #define SOC_PMU_SUPPORTED 1 // TODO: [ESP32S31] IDF-14642
// #define SOC_PAU_SUPPORTED 1 // TODO: [ESP32S31] IDF-14582
#define SOC_PMU_SUPPORTED 1
#define SOC_RTC_TIMER_SUPPORTED 1
// #define SOC_ULP_LP_UART_SUPPORTED 1 // TODO: [ESP32S31] IDF-14634
// #define SOC_LP_GPIO_MATRIX_SUPPORTED 1 // TODO: [ESP32S31] IDF-14785
@@ -285,6 +286,40 @@
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control has own registers for each module */
/*-------------------------- Power Management CAPS ----------------------------*/
#define SOC_PM_SUPPORT_EXT1_WAKEUP (1)
#define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (1) /*!<Supports one bit per pin to configure the EXT1 trigger level */
#define SOC_PM_EXT1_WAKEUP_BY_PMU (1)
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
#define SOC_PM_SUPPORT_BEACON_WAKEUP (1)
#define SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP (1) /*!<Supports waking up from touch pad trigger */
// #define SOC_PM_SUPPORT_CPU_PD (1) // TODO: [ESP32S31] IDF-14647
#define SOC_PM_SUPPORT_XTAL32K_PD (1)
#define SOC_PM_SUPPORT_RC32K_PD (1)
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
#define SOC_PM_SUPPORT_TOP_PD (1)
#define SOC_PM_SUPPORT_HP_AON_PD (1)
#define SOC_PM_SUPPORT_CNNT_PD (1)
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
#define SOC_PM_SUPPORT_MODEM_PD (1) /*!<modem includes BLE and 15.4 and wifi*/
#define SOC_PM_SUPPORT_MAC_BB_PD (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)
#define SOC_PM_CACHE_RETENTION_BY_PAU (1)
#define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1)
#define SOC_PM_PAU_LINK_NUM (5)
#define SOC_PM_PAU_REGDMA_LINK_CONFIGURABLE (1)
#define SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC (4) // The range of values for the link index is [0, SOC_PM_PAU_LINK_NUM)
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (1)
// #define SOC_PM_SUPPORT_PMU_MODEM_STATE (1) // TODO: [ESP32S31] IDF-14582
#define SOC_PM_RETENTION_MODULE_NUM (64)
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part
#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part