From d3a9e4f185ba2375a9eea66dd6e60e8534476b1e Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 4 Mar 2025 19:58:00 +0800 Subject: [PATCH 1/9] change(esp_hw_support): add main XTAL kconfig option to support clock source select --- .../esp_hw_support/port/esp32h21/Kconfig.xtal | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 components/esp_hw_support/port/esp32h21/Kconfig.xtal diff --git a/components/esp_hw_support/port/esp32h21/Kconfig.xtal b/components/esp_hw_support/port/esp32h21/Kconfig.xtal new file mode 100644 index 0000000000..e9aa20e3b5 --- /dev/null +++ b/components/esp_hw_support/port/esp32h21/Kconfig.xtal @@ -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 From e351f177905885c70d85f0b596ef2d59b46f04d5 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 4 Mar 2025 20:15:56 +0800 Subject: [PATCH 2/9] change(esp_hw_support): support power management dfs flow --- components/esp_hw_support/CMakeLists.txt | 6 ------ components/esp_hw_support/sleep_modes.c | 8 +++++++- components/esp_pm/pm_impl.c | 5 +++-- components/soc/esp32h21/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32h21/include/soc/soc_caps.h | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 11eb968678..267adb7ef1 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -171,12 +171,6 @@ set(public_include_dirs "include" "include/soc" "include/soc/${target}" "dma/include" "ldo/include" "debug_probe/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} INCLUDE_DIRS ${public_include_dirs} PRIV_INCLUDE_DIRS port/include include/esp_private diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 0c31d4738b..db2629e21e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -108,9 +108,12 @@ #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/cache.h" -#include "esp32h2/rom/rtc.h" #include "soc/extmem_reg.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 #include "esp32p4/rom/rtc.h" #include "hal/gpio_ll.h" @@ -167,6 +170,9 @@ #elif CONFIG_IDF_TARGET_ESP32H2 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (118) #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 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (324) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (240) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index b43e23b572..2c70cea9c3 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -379,14 +379,15 @@ static esp_err_t esp_pm_sleep_configure(const void *vconfig) 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); if (err != ESP_OK) { return err; } #endif - +#if CONFIG_SOC_LIGHT_SLEEP_SUPPORTED err = sleep_modem_configure(config->max_freq_mhz, config->min_freq_mhz, config->light_sleep_enable); +#endif return err; } diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 1d84edc1f5..1dd84d1f56 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -75,6 +75,10 @@ config SOC_PAU_SUPPORTED bool default y +config SOC_PM_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_32M bool default y diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index ce568f4f1e..5e0b01f102 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -78,7 +78,7 @@ // #define SOC_LIGHT_SLEEP_SUPPORTED 1 //TODO: [ESP32H21] IDF-11517, IDF-11520 // #define SOC_DEEP_SLEEP_SUPPORTED 1 //TODO: [ESP32H21] IDF-11515 // #define SOC_MODEM_CLOCK_SUPPORTED 1 -// #define SOC_PM_SUPPORTED 1 +#define SOC_PM_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_32M 1 From 8103ea67c7cc8ad44e9ad7b4ca139a67a90495b4 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 4 Mar 2025 21:19:13 +0800 Subject: [PATCH 3/9] change(esp_hw_support): pmu driver, hal and ll layer support for esp32h21 --- .../port/esp32h21/CMakeLists.txt | 1 + .../esp_hw_support/port/esp32h21/pmu_init.c | 251 ++++++ .../esp_hw_support/port/esp32h21/pmu_param.c | 502 ++++++++++++ .../esp_hw_support/port/esp32h21/pmu_sleep.c | 277 +++++++ .../esp32h21/private_include/pmu_bit_defs.h | 24 + .../port/esp32h21/private_include/pmu_param.h | 561 ++++++++++++++ components/esp_system/port/soc/esp32h21/clk.c | 11 +- components/hal/esp32h21/include/hal/pmu_hal.h | 41 + components/hal/esp32h21/include/hal/pmu_ll.h | 719 ++++++++++++++++++ components/hal/esp32h21/pmu_hal.c | 62 ++ .../esp32h21/include/soc/Kconfig.soc_caps.in | 20 +- .../soc/esp32h21/include/soc/soc_caps.h | 16 +- 12 files changed, 2470 insertions(+), 15 deletions(-) create mode 100644 components/esp_hw_support/port/esp32h21/pmu_init.c create mode 100644 components/esp_hw_support/port/esp32h21/pmu_param.c create mode 100644 components/esp_hw_support/port/esp32h21/pmu_sleep.c create mode 100644 components/esp_hw_support/port/esp32h21/private_include/pmu_bit_defs.h create mode 100644 components/esp_hw_support/port/esp32h21/private_include/pmu_param.h create mode 100644 components/hal/esp32h21/include/hal/pmu_hal.h create mode 100644 components/hal/esp32h21/include/hal/pmu_ll.h create mode 100644 components/hal/esp32h21/pmu_hal.c diff --git a/components/esp_hw_support/port/esp32h21/CMakeLists.txt b/components/esp_hw_support/port/esp32h21/CMakeLists.txt index 922e3c6461..dd0517199b 100644 --- a/components/esp_hw_support/port/esp32h21/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h21/CMakeLists.txt @@ -6,6 +6,7 @@ if(CONFIG_SOC_PMU_SUPPORTED) list(APPEND srcs "rtc_clk_init.c" "pmu_param.c" "pmu_init.c" + "pmu_sleep.c" ) endif() diff --git a/components/esp_hw_support/port/esp32h21/pmu_init.c b/components/esp_hw_support/port/esp32h21/pmu_init.c new file mode 100644 index 0000000000..5e0a07c105 --- /dev/null +++ b/components/esp_hw_support/port/esp32h21/pmu_init.c @@ -0,0 +1,251 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#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, ¶m); + pmu_hp_system_init(ctx, mode, ¶m); + } +} + +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, ¶m); + pmu_lp_system_init(ctx, mode, ¶m); + } +} + +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()); +} diff --git a/components/esp_hw_support/port/esp32h21/pmu_param.c b/components/esp_hw_support/port/esp32h21/pmu_param.c new file mode 100644 index 0000000000..991564a25d --- /dev/null +++ b/components/esp_hw_support/port/esp32h21/pmu_param.c @@ -0,0 +1,502 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#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; +} diff --git a/components/esp_hw_support/port/esp32h21/pmu_sleep.c b/components/esp_hw_support/port/esp32h21/pmu_sleep.c new file mode 100644 index 0000000000..9f5cf7cac5 --- /dev/null +++ b/components/esp_hw_support/port/esp32h21/pmu_sleep.c @@ -0,0 +1,277 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#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(¶m_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; +} diff --git a/components/esp_hw_support/port/esp32h21/private_include/pmu_bit_defs.h b/components/esp_hw_support/port/esp32h21/private_include/pmu_bit_defs.h new file mode 100644 index 0000000000..c456a178c6 --- /dev/null +++ b/components/esp_hw_support/port/esp32h21/private_include/pmu_bit_defs.h @@ -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 diff --git a/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h new file mode 100644 index 0000000000..f0fd3e7704 --- /dev/null +++ b/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h @@ -0,0 +1,561 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#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 diff --git a/components/esp_system/port/soc/esp32h21/clk.c b/components/esp_system/port/soc/esp32h21/clk.c index 3477f1a0f2..40ced86a20 100644 --- a/components/esp_system/port/soc/esp32h21/clk.c +++ b/components/esp_system/port/soc/esp32h21/clk.c @@ -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 */ @@ -165,6 +165,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); + // 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) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. * Improve calibration routine to wait until the frequency is stable. diff --git a/components/hal/esp32h21/include/hal/pmu_hal.h b/components/hal/esp32h21/include/hal/pmu_hal.h new file mode 100644 index 0000000000..bec308350f --- /dev/null +++ b/components/hal/esp32h21/include/hal/pmu_hal.h @@ -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 diff --git a/components/hal/esp32h21/include/hal/pmu_ll.h b/components/hal/esp32h21/include/hal/pmu_ll.h new file mode 100644 index 0000000000..eb6f838621 --- /dev/null +++ b/components/hal/esp32h21/include/hal/pmu_ll.h @@ -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 +#include +#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 diff --git a/components/hal/esp32h21/pmu_hal.c b/components/hal/esp32h21/pmu_hal.c new file mode 100644 index 0000000000..37a1398ad6 --- /dev/null +++ b/components/hal/esp32h21/pmu_hal.c @@ -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); +} diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 1dd84d1f56..ac5914ed1e 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -59,6 +59,14 @@ config SOC_FLASH_ENC_SUPPORTED bool default y +config SOC_PMU_SUPPORTED + bool + default y + +config SOC_LP_TIMER_SUPPORTED + bool + default y + config SOC_SPI_FLASH_SUPPORTED bool default y @@ -709,23 +717,23 @@ config SOC_PHY_DIG_REGS_MEM_SIZE config SOC_PM_SUPPORT_BT_WAKEUP bool - default y + default n config SOC_PM_SUPPORT_EXT1_WAKEUP bool - default y + default n config SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN bool - default y + default n config SOC_PM_SUPPORT_CPU_PD bool - default y + default n config SOC_PM_SUPPORT_MODEM_PD bool - default y + default n config SOC_PM_SUPPORT_XTAL32K_PD bool @@ -745,7 +753,7 @@ config SOC_PM_SUPPORT_VDDSDIO_PD config SOC_PM_SUPPORT_TOP_PD bool - default y + default n config SOC_PM_PAU_LINK_NUM int diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 5e0b01f102..f95220466a 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -54,8 +54,8 @@ // #define SOC_SECURE_BOOT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11500 // #define SOC_BOD_SUPPORTED 1 //TODO: [ESP32H21] IDF-11530 // #define SOC_APM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11494 -// #define SOC_PMU_SUPPORTED 1 //TODO: [ESP32H21] IDf-11522 -// #define SOC_LP_TIMER_SUPPORTED 1 //TODO: [ESP32H21] IDF-11512 +#define SOC_PMU_SUPPORTED 1 +#define SOC_LP_TIMER_SUPPORTED 1 // #define SOC_LP_AON_SUPPORTED 1 // #define SOC_LP_PERIPHERALS_SUPPORTED 1 // #define SOC_CLK_TREE_SUPPORTED 1 //TODO: [ESP32H21] IDF-11521 @@ -520,16 +520,16 @@ #define SOC_PHY_DIG_REGS_MEM_SIZE (21*4) /*-------------------------- Power Management CAPS ----------------------------*/ -#define SOC_PM_SUPPORT_BT_WAKEUP (1) -#define SOC_PM_SUPPORT_EXT1_WAKEUP (1) -#define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (1) /*! Date: Tue, 4 Mar 2025 21:20:49 +0800 Subject: [PATCH 4/9] change(esp_system): change for light sleep example build pass --- components/esp_system/fpga_overrides_clk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/esp_system/fpga_overrides_clk.c b/components/esp_system/fpga_overrides_clk.c index ce3a889416..bd50439549 100644 --- a/components/esp_system/fpga_overrides_clk.c +++ b/components/esp_system/fpga_overrides_clk.c @@ -30,6 +30,7 @@ #include "esp32h2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32H21 #include "esp32h21/rom/rtc.h" +#include "esp_private/esp_pmu.h" #elif CONFIG_IDF_TARGET_ESP32P4 #include "esp32p4/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C5 From 1da425bdc7844d7214e17325d49fd1fdc0f39211 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 4 Mar 2025 22:39:52 +0800 Subject: [PATCH 5/9] change(hal): update lp_timer register structure and support driver for esp32h21 --- .../hal/esp32h21/include/hal/lp_timer_ll.h | 62 ++++ .../esp32h21/register/soc/lp_timer_struct.h | 309 +++++------------- 2 files changed, 140 insertions(+), 231 deletions(-) create mode 100644 components/hal/esp32h21/include/hal/lp_timer_ll.h diff --git a/components/hal/esp32h21/include/hal/lp_timer_ll.h b/components/hal/esp32h21/include/hal/lp_timer_ll.h new file mode 100644 index 0000000000..53ecf81538 --- /dev/null +++ b/components/hal/esp32h21/include/hal/lp_timer_ll.h @@ -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 +#include +#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 diff --git a/components/soc/esp32h21/register/soc/lp_timer_struct.h b/components/soc/esp32h21/register/soc/lp_timer_struct.h index 942322114f..9387480aae 100644 --- a/components/soc/esp32h21/register/soc/lp_timer_struct.h +++ b/components/soc/esp32h21/register/soc/lp_timer_struct.h @@ -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 */ @@ -10,247 +10,94 @@ extern "C" { #endif -/** Group: configure_register */ -/** Type of timer_tar0_low register - * need_des - */ -typedef union { - struct { - /** timer_main_timer_tar_low0 : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t timer_main_timer_tar_low0:32; - }; - uint32_t val; -} lp_timer_tar0_low_reg_t; +typedef struct { + union { + struct { + uint32_t target_lo: 32; + }; + uint32_t val; + } lo; + union { + struct { + uint32_t target_hi: 16; + uint32_t reserved0: 15; + uint32_t enable : 1; + }; + uint32_t val; + } hi; +} lp_timer_target_reg_t; -/** Type of timer_tar0_high register - * need_des - */ typedef union { struct { - /** timer_main_timer_tar_high0 : R/W; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t timer_main_timer_tar_high0:16; - uint32_t reserved_16:15; - /** timer_main_timer_tar_en0 : WT; bitpos: [31]; default: 0; - * 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 reserved0: 27; + uint32_t update : 1; + uint32_t regdma_work: 1; + uint32_t xtal_off : 1; + uint32_t sys_stall: 1; + uint32_t sys_rst : 1; }; uint32_t val; } 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 { - volatile lp_timer_tar0_low_reg_t timer_tar0_low; - volatile lp_timer_tar0_high_reg_t timer_tar0_high; - uint32_t reserved_008[2]; - volatile lp_timer_update_reg_t timer_update; - volatile lp_timer_main_buf0_low_reg_t timer_main_buf0_low; - volatile lp_timer_main_buf0_high_reg_t timer_main_buf0_high; - volatile lp_timer_main_buf1_low_reg_t timer_main_buf1_low; - volatile lp_timer_main_buf1_high_reg_t timer_main_buf1_high; - volatile lp_timer_main_overflow_reg_t timer_main_overflow; - volatile lp_timer_int_raw_reg_t timer_int_raw; - volatile lp_timer_int_st_reg_t timer_int_st; - volatile lp_timer_int_ena_reg_t timer_int_ena; - volatile lp_timer_int_clr_reg_t timer_int_clr; - uint32_t reserved_038[241]; - volatile lp_timer_date_reg_t timer_date; -} lp_dev_t; + union { + struct { + uint32_t counter_lo: 32; + }; + uint32_t val; + } lo; + union { + struct { + uint32_t counter_hi: 16; + uint32_t reserved0 : 16; + }; + uint32_t val; + } hi; +} lp_timer_counter_reg_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 -_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 #ifdef __cplusplus From 410fb091d96a9ea0f11d5863676def3405824d66 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 10 Mar 2025 11:49:25 +0800 Subject: [PATCH 6/9] change(esp_hw_support): change for pmu build pass --- components/esp_hw_support/CMakeLists.txt | 6 ++++-- components/esp_hw_support/sleep_modes.c | 3 ++- .../hal/esp32h21/include/hal/lp_aon_hal.h | 19 +++++++++++++++++++ components/soc/CMakeLists.txt | 2 +- .../esp32h21/include/soc/Kconfig.soc_caps.in | 4 ---- .../soc/esp32h21/include/soc/soc_caps.h | 2 +- 6 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 components/hal/esp32h21/include/hal/lp_aon_hal.h diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 267adb7ef1..0e8ea4bc83 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -33,11 +33,13 @@ if(NOT non_os_build) "sar_periph_ctrl_common.c" "port/${target}/io_mux.c" "port/${target}/esp_clk_tree.c" - "port/esp_clk_tree_common.c" "dma/esp_dma_utils.c" "dma/gdma_link.c" "spi_bus_lock.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) list(APPEND srcs "spi_share_hw_ctrl.c") endif() @@ -58,7 +60,7 @@ if(NOT non_os_build) "sleep_gpio.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") endif() endif() diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index db2629e21e..54452ccab6 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1642,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) { +#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 ) { return ESP_ERR_INVALID_ARG; } - +#endif s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN; s_config.sleep_duration = time_in_us; return ESP_OK; diff --git a/components/hal/esp32h21/include/hal/lp_aon_hal.h b/components/hal/esp32h21/include/hal/lp_aon_hal.h new file mode 100644 index 0000000000..dab6415e9a --- /dev/null +++ b/components/hal/esp32h21/include/hal/lp_aon_hal.h @@ -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 diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index e446e96994..5c95fddb84 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -165,7 +165,7 @@ if(CONFIG_SOC_SDIO_SLAVE_SUPPORTED) list(APPEND srcs "${target_folder}/sdio_slave_periph.c") 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") endif() diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index ac5914ed1e..a37d41c1d9 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -779,10 +779,6 @@ config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y -config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION - bool - default y - config SOC_CLK_XTAL32K_SUPPORTED bool default y diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index f95220466a..13c7a1c1a0 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -538,7 +538,7 @@ #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Mon, 10 Mar 2025 20:03:35 +0800 Subject: [PATCH 7/9] fix(power_management): fix ci warning due to unused variable config --- components/esp_pm/pm_impl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 2c70cea9c3..41cfd92428 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -374,10 +374,9 @@ static void IRAM_ATTR esp_pm_execute_exit_sleep_callbacks(int64_t sleep_time_us) } #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; - const esp_pm_config_t* config = (const esp_pm_config_t*) vconfig; #if ESP_SLEEP_POWER_DOWN_CPU && CONFIG_SOC_LIGHT_SLEEP_SUPPORTED err = sleep_cpu_configure(config->light_sleep_enable); From d89b9cb674abe01bc1292d9e138316c551a06077 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 11 Mar 2025 16:39:28 +0800 Subject: [PATCH 8/9] change(esp_hw_support): this change needs to be reverted when the PMU build --- .../esp32h21/include/soc/Kconfig.soc_caps.in | 24 +++++-------------- .../soc/esp32h21/include/soc/soc_caps.h | 18 +++++++------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index a37d41c1d9..e044bee30e 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -59,14 +59,6 @@ config SOC_FLASH_ENC_SUPPORTED bool default y -config SOC_PMU_SUPPORTED - bool - default y - -config SOC_LP_TIMER_SUPPORTED - bool - default y - config SOC_SPI_FLASH_SUPPORTED bool default y @@ -83,10 +75,6 @@ config SOC_PAU_SUPPORTED bool default y -config SOC_PM_SUPPORTED - bool - default y - config SOC_XTAL_SUPPORT_32M bool default y @@ -717,23 +705,23 @@ config SOC_PHY_DIG_REGS_MEM_SIZE config SOC_PM_SUPPORT_BT_WAKEUP bool - default n + default y config SOC_PM_SUPPORT_EXT1_WAKEUP bool - default n + default y config SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN bool - default n + default y config SOC_PM_SUPPORT_CPU_PD bool - default n + default y config SOC_PM_SUPPORT_MODEM_PD bool - default n + default y config SOC_PM_SUPPORT_XTAL32K_PD bool @@ -753,7 +741,7 @@ config SOC_PM_SUPPORT_VDDSDIO_PD config SOC_PM_SUPPORT_TOP_PD bool - default n + default y config SOC_PM_PAU_LINK_NUM int diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 13c7a1c1a0..8f9ff82c7f 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -54,8 +54,8 @@ // #define SOC_SECURE_BOOT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11500 // #define SOC_BOD_SUPPORTED 1 //TODO: [ESP32H21] IDF-11530 // #define SOC_APM_SUPPORTED 1 //TODO: [ESP32H21] IDF-11494 -#define SOC_PMU_SUPPORTED 1 -#define SOC_LP_TIMER_SUPPORTED 1 +// #define SOC_PMU_SUPPORTED 1 +// #define SOC_LP_TIMER_SUPPORTED 1 // #define SOC_LP_AON_SUPPORTED 1 // #define SOC_LP_PERIPHERALS_SUPPORTED 1 // #define SOC_CLK_TREE_SUPPORTED 1 //TODO: [ESP32H21] IDF-11521 @@ -78,7 +78,7 @@ // #define SOC_LIGHT_SLEEP_SUPPORTED 1 //TODO: [ESP32H21] IDF-11517, IDF-11520 // #define SOC_DEEP_SLEEP_SUPPORTED 1 //TODO: [ESP32H21] IDF-11515 // #define SOC_MODEM_CLOCK_SUPPORTED 1 -#define SOC_PM_SUPPORTED 1 +// #define SOC_PM_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_32M 1 @@ -520,16 +520,16 @@ #define SOC_PHY_DIG_REGS_MEM_SIZE (21*4) /*-------------------------- Power Management CAPS ----------------------------*/ -#define SOC_PM_SUPPORT_BT_WAKEUP (0) -#define SOC_PM_SUPPORT_EXT1_WAKEUP (0) -#define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (0) /*! Date: Thu, 13 Mar 2025 15:40:47 +0800 Subject: [PATCH 9/9] fix(esp_system): update clk code for esp32h21 --- components/esp_system/port/soc/esp32h21/clk.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/esp_system/port/soc/esp32h21/clk.c b/components/esp_system/port/soc/esp32h21/clk.c index 40ced86a20..7b21b1cbd0 100644 --- a/components/esp_system/port/soc/esp32h21/clk.c +++ b/components/esp_system/port/soc/esp32h21/clk.c @@ -24,6 +24,7 @@ #include "soc/lp_clkrst_reg.h" #include "soc/pcr_reg.h" #include "hal/wdt_hal.h" +#include "esp_private/esp_modem_clock.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.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); #endif + modem_clock_deselect_all_module_lp_clock_source(); #if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS) select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K); #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. 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)