Merge branch 'feat/esp32h21_system_sleep_pmu' into 'master'

Stage 3: Support esp32h21 DFS & PMU & LP Timer & Clock domain

Closes PM-349 and PM-350

See merge request espressif/esp-idf!37632
This commit is contained in:
Li Shuai
2025-03-17 18:11:49 +08:00
21 changed files with 2647 additions and 257 deletions

View File

@@ -33,11 +33,13 @@ if(NOT non_os_build)
"sar_periph_ctrl_common.c" "sar_periph_ctrl_common.c"
"port/${target}/io_mux.c" "port/${target}/io_mux.c"
"port/${target}/esp_clk_tree.c" "port/${target}/esp_clk_tree.c"
"port/esp_clk_tree_common.c"
"dma/esp_dma_utils.c" "dma/esp_dma_utils.c"
"dma/gdma_link.c" "dma/gdma_link.c"
"spi_bus_lock.c" "spi_bus_lock.c"
"clk_utils.c") "clk_utils.c")
if(CONFIG_SOC_CLK_TREE_SUPPORTED)
list(APPEND srcs "port/esp_clk_tree_common.c")
endif()
if(CONFIG_SOC_GPSPI_SUPPORTED) if(CONFIG_SOC_GPSPI_SUPPORTED)
list(APPEND srcs "spi_share_hw_ctrl.c") list(APPEND srcs "spi_share_hw_ctrl.c")
endif() endif()
@@ -58,7 +60,7 @@ if(NOT non_os_build)
"sleep_gpio.c" "sleep_gpio.c"
"sleep_event.c" "sleep_event.c"
) )
if(CONFIG_SOC_PAU_SUPPORTED) if(CONFIG_SOC_PAU_SUPPORTED AND CONFIG_SOC_PM_SUPPORT_TOP_PD)
list(APPEND srcs "sleep_system_peripheral.c") list(APPEND srcs "sleep_system_peripheral.c")
endif() endif()
endif() endif()
@@ -171,12 +173,6 @@ set(public_include_dirs "include" "include/soc" "include/soc/${target}"
"dma/include" "ldo/include" "debug_probe/include" "dma/include" "ldo/include" "debug_probe/include"
"mspi_timing_tuning/include" "power_supply/include") "mspi_timing_tuning/include" "power_supply/include")
if(CONFIG_IDF_TARGET_ESP32H21)
list(REMOVE_ITEM srcs
"sleep_modes.c" # TODO: [ESP32H21] IDF-11515, IDF-11517
)
endif()
idf_component_register(SRCS ${srcs} idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include_dirs} INCLUDE_DIRS ${public_include_dirs}
PRIV_INCLUDE_DIRS port/include include/esp_private PRIV_INCLUDE_DIRS port/include include/esp_private

View File

@@ -6,6 +6,7 @@ if(CONFIG_SOC_PMU_SUPPORTED)
list(APPEND srcs "rtc_clk_init.c" list(APPEND srcs "rtc_clk_init.c"
"pmu_param.c" "pmu_param.c"
"pmu_init.c" "pmu_init.c"
"pmu_sleep.c"
) )
endif() endif()

View File

@@ -0,0 +1,16 @@
choice XTAL_FREQ
prompt "Main XTAL frequency"
default XTAL_FREQ_32
help
This option selects the operating frequency of the XTAL (crystal) clock used to drive the ESP target.
The selected value MUST reflect the frequency of the given hardware.
config XTAL_FREQ_32
bool "32 MHz"
endchoice
# soc_xtal_freq_t enum in soc/clk_tree_defs.h lists the XTAL frequencies can be supported
# SOC_XTAL_SUPPORT_XXX in soc_caps.h lists the XTAL frequencies already supported
config XTAL_FREQ
int
default 32 if XTAL_FREQ_32

View File

@@ -0,0 +1,251 @@
/*
* SPDX-FileCopyrightText: 2025 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/soc.h"
#include "soc/pmu_struct.h"
#include "hal/pmu_hal.h"
#include "pmu_param.h"
#include "esp_private/esp_pmu.h"
#include "soc/regi2c_pmu.h"
#include "soc/regi2c_bias.h"
#include "regi2c_ctrl.h"
static __attribute__((unused)) const char *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;
pmu_hp_system_analog_param_t *analog; //param determined at runtime
const pmu_hp_system_retention_param_t *retent;
} pmu_hp_system_param_t;
typedef struct {
const pmu_lp_system_power_param_t *power;
pmu_lp_system_analog_param_t *analog; //param determined at runtime
} 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, const 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);
pmu_ll_hp_set_icg_apb (ctx->hal->dev, mode, clock->icg_apb);
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_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_dcdc_ccm_enable (ctx->hal->dev, mode, anlg->bias.dcdc_ccm_enb);
pmu_ll_hp_set_dig_reg_dpcur_bias (ctx->hal->dev, mode, anlg->bias.dig_reg_dpcur_bias);
pmu_ll_hp_set_dig_reg_dsfmos (ctx->hal->dev, mode, anlg->bias.dig_reg_dsfmos);
pmu_ll_hp_set_dcm_vset (ctx->hal->dev, mode, anlg->bias.dcm_vset);
pmu_ll_hp_set_dcm_mode (ctx->hal->dev, mode, anlg->bias.dcm_mode);
pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias);
pmu_ll_hp_set_trx_xpd (ctx->hal->dev, mode, anlg->bias.xpd_trx);
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.dbias_init);
}
pmu_ll_hp_set_regulator_power_detect_bypass(ctx->hal->dev, mode, anlg->regulator0.power_det_bypass);
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd);
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd);
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.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_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_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);
/* 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, const 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 */
if (mode == PMU_MODE_LP_SLEEP) {
pmu_ll_lp_set_dcdc_ccm_enable (ctx->hal->dev, mode, anlg->bias.dcdc_ccm_enb);
pmu_ll_lp_set_dig_reg_dpcur_bias(ctx->hal->dev, mode, anlg->bias.dig_reg_dpcur_bias);
pmu_ll_lp_set_dig_reg_dsfmos (ctx->hal->dev, mode, anlg->bias.dig_reg_dsfmos);
pmu_ll_lp_set_dcm_vset (ctx->hal->dev, mode, anlg->bias.dcm_vset);
pmu_ll_lp_set_dcm_mode (ctx->hal->dev, mode, anlg->bias.dcm_mode);
pmu_ll_lp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias);
pmu_ll_lp_set_current_power_off (ctx->hal->dev, mode, anlg->bias.pd_cur);
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep);
}
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_xpd);
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_dbias);
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.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_CPU,
PMU_HP_PD_WIFI
};
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)
{
assert (param->analog);
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); //copy default value
param->retent = pmu_hp_system_retention_param_default(mode);
if (mode == PMU_MODE_HP_ACTIVE || mode == PMU_MODE_HP_MODEM) {
param->analog->regulator0.dbias = get_act_hp_dbias();
}
}
static void pmu_hp_system_init_default(pmu_context_t *ctx)
{
assert(ctx);
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
pmu_hp_system_analog_param_t analog = {};
pmu_hp_system_param_t param = {.analog = &analog};
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)
{
assert (param->analog);
param->power = pmu_lp_system_power_param_default(mode);
*param->analog = *pmu_lp_system_analog_param_default(mode); //copy default value
if (mode == PMU_MODE_LP_ACTIVE) {
param->analog->regulator0.dbias = get_act_lp_dbias();
}
}
static void pmu_lp_system_init_default(pmu_context_t *ctx)
{
assert(ctx);
for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) {
pmu_lp_system_analog_param_t analog = {};
pmu_lp_system_param_t param = {.analog = &analog};
pmu_lp_system_param_default(mode, &param);
pmu_lp_system_init(ctx, mode, &param);
}
}
void pmu_init()
{
/* No peripheral reg i2c power up required on the target */
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG_SLP, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG_SLP, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_REG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_DIG_REG, 0);
REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_TRX, 0);
WRITE_PERI_REG(PMU_POWER_PD_TOP_CNTL_REG, 0);
WRITE_PERI_REG(PMU_POWER_PD_HPAON_CNTL_REG, 0);
WRITE_PERI_REG(PMU_POWER_PD_HPCPU_CNTL_REG, 0);
WRITE_PERI_REG(PMU_POWER_PD_HPPERI_RESERVE_REG, 0);
WRITE_PERI_REG(PMU_POWER_PD_HPWIFI_CNTL_REG, 0);
WRITE_PERI_REG(PMU_POWER_PD_LPPERI_CNTL_REG, 0);
pmu_hp_system_init_default(PMU_instance());
pmu_lp_system_init_default(PMU_instance());
pmu_power_domain_force_default(PMU_instance());
}

View File

@@ -0,0 +1,502 @@
/*
* SPDX-FileCopyrightText: 2025 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"
static __attribute__((unused)) const char *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_flash_mode = 0, \
.mem_dslp = 0, \
.mem_pd_en = 0, \
.wifi_pd_en = 0, \
.cpu_pd_en = 0, \
.aon_pd_en = 0, \
.top_pd_en = 0 \
}, \
.clk_power = { \
.i2c_iso_en = 0, \
.i2c_retention = 0, \
.xpd_bb_i2c = 1, \
.xpd_bbpll_i2c = 1, \
.xpd_bbpll = 1 \
}, \
.xtal = { \
.xpd_xtalx2 = 1, \
.xpd_xtal = 1 \
} \
}
#define PMU_HP_MODEM_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.vdd_flash_mode = 0, \
.mem_dslp = 1, \
.mem_pd_en = 0, \
.wifi_pd_en = 0, \
.cpu_pd_en = 1, \
.aon_pd_en = 0, \
.top_pd_en = 0 \
}, \
.clk_power = { \
.i2c_iso_en = 0, \
.i2c_retention = 0, \
.xpd_bb_i2c = 1, \
.xpd_bbpll_i2c = 1, \
.xpd_bbpll = 1 \
}, \
.xtal = { \
.xpd_xtalx2 = 0, \
.xpd_xtal = 1 \
} \
}
#define PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.vdd_flash_mode = 1, \
.mem_dslp = 0, \
.mem_pd_en = 0, \
.wifi_pd_en = 1, \
.cpu_pd_en = 1, \
.aon_pd_en = 0, \
.top_pd_en = 1 \
}, \
.clk_power = { \
.i2c_iso_en = 1, \
.i2c_retention = 0, \
.xpd_bb_i2c = 0, \
.xpd_bbpll_i2c = 0, \
.xpd_bbpll = 0, \
}, \
.xtal = { \
.xpd_xtalx2 = 0, \
.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 = 0xffffffff, \
.icg_apb = 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 = 0, \
.icg_apb = 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_PLL \
} \
}
#define PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() { \
.icg_func = 0, \
.icg_apb = 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 = { \
.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 = { \
.uart_wakeup_en = 1, \
.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 = { \
.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 = { \
.dcdc_ccm_enb = 1, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 2, \
.dig_reg_dsfmos = 10, \
.dcm_vset = 22, \
.dcm_mode = 2, \
.xpd_trx = 1, \
.xpd_bias = 1, \
.discnnt_dig_rtc = 0, \
.pd_cur = 0, \
.bias_sleep = 0 \
}, \
.regulator0 = { \
.power_det_bypass = 0, \
.lp_dbias_vol = 0xd, \
.hp_dbias_vol = 0x1c, \
.dbias_sel = 1, \
.dbias_init = 1, \
.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 = 0x1a \
} \
}
#define PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT() { \
.bias = { \
.dcdc_ccm_enb = 1, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 3, \
.dig_reg_dsfmos = 12, \
.dcm_vset = 20, \
.dcm_mode = 1, \
.xpd_trx = 1, \
.xpd_bias = 1, \
.discnnt_dig_rtc = 0, \
.pd_cur = 0, \
.bias_sleep = 0 \
}, \
.regulator0 = { \
.power_det_bypass = 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 = 0x1b \
} \
}
#define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \
.bias = { \
.dcdc_ccm_enb = 1, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 1, \
.dig_reg_dsfmos = 8, \
.dcm_vset = 0, \
.dcm_mode = 0, \
.xpd_trx = 0, \
.xpd_bias = 0, \
.discnnt_dig_rtc = 0, \
.pd_cur = 1, \
.bias_sleep = 1 \
}, \
.regulator0 = { \
.power_det_bypass = 0, \
.slp_mem_xpd = 0, \
.slp_logic_xpd = 0, \
.xpd = 1, \
.slp_mem_dbias = 0, \
.slp_logic_dbias = 0, \
.dbias = 0 \
}, \
.regulator1 = { \
.drv_b = 0x13 \
} \
}
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 = 3, \
.hp_modem2active_backup_modem_clk_code = 1, \
.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 = 0xffffffff, \
}
#define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \
.retention = { \
.hp_sleep2modem_backup_modem_clk_code = 3, \
.hp_sleep2modem_backup_clk_sel = 0, \
.hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \
.hp_sleep2modem_backup_en = 0, \
}, \
.backup_clk = 0xffffffff, \
}
#define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \
.retention = { \
.hp_modem2sleep_backup_modem_clk_code = 3, \
.hp_active2sleep_backup_modem_clk_code = 3, \
.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 = 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 = { \
.vdd_io_mode = 3, \
.bod_source_sel = 0, \
.vddbat_mode = 2, \
.mem_dslp = 0, \
.peri_pd_en = 0, \
}, \
.clk_power = { \
.xpd_lppll = 0, \
.xpd_xtal32k = 1, \
.xpd_rc32k = 1, \
.xpd_fosc = 1, \
.pd_osc = 0 \
} \
}
#define PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() { \
.dig_power = { \
.vdd_io_mode = 5, \
.bod_source_sel = 0, \
.vddbat_mode = 1, \
.mem_dslp = 1, \
.peri_pd_en = 0, \
}, \
.clk_power = { \
.xpd_lppll = 0, \
.xpd_xtal32k = 0, \
.xpd_rc32k = 0, \
.xpd_fosc = 0, \
.pd_osc = 0 \
}, \
.xtal = { \
.xpd_xtalx2 = 0, \
.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 = 0 \
} \
}
#define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \
.bias = { \
.dcdc_ccm_enb = 0, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 3, \
.dig_reg_dsfmos = 5, \
.dcm_vset = 0, \
.dcm_mode = 0, \
.xpd_bias = 0, \
.discnnt_dig_rtc = 0, \
.pd_cur = 1, \
.bias_sleep = 1 \
}, \
.regulator0 = { \
.slp_xpd = 0, \
.xpd = 1, \
.slp_dbias = 0, \
.dbias = 1 \
}, \
.regulator1 = { \
.drv_b = 9 \
} \
}
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];
}
uint32_t get_act_hp_dbias(void)
{
/* hp_cali_dbias is read from efuse to ensure that the hp_active_voltage is close to 0.93V */
// TODO: PM-373
//unsigned blk_version = efuse_hal_blk_version();
uint32_t hp_cali_dbias = HP_CALI_DBIAS_DEFAULT;
//if (blk_version >= 3) {
// hp_cali_dbias = efuse_ll_get_active_hp_dbias();
// if (hp_cali_dbias != 0) {
// //efuse dbias need to add 2 to meet the CPU frequency switching
// if (hp_cali_dbias + 2 > 31) {
// hp_cali_dbias = 31;
// } else {
// hp_cali_dbias += 2;
// }
// } else {
// hp_cali_dbias = HP_CALI_DBIAS_DEFAULT;
// ESP_HW_LOGD(TAG, "hp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %d\n", blk_version);
// }
//} else {
// ESP_HW_LOGD(TAG, "blk_version is less than 3, act dbias not burnt in efuse\n");
//}
return hp_cali_dbias;
}
uint32_t get_act_lp_dbias(void)
{
/* lp_cali_dbias are read from efuse to ensure that the lp_active_voltage is close to 0.925V */
// TODO: PM-373
//unsigned blk_version = efuse_hal_blk_version();
uint32_t lp_cali_dbias = LP_CALI_DBIAS_DEFAULT;
//if (blk_version >= 3) {
// lp_cali_dbias = efuse_ll_get_active_lp_dbias();
// if (lp_cali_dbias != 0) {
// //efuse dbias need to add 2 to meet the CPU frequency switching
// if (lp_cali_dbias + 2 > 31) {
// lp_cali_dbias = 31;
// } else {
// lp_cali_dbias += 2;
// }
// } else {
// lp_cali_dbias = LP_CALI_DBIAS_DEFAULT;
// ESP_HW_LOGD(TAG, "lp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %d\n", blk_version);
// }
//} else {
// ESP_HW_LOGD(TAG, "blk_version is less than 3, act dbias not burnt in efuse\n");
//}
return lp_cali_dbias;
}

View File

@@ -0,0 +1,277 @@
/*
* SPDX-FileCopyrightText: 2025 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 "hal/lp_aon_hal.h"
#include "esp_private/esp_pmu.h"
#include "pmu_param.h"
#include "hal/efuse_ll.h"
#include "hal/efuse_hal.h"
#include "esp_hw_log.h"
#include "soc/regi2c_bias.h"
#include "regi2c_ctrl.h"
static __attribute__((unused)) const char *TAG = "pmu_sleep";
#define HP(state) (PMU_MODE_HP_ ## state)
#define LP(state) (PMU_MODE_LP_ ## state)
uint32_t get_slp_lp_dbias(void)
{
/* pmu_lp_dbias_sleep_0v7 is read from efuse to ensure that the HP_LDO_voltage is close to 0.68V,
** and the LP_LDO_voltage is close to 0.73V
*/
// TODO: PM-373
uint32_t pmu_lp_dbias_sleep_0v7 = PMU_LP_DBIAS_SLEEP_0V7_DEFAULT;
//unsigned blk_version = efuse_hal_blk_version();
//if (blk_version >= 3) {
// pmu_lp_dbias_sleep_0v7 = efuse_ll_get_dslp_dbias();
// if (pmu_lp_dbias_sleep_0v7 == 0) {
// pmu_lp_dbias_sleep_0v7 = PMU_LP_DBIAS_SLEEP_0V7_DEFAULT;
// ESP_HW_LOGD(TAG, "slp dbias not burnt in efuse or wrong value was burnt in blk version: %d\n", blk_version);
// }
//} else {
// ESP_HW_LOGD(TAG, "blk_version is less than 3, slp dbias not burnt in efuse\n");
//}
return pmu_lp_dbias_sleep_0v7;
}
void pmu_sleep_enable_regdma_backup(void)
{
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);
}
void pmu_sleep_disable_regdma_backup(void)
{
assert(PMU_instance()->hal);
pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal);
}
uint32_t pmu_sleep_calculate_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;
/* LP core hardware wait time, microsecond */
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_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \
+ lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us + mc->lp.power_up_wait_time_us;
/* 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;
if (sleep_flags & PMU_SLEEP_PD_TOP) {
mc->hp.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PD_TOP_US;
} else {
mc->hp.regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PU_TOP_US;
}
const int hp_regdma_wait_time_us = mc->hp.regdma_s2a_work_time_us;
/* 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;
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;
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,
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->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);
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 adjustment,
uint32_t slowclk_period,
uint32_t fastclk_period,
bool dslp
)
{
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
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_period, fastclk_period);
if (dslp) {
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
config->analog = analog_default;
} else {
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags);
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
analog_default.hp_sys.analog.dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT;
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
if (!(sleep_flags & PMU_SLEEP_PD_XTAL)){
analog_default.hp_sys.analog.xpd_trx = PMU_XPD_TRX_SLEEP_ON;
analog_default.hp_sys.analog.dbias = get_act_hp_dbias();
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.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.dbias = get_act_lp_dbias();
} else if (!(sleep_flags & PMU_SLEEP_PD_RC_FAST)) {
analog_default.hp_sys.analog.dbias = get_act_hp_dbias();
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_act_lp_dbias();
}
config->analog = analog_default;
}
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);
}
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_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
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_hp_set_trx_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd_trx);
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_slp_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_xpd);
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.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_regulator_driver_bar (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.drv_b);
}
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);
}
void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp)
{
assert(PMU_instance());
pmu_sleep_power_init(PMU_instance(), &config->power, dslp);
if (!dslp) {
pmu_sleep_digital_init(PMU_instance(), &config->digital);
}
pmu_sleep_analog_init(PMU_instance(), &config->analog, dslp);
pmu_sleep_param_init(PMU_instance(), &config->param, dslp);
}
uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
{
assert(PMU_instance()->hal);
lp_aon_hal_inform_wakeup_type(dslp);
pmu_ll_hp_set_wakeup_enable(PMU_instance()->hal->dev, wakeup_opt);
pmu_ll_hp_set_reject_enable(PMU_instance()->hal->dev, reject_opt);
pmu_ll_hp_clear_wakeup_intr_status(PMU_instance()->hal->dev);
pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev);
pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev);
/* Start entry into sleep mode */
pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev);
while (!pmu_ll_hp_is_sleep_wakeup(PMU_instance()->hal->dev) &&
!pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
;
}
return pmu_sleep_finish(dslp);
}
bool pmu_sleep_finish(bool dslp)
{
(void)dslp;
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
}
uint32_t pmu_sleep_get_wakup_retention_cost(void)
{
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
return mc->hp.regdma_s2a_work_time_us;
}

View File

@@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define PMU_EXT0_WAKEUP_EN BIT(0)
#define PMU_EXT1_WAKEUP_EN BIT(1)
#define PMU_GPIO_WAKEUP_EN BIT(2)
#define PMU_LP_TIMER_WAKEUP_EN BIT(4)
#define PMU_UART0_WAKEUP_EN BIT(6)
#define PMU_UART1_WAKEUP_EN BIT(7)
#define PMU_BLE_SOC_WAKEUP_EN BIT(10)
#define PMU_USB_WAKEUP_EN BIT(14)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,561 @@
/*
* SPDX-FileCopyrightText: 2025 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 17
#define LP_CALI_DBIAS_DEFAULT 18
// FOR XTAL FORCE PU IN SLEEP
#define PMU_PD_CUR_SLEEP_ON 0
#define PMU_BIASSLP_SLEEP_ON 0
#define PMU_XPD_TRX_SLEEP_ON 1
// 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_XPD_TRX_SLEEP_DEFAULT 0
#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0
#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0
// FOR LIGHTSLEEP
#define PMU_HP_XPD_LIGHTSLEEP 1
#define PMU_HP_DRVB_LIGHTSLEEP 0xFFFFF8
#define PMU_LP_DRVB_LIGHTSLEEP 0
#define PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT 1
#define PMU_LP_DBIAS_SLEEP_0V7_DEFAULT 6
#define PMU_REGDMA_S2A_WORK_TIME_PD_TOP_US 0
// The current value of this depends on the restoration time overhead of the longest chain in regdma
#define PMU_REGDMA_S2A_WORK_TIME_PU_TOP_US 390
// FOR DEEPSLEEP
#define PMU_HP_XPD_DEEPSLEEP 0
#define PMU_LP_DRVB_DEEPSLEEP 7
uint32_t get_act_hp_dbias(void);
uint32_t get_act_lp_dbias(void);
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 {
uint32_t icg_func;
uint32_t 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;
} 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 reserved0 : 18;
uint32_t vdd_flash_mode: 4;
uint32_t mem_dslp : 1;
uint32_t mem_pd_en : 4;
uint32_t wifi_pd_en : 1;
uint32_t peri_pd_en : 1;
uint32_t cpu_pd_en : 1;
uint32_t aon_pd_en : 1;
uint32_t top_pd_en : 1;
};
struct {
uint32_t reserved1 : 26;
uint32_t i2c_iso_en : 1;
uint32_t i2c_retention: 1;
uint32_t xpd_bb_i2c : 1;
uint32_t xpd_bbpll_i2c: 1;
uint32_t xpd_bbpll : 1;
uint32_t reserved2 : 1;
};
struct {
uint32_t reserved3 : 30;
uint32_t xpd_xtalx2: 1;
uint32_t xpd_xtal : 1;
};
uint32_t val;
} pmu_hp_power_t;
typedef union {
struct {
uint32_t reserved0 : 23;
uint32_t vdd_io_mode : 4;
uint32_t bod_source_sel: 1;
uint32_t vddbat_mode : 2;
uint32_t mem_dslp : 1;
uint32_t peri_pd_en : 1;
};
struct {
uint32_t reserved1 : 27;
uint32_t xpd_lppll : 1;
uint32_t xpd_xtal32k: 1;
uint32_t xpd_rc32k : 1;
uint32_t xpd_fosc : 1;
uint32_t pd_osc : 1;
};
struct {
uint32_t reserved2 : 30;
uint32_t xpd_xtalx2: 1;
uint32_t xpd_xtal : 1;
};
uint32_t val;
} pmu_lp_power_t;
typedef struct {
struct {
uint32_t reserved0 : 9;
uint32_t dcdc_ccm_enb : 1;
uint32_t dcdc_clear_rdy : 1;
uint32_t dig_reg_dpcur_bias: 2;
uint32_t dig_reg_dsfmos : 4;
uint32_t dcm_vset : 5;
uint32_t dcm_mode : 2;
uint32_t xpd_trx : 1;
uint32_t xpd_bias : 1;
uint32_t reserved1 : 3;
uint32_t discnnt_dig_rtc : 1;
uint32_t pd_cur : 1;
uint32_t bias_sleep : 1;
};
struct {
uint32_t power_det_bypass: 1;
uint32_t reserved2 : 15;
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 reserved3: 8;
uint32_t drv_b : 24;
};
} pmu_hp_analog_t;
typedef struct {
struct {
uint32_t reserved0 : 9;
uint32_t dcdc_ccm_enb : 1;
uint32_t dcdc_clear_rdy : 1;
uint32_t dig_reg_dpcur_bias: 2;
uint32_t dig_reg_dsfmos : 4;
uint32_t dcm_vset : 5;
uint32_t dcm_mode : 2;
uint32_t reserved1 : 1;
uint32_t xpd_bias : 1;
uint32_t reserved2 : 3;
uint32_t discnnt_dig_rtc : 1;
uint32_t pd_cur : 1;
uint32_t bias_sleep : 1;
};
struct {
uint32_t reserved3: 21;
uint32_t slp_xpd : 1;
uint32_t xpd : 1;
uint32_t slp_dbias: 4;
uint32_t dbias : 5;
};
struct {
uint32_t reserved4: 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 414 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 (1700) /* Fast OSC as PMU work clock source is about 223 us */
#define PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32)
#define PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES (32)
#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 (15) /* Slow OSC as PMU slow clock source is about 100 us */
#define PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 4 us */
#define PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 4 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(pd_flags) { \
.hp_sys = { \
.dig_power = { \
.vdd_flash_mode = 3, \
.wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
.cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
.top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
.mem_pd_en = 0, \
.mem_dslp = 0 \
}, \
.clk_power = { \
.i2c_iso_en = 1, \
.i2c_retention = 1, \
.xpd_bb_i2c = 0, \
.xpd_bbpll_i2c = 0, \
.xpd_bbpll = 0 \
}, \
.xtal = { \
.xpd_xtalx2 = 0, \
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.dig_power = { \
.vdd_io_mode = 5, \
.bod_source_sel = 0, \
.vddbat_mode = 0, \
.peri_pd_en = 0, \
.mem_dslp = 0 \
}, \
.clk_power = { \
.xpd_lppll = 0, \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = 1 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.dig_power = { \
.vdd_io_mode = 11, \
.bod_source_sel = 0, \
.vddbat_mode = 1, \
.peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0,\
.mem_dslp = 1 \
}, \
.clk_power = { \
.xpd_lppll = 0, \
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
.xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
}, \
.xtal = { \
.xpd_xtalx2 = 0, \
.xpd_xtal = ((pd_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_LSLP_CONFIG_DEFAULT(pd_flags) { \
.syscntl = { \
.dig_pad_slp_sel = ((pd_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(pd_flags) { \
.hp_sys = { \
.analog = { \
.dcdc_ccm_enb = 1, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 2, \
.dig_reg_dsfmos = 10, \
.dcm_vset = 29, \
.dcm_mode = 2, \
.xpd_trx = PMU_XPD_TRX_SLEEP_DEFAULT, \
.xpd_bias = 1, \
.discnnt_dig_rtc = 0, \
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
.xpd = PMU_HP_XPD_LIGHTSLEEP, \
.dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT, \
.power_det_bypass = 0, \
.slp_mem_xpd = 1, \
.slp_logic_xpd = 1, \
.slp_mem_dbias = 13, \
.slp_logic_dbias = 10, \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.analog = { \
.slp_xpd = 1, \
.xpd = 1, \
.slp_dbias = 11, \
.dbias = 30, \
.drv_b = 9 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.analog = { \
.dcdc_ccm_enb = 0, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 0, \
.dig_reg_dsfmos = 0, \
.dcm_vset = 0, \
.dcm_mode = 0, \
.xpd_bias = 1, \
.discnnt_dig_rtc = 1, \
.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, \
.dbias = PMU_LP_DBIAS_SLEEP_0V7_DEFAULT \
} \
} \
}
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
.hp_sys = { \
.analog = { \
.dcdc_ccm_enb = 0, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 0, \
.dig_reg_dsfmos = 5, \
.dcm_vset = 10, \
.dcm_mode = 0, \
.xpd_trx = PMU_XPD_TRX_SLEEP_DEFAULT, \
.xpd_bias = 0, \
.discnnt_dig_rtc = 0, \
.drv_b = 0, \
.pd_cur = PMU_PD_CUR_SLEEP_ON, \
.bias_sleep = PMU_BIASSLP_SLEEP_ON, \
.xpd = PMU_HP_XPD_DEEPSLEEP, \
.dbias = 8, \
.power_det_bypass = 0, \
.slp_mem_xpd = 0, \
.slp_logic_xpd = 0, \
.slp_mem_dbias = 5, \
.slp_logic_dbias = 3 \
} \
}, \
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
.analog = { \
.slp_xpd = 1, \
.xpd = 1, \
.slp_dbias = 11, \
.dbias = 30, \
.drv_b = 9 \
} \
}, \
.lp_sys[PMU_MODE_LP_SLEEP] = { \
.analog = { \
.dcdc_ccm_enb = 0, \
.dcdc_clear_rdy = 0, \
.dig_reg_dpcur_bias = 0, \
.dig_reg_dsfmos = 0, \
.dcm_vset = 0, \
.dcm_mode = 0, \
.xpd_bias = 1, \
.discnnt_dig_rtc = 1, \
.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, \
.dbias = PMU_LP_DBIAS_SLEEP_0V7_DEFAULT \
} \
} \
}
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(pd_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, \
.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) */
uint16_t reserved0;
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 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_s2a_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) 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 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, \
.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, \
.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_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_PD_TOP_US, \
.regdma_a2s_work_time_us = 0, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
} \
}
#ifdef __cplusplus
}
#endif

View File

@@ -108,9 +108,12 @@
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h" #include "esp32h2/rom/rtc.h"
#include "esp32h2/rom/cache.h" #include "esp32h2/rom/cache.h"
#include "esp32h2/rom/rtc.h"
#include "soc/extmem_reg.h" #include "soc/extmem_reg.h"
#include "hal/gpio_ll.h" #include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32H21
#include "esp32h21/rom/rtc.h"
#include "esp32h21/rom/cache.h"
#include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/rtc.h" #include "esp32p4/rom/rtc.h"
#include "hal/gpio_ll.h" #include "hal/gpio_ll.h"
@@ -167,6 +170,9 @@
#elif CONFIG_IDF_TARGET_ESP32H2 #elif CONFIG_IDF_TARGET_ESP32H2
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118) #define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
#elif CONFIG_IDF_TARGET_ESP32H21
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32P4
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (324) #define DEFAULT_SLEEP_OUT_OVERHEAD_US (324)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (240) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (240)
@@ -1636,10 +1642,11 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void)
esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
{ {
#if CONFIG_SOC_CLK_TREE_SUPPORTED
if (time_in_us > ((BIT64(SOC_LP_TIMER_BIT_WIDTH_LO + SOC_LP_TIMER_BIT_WIDTH_HI) - 1) / esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX)) * MHZ ) { if (time_in_us > ((BIT64(SOC_LP_TIMER_BIT_WIDTH_LO + SOC_LP_TIMER_BIT_WIDTH_HI) - 1) / esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX)) * MHZ ) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
#endif
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN; s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
s_config.sleep_duration = time_in_us; s_config.sleep_duration = time_in_us;
return ESP_OK; return ESP_OK;

View File

@@ -374,19 +374,19 @@ static void IRAM_ATTR esp_pm_execute_exit_sleep_callbacks(int64_t sleep_time_us)
} }
#endif #endif
static esp_err_t esp_pm_sleep_configure(const void *vconfig) static esp_err_t esp_pm_sleep_configure(const esp_pm_config_t *config)
{ {
esp_err_t err = ESP_OK; esp_err_t err = ESP_OK;
const esp_pm_config_t* config = (const esp_pm_config_t*) vconfig;
#if ESP_SLEEP_POWER_DOWN_CPU #if ESP_SLEEP_POWER_DOWN_CPU && CONFIG_SOC_LIGHT_SLEEP_SUPPORTED
err = sleep_cpu_configure(config->light_sleep_enable); err = sleep_cpu_configure(config->light_sleep_enable);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
#endif #endif
#if CONFIG_SOC_LIGHT_SLEEP_SUPPORTED
err = sleep_modem_configure(config->max_freq_mhz, config->min_freq_mhz, config->light_sleep_enable); err = sleep_modem_configure(config->max_freq_mhz, config->min_freq_mhz, config->light_sleep_enable);
#endif
return err; return err;
} }

View File

@@ -30,6 +30,7 @@
#include "esp32h2/rom/rtc.h" #include "esp32h2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H21 #elif CONFIG_IDF_TARGET_ESP32H21
#include "esp32h21/rom/rtc.h" #include "esp32h21/rom/rtc.h"
#include "esp_private/esp_pmu.h"
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/rtc.h" #include "esp32p4/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C5 #elif CONFIG_IDF_TARGET_ESP32C5

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -24,6 +24,7 @@
#include "soc/lp_clkrst_reg.h" #include "soc/lp_clkrst_reg.h"
#include "soc/pcr_reg.h" #include "soc/pcr_reg.h"
#include "hal/wdt_hal.h" #include "hal/wdt_hal.h"
#include "esp_private/esp_modem_clock.h"
#include "esp_private/periph_ctrl.h" #include "esp_private/periph_ctrl.h"
#include "esp_private/esp_clk.h" #include "esp_private/esp_clk.h"
#include "esp_private/esp_pmu.h" #include "esp_private/esp_pmu.h"
@@ -79,6 +80,7 @@ __attribute__((weak)) void esp_clk_init(void)
wdt_hal_write_protect_enable(&rtc_wdt_ctx); wdt_hal_write_protect_enable(&rtc_wdt_ctx);
#endif #endif
modem_clock_deselect_all_module_lp_clock_source();
#if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS) #if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS)
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K); select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K);
#elif defined(CONFIG_RTC_CLK_SRC_EXT_OSC) #elif defined(CONFIG_RTC_CLK_SRC_EXT_OSC)
@@ -118,9 +120,6 @@ __attribute__((weak)) void esp_clk_init(void)
// Re calculate the ccount to make time calculation correct. // Re calculate the ccount to make time calculation correct.
esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz); esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz);
// Set crypto clock (`clk_sec`) to use 96M PLL clock
REG_SET_FIELD(PCR_SEC_CONF_REG, PCR_SEC_CLK_SEL, 0x3);
} }
static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src) static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src)
@@ -165,6 +164,15 @@ static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src)
} }
rtc_clk_slow_src_set(rtc_slow_clk_src); rtc_clk_slow_src_set(rtc_slow_clk_src);
// Disable unused clock sources after clock source switching is complete.
// Regardless of the clock source selection, the internal 136K clock source will always keep on.
if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_XTAL32K && rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
rtc_clk_32k_enable(false);
}
if (rtc_slow_clk_src != SOC_RTC_SLOW_CLK_SRC_RC32K) {
rtc_clk_rc32k_enable(false);
}
if (SLOW_CLK_CAL_CYCLES > 0) { if (SLOW_CLK_CAL_CYCLES > 0) {
/* TODO: 32k XTAL oscillator has some frequency drift at startup. /* TODO: 32k XTAL oscillator has some frequency drift at startup.
* Improve calibration routine to wait until the frequency is stable. * Improve calibration routine to wait until the frequency is stable.

View File

@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "hal/lp_aon_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
#define lp_aon_hal_inform_wakeup_type(dslp) lp_aon_ll_inform_wakeup_type(dslp)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,62 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-H2 LP_Timer register operations
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/lp_timer_struct.h"
#include "soc/lp_aon_reg.h"
#include "hal/lp_timer_types.h"
#include "hal/misc.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
FORCE_INLINE_ATTR void lp_timer_ll_set_alarm_target(lp_timer_dev_t *dev, uint8_t timer_id, uint64_t value)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->target[timer_id].hi, target_hi, (value >> 32) & 0xFFFF);
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->target[timer_id].lo, target_lo, value & 0xFFFFFFFF);
}
FORCE_INLINE_ATTR void lp_timer_ll_set_target_enable(lp_timer_dev_t *dev, uint8_t timer_id, bool en)
{
dev->target[timer_id].hi.enable = en;
}
FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_low(lp_timer_dev_t *dev, uint8_t timer_id)
{
return HAL_FORCE_READ_U32_REG_FIELD(dev->counter[timer_id].lo, counter_lo);
}
FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_high(lp_timer_dev_t *dev, uint8_t timer_id)
{
return HAL_FORCE_READ_U32_REG_FIELD(dev->counter[timer_id].hi, counter_hi);
}
FORCE_INLINE_ATTR void lp_timer_ll_counter_snapshot(lp_timer_dev_t *dev)
{
dev->update.update = 1;
}
FORCE_INLINE_ATTR void lp_timer_ll_clear_alarm_intr_status(lp_timer_dev_t *dev)
{
dev->int_clr.alarm = 1;
}
FORCE_INLINE_ATTR void lp_timer_ll_clear_overflow_intr_status(lp_timer_dev_t *dev)
{
dev->int_clr.overflow = 1;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2025 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);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,719 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-H21 PMU register operations
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc.h"
#include "esp_attr.h"
#include "hal/assert.h"
#include "soc/pmu_struct.h"
#include "hal/pmu_types.h"
#include "hal/misc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set the power domain that needs to be powered down in the digital power
*
* @param hw Beginning address of the peripheral registers.
* @param mode The pmu mode
* @param flag Digital power domain flag
*
* @return None
*/
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_func)
{
hw->hp_sys[mode].icg_func = icg_func;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_apb(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t bitmap)
{
hw->hp_sys[mode].icg_apb = bitmap;
}
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_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_dcdc_ccm_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool enable)
{
hw->hp_sys[mode].bias.dcdc_ccm_enb = enable;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_reg_dpcur_bias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t bias)
{
hw->hp_sys[mode].bias.dig_reg_dpcur_bias = bias;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_reg_dsfmos(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t value)
{
hw->hp_sys[mode].bias.dig_reg_dsfmos = value;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dcm_vset(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t value)
{
hw->hp_sys[mode].bias.dcm_vset = value;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_dcm_mode(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dcm_mode)
{
hw->hp_sys[mode].bias.dcm_mode = dcm_mode;
}
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_trx_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_trx)
{
hw->hp_sys[mode].bias.xpd_trx = xpd_trx;
}
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_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.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.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.hp_sleep2active_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.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.hp_active2sleep_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_func)
{
hw->hp_sys[mode].backup_clk = icg_func;
}
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_power_detect_bypass(pmu_dev_t *hw, pmu_hp_mode_t mode, bool bypass)
{
hw->hp_sys[mode].regulator0.power_det_bypass = bypass;
}
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.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 slp_xpd)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].xtal.xpd_xtal = slp_xpd;
}
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_dcdc_ccm_enable(pmu_dev_t *hw, pmu_lp_mode_t mode, bool enable)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.dcdc_ccm_enb = enable;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_dig_reg_dpcur_bias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t value)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.dig_reg_dpcur_bias = value;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_dig_reg_dsfmos(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t value)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.dig_reg_dsfmos = value;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_dcm_vset(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t value)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.dcm_vset = value;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_dcm_mode(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t dcm_mode)
{
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
hw->lp_sys[mode].bias.dcm_mode = dcm_mode;
}
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_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 flag)
{
hw->imm.clk_power.val = flag;
}
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_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_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_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_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_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_pd = fpd;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_reset(pmu_dev_t *hw, bool rst)
{
hw->power.lp_peri.force_reset = rst;
}
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_isolate(pmu_dev_t *hw, bool iso)
{
hw->power.lp_peri.force_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_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_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_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_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.cntl1.slp_reject_en = 1;
}
FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_disable(pmu_dev_t *hw)
{
hw->wakeup.cntl1.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 cycle)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wakeup.cntl3, hp_min_slp_val, 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 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_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 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_lp_set_isolate_wait_cycle(pmu_dev_t *hw, uint32_t isolate_wait_cycle)
{
hw->power.wait_timer2.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.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.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.hp_rst_wait_timer = reset_wait_cycle;
}
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 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;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,62 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for PMU (ESP32-H2 specific part)
#include "soc/soc.h"
#include "esp_attr.h"
#include "hal/pmu_hal.h"
#include "hal/pmu_types.h"
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)
{
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 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 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 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 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 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);
}

View File

@@ -165,7 +165,7 @@ if(CONFIG_SOC_SDIO_SLAVE_SUPPORTED)
list(APPEND srcs "${target_folder}/sdio_slave_periph.c") list(APPEND srcs "${target_folder}/sdio_slave_periph.c")
endif() endif()
if(CONFIG_SOC_PAU_SUPPORTED AND CONFIG_SOC_LIGHT_SLEEP_SUPPORTED) if(CONFIG_SOC_PAU_SUPPORTED AND CONFIG_SOC_LIGHT_SLEEP_SUPPORTED AND CONFIG_SOC_PM_SUPPORT_TOP_PD)
list(APPEND srcs "${target_folder}/system_retention_periph.c") list(APPEND srcs "${target_folder}/system_retention_periph.c")
endif() endif()

View File

@@ -831,10 +831,6 @@ config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
bool bool
default y default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y
config SOC_CLK_XTAL32K_SUPPORTED config SOC_CLK_XTAL32K_SUPPORTED
bool bool
default y default y

View File

@@ -54,8 +54,8 @@
// #define SOC_SECURE_BOOT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11500 // #define SOC_SECURE_BOOT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11500
// #define SOC_BOD_SUPPORTED 1 //TODO: [ESP32H21] IDF-11530 // #define SOC_BOD_SUPPORTED 1 //TODO: [ESP32H21] IDF-11530
// #define SOC_APM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11494 // #define SOC_APM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11494
// #define SOC_PMU_SUPPORTED 1 //TODO: [ESP32H21] IDf-11522 // #define SOC_PMU_SUPPORTED 1
// #define SOC_LP_TIMER_SUPPORTED 1 //TODO: [ESP32H21] IDF-11512 // #define SOC_LP_TIMER_SUPPORTED 1
// #define SOC_LP_AON_SUPPORTED 1 // #define SOC_LP_AON_SUPPORTED 1
// #define SOC_LP_PERIPHERALS_SUPPORTED 1 // #define SOC_LP_PERIPHERALS_SUPPORTED 1
// #define SOC_CLK_TREE_SUPPORTED 1 //TODO: [ESP32H21] IDF-11521 // #define SOC_CLK_TREE_SUPPORTED 1 //TODO: [ESP32H21] IDF-11521
@@ -539,7 +539,7 @@
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */ #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) // #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ #define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */ #define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */

View File

@@ -1,5 +1,5 @@
/** /**
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -10,247 +10,94 @@
extern "C" { extern "C" {
#endif #endif
/** Group: configure_register */ typedef struct {
/** Type of timer_tar0_low register union {
* need_des struct {
*/ uint32_t target_lo: 32;
typedef union { };
struct { uint32_t val;
/** timer_main_timer_tar_low0 : R/W; bitpos: [31:0]; default: 0; } lo;
* need_des union {
*/ struct {
uint32_t timer_main_timer_tar_low0:32; uint32_t target_hi: 16;
}; uint32_t reserved0: 15;
uint32_t val; uint32_t enable : 1;
} lp_timer_tar0_low_reg_t; };
uint32_t val;
} hi;
} lp_timer_target_reg_t;
/** Type of timer_tar0_high register
* need_des
*/
typedef union { typedef union {
struct { struct {
/** timer_main_timer_tar_high0 : R/W; bitpos: [15:0]; default: 0; uint32_t reserved0: 27;
* need_des uint32_t update : 1;
*/ uint32_t regdma_work: 1;
uint32_t timer_main_timer_tar_high0:16; uint32_t xtal_off : 1;
uint32_t reserved_16:15; uint32_t sys_stall: 1;
/** timer_main_timer_tar_en0 : WT; bitpos: [31]; default: 0; uint32_t sys_rst : 1;
* need_des
*/
uint32_t timer_main_timer_tar_en0:1;
};
uint32_t val;
} lp_timer_tar0_high_reg_t;
/** Type of timer_update register
* need_des
*/
typedef union {
struct {
uint32_t reserved_0:27;
/** timer_main_timer_update : WT; bitpos: [27]; default: 0;
* need_des
*/
uint32_t timer_main_timer_update:1;
/** timer_main_timer_regdma_work : R/W; bitpos: [28]; default: 0;
* Selects the triggering condition for the RTC timer,triggered when regdma working
*/
uint32_t timer_main_timer_regdma_work:1;
/** timer_main_timer_xtal_off : R/W; bitpos: [29]; default: 0;
* need_des
*/
uint32_t timer_main_timer_xtal_off:1;
/** timer_main_timer_sys_stall : R/W; bitpos: [30]; default: 0;
* need_des
*/
uint32_t timer_main_timer_sys_stall:1;
/** timer_main_timer_sys_rst : R/W; bitpos: [31]; default: 0;
* need_des
*/
uint32_t timer_main_timer_sys_rst:1;
}; };
uint32_t val; uint32_t val;
} lp_timer_update_reg_t; } lp_timer_update_reg_t;
/** Type of timer_main_buf0_low register
* need_des
*/
typedef union {
struct {
/** timer_main_timer_buf0_low : RO; bitpos: [31:0]; default: 0;
* need_des
*/
uint32_t timer_main_timer_buf0_low:32;
};
uint32_t val;
} lp_timer_main_buf0_low_reg_t;
/** Type of timer_main_buf0_high register
* need_des
*/
typedef union {
struct {
/** timer_main_timer_buf0_high : RO; bitpos: [15:0]; default: 0;
* need_des
*/
uint32_t timer_main_timer_buf0_high:16;
uint32_t reserved_16:16;
};
uint32_t val;
} lp_timer_main_buf0_high_reg_t;
/** Type of timer_main_buf1_low register
* need_des
*/
typedef union {
struct {
/** timer_main_timer_buf1_low : RO; bitpos: [31:0]; default: 0;
* need_des
*/
uint32_t timer_main_timer_buf1_low:32;
};
uint32_t val;
} lp_timer_main_buf1_low_reg_t;
/** Type of timer_main_buf1_high register
* need_des
*/
typedef union {
struct {
/** timer_main_timer_buf1_high : RO; bitpos: [15:0]; default: 0;
* need_des
*/
uint32_t timer_main_timer_buf1_high:16;
uint32_t reserved_16:16;
};
uint32_t val;
} lp_timer_main_buf1_high_reg_t;
/** Type of timer_main_overflow register
* need_des
*/
typedef union {
struct {
uint32_t reserved_0:31;
/** timer_main_timer_alarm_load : WT; bitpos: [31]; default: 0;
* need_des
*/
uint32_t timer_main_timer_alarm_load:1;
};
uint32_t val;
} lp_timer_main_overflow_reg_t;
/** Type of timer_int_raw register
* need_des
*/
typedef union {
struct {
uint32_t reserved_0:30;
/** timer_overflow_raw : R/WTC/SS; bitpos: [30]; default: 0;
* need_des
*/
uint32_t timer_overflow_raw:1;
/** timer_soc_wakeup_int_raw : R/WTC/SS; bitpos: [31]; default: 0;
* need_des
*/
uint32_t timer_soc_wakeup_int_raw:1;
};
uint32_t val;
} lp_timer_int_raw_reg_t;
/** Type of timer_int_st register
* need_des
*/
typedef union {
struct {
uint32_t reserved_0:30;
/** timer_overflow_st : RO; bitpos: [30]; default: 0;
* need_des
*/
uint32_t timer_overflow_st:1;
/** timer_soc_wakeup_int_st : RO; bitpos: [31]; default: 0;
* need_des
*/
uint32_t timer_soc_wakeup_int_st:1;
};
uint32_t val;
} lp_timer_int_st_reg_t;
/** Type of timer_int_ena register
* need_des
*/
typedef union {
struct {
uint32_t reserved_0:30;
/** timer_overflow_ena : R/W; bitpos: [30]; default: 0;
* need_des
*/
uint32_t timer_overflow_ena:1;
/** timer_soc_wakeup_int_ena : R/W; bitpos: [31]; default: 0;
* need_des
*/
uint32_t timer_soc_wakeup_int_ena:1;
};
uint32_t val;
} lp_timer_int_ena_reg_t;
/** Type of timer_int_clr register
* need_des
*/
typedef union {
struct {
uint32_t reserved_0:30;
/** timer_overflow_clr : WT; bitpos: [30]; default: 0;
* need_des
*/
uint32_t timer_overflow_clr:1;
/** timer_soc_wakeup_int_clr : WT; bitpos: [31]; default: 0;
* need_des
*/
uint32_t timer_soc_wakeup_int_clr:1;
};
uint32_t val;
} lp_timer_int_clr_reg_t;
/** Type of timer_date register
* need_des
*/
typedef union {
struct {
/** timer_date : R/W; bitpos: [30:0]; default: 37785904;
* need_des
*/
uint32_t timer_date:31;
/** timer_clk_en : R/W; bitpos: [31]; default: 0;
* need_des
*/
uint32_t timer_clk_en:1;
};
uint32_t val;
} lp_timer_date_reg_t;
typedef struct { typedef struct {
volatile lp_timer_tar0_low_reg_t timer_tar0_low; union {
volatile lp_timer_tar0_high_reg_t timer_tar0_high; struct {
uint32_t reserved_008[2]; uint32_t counter_lo: 32;
volatile lp_timer_update_reg_t timer_update; };
volatile lp_timer_main_buf0_low_reg_t timer_main_buf0_low; uint32_t val;
volatile lp_timer_main_buf0_high_reg_t timer_main_buf0_high; } lo;
volatile lp_timer_main_buf1_low_reg_t timer_main_buf1_low; union {
volatile lp_timer_main_buf1_high_reg_t timer_main_buf1_high; struct {
volatile lp_timer_main_overflow_reg_t timer_main_overflow; uint32_t counter_hi: 16;
volatile lp_timer_int_raw_reg_t timer_int_raw; uint32_t reserved0 : 16;
volatile lp_timer_int_st_reg_t timer_int_st; };
volatile lp_timer_int_ena_reg_t timer_int_ena; uint32_t val;
volatile lp_timer_int_clr_reg_t timer_int_clr; } hi;
uint32_t reserved_038[241]; } lp_timer_counter_reg_t;
volatile lp_timer_date_reg_t timer_date;
} lp_dev_t;
typedef union {
struct {
uint32_t reserved0: 31;
uint32_t trigger : 1;
};
uint32_t val;
} lp_timer_overflow_reg_t;
typedef union {
struct {
uint32_t reserved0: 30;
uint32_t overflow : 1;
uint32_t alarm : 1;
};
uint32_t val;
} lp_timer_intr_reg_t;
typedef union {
struct {
uint32_t date : 31;
uint32_t clk_en: 1;
};
uint32_t val;
} lp_timer_date_clken_reg_t;
typedef struct lp_timer_dev_t{
volatile lp_timer_target_reg_t target[1];
uint32_t reserved0[2];
volatile lp_timer_update_reg_t update;
volatile lp_timer_counter_reg_t counter[2];
volatile lp_timer_overflow_reg_t overflow;
volatile lp_timer_intr_reg_t int_raw;
volatile lp_timer_intr_reg_t int_st;
volatile lp_timer_intr_reg_t int_en;
volatile lp_timer_intr_reg_t int_clr;
uint32_t reserved[241];
volatile lp_timer_date_clken_reg_t date_clken;
} lp_timer_dev_t;
extern lp_timer_dev_t LP_TIMER;
#ifndef __cplusplus #ifndef __cplusplus
_Static_assert(sizeof(lp_dev_t) == 0x400, "Invalid size of lp_dev_t structure"); _Static_assert(sizeof(lp_timer_dev_t) == 0x400, "Invalid size of lp_timer_dev_t structure");
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus