diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 189b6c931f..5e3b45ae5b 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -118,9 +118,7 @@ if(NOT BOOTLOADER_BUILD) if(CONFIG_IDF_TARGET_ESP32H2) list(REMOVE_ITEM srcs "sleep_cpu.c" # TODO: IDF-6267 - "sleep_modes.c" # TODO: IDF-6267 "sleep_wake_stub.c" # TODO: IDF-6267 - "sleep_gpio.c" # TODO: IDF-6267 ) endif() else() diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 03a85ea5a5..4dcb820b11 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -96,7 +96,11 @@ extern "C" { #define PMU_SLEEP_PD_MODEM BIT(2) #define PMU_SLEEP_PD_HP_PERIPH BIT(3) #define PMU_SLEEP_PD_CPU BIT(4) -#define PMU_SLEEP_PD_AON BIT(5) + +#if SOC_PM_SUPPORT_HP_AON_PD +#define PMU_SLEEP_PD_HP_AON BIT(5) +#endif + #define PMU_SLEEP_PD_MEM_G0 BIT(6) #define PMU_SLEEP_PD_MEM_G1 BIT(7) #define PMU_SLEEP_PD_MEM_G2 BIT(8) diff --git a/components/esp_hw_support/port/esp32c6/pmu_init.c b/components/esp_hw_support/port/esp32c6/pmu_init.c index b99e6e639d..8c04486f02 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_init.c +++ b/components/esp_hw_support/port/esp32c6/pmu_init.c @@ -131,7 +131,7 @@ static inline void pmu_power_domain_force_default(pmu_context_t *ctx) // for bypass reserved power domain const pmu_hp_power_domain_t pmu_hp_domains[] = { PMU_HP_PD_TOP, - PMU_HP_PD_AON, + PMU_HP_PD_HP_AON, PMU_HP_PD_CPU, PMU_HP_PD_WIFI }; diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index 4e0e959b67..07f96f4803 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -196,11 +196,6 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi 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); - - if (dslp) { - // TODO: IDF-5349 - } else { - } } static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig) @@ -234,11 +229,6 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con 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); - - if (dslp) { - // TODO: IDF-5349 - } else { - } } static void pmu_sleep_param_init(pmu_context_t *ctx, const pmu_sleep_param_config_t *param, bool dslp) diff --git a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h index eba0df4dff..298fdf1b44 100644 --- a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h @@ -107,7 +107,7 @@ typedef struct { .vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \ .wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \ .cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \ - .aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_AON) ? 1 : 0, \ + .aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_HP_AON) ? 1 : 0, \ .top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \ .mem_pd_en = 0, \ .mem_dslp = 0 \ diff --git a/components/esp_hw_support/port/esp32h2/pmu_init.c b/components/esp_hw_support/port/esp32h2/pmu_init.c index c26505d4b3..0548461a2b 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_init.c +++ b/components/esp_hw_support/port/esp32h2/pmu_init.c @@ -18,8 +18,6 @@ #include "soc/regi2c_bias.h" #include "regi2c_ctrl.h" -// TODO: IDF-6267 - static __attribute__((unused)) const char *TAG = "pmu_init"; typedef struct { @@ -40,10 +38,8 @@ 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 - }; + 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; } @@ -99,11 +95,11 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa 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); + /* 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); + pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP); } void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param) @@ -135,7 +131,6 @@ static inline void pmu_power_domain_force_default(pmu_context_t *ctx) // for bypass reserved power domain const pmu_hp_power_domain_t pmu_hp_domains[] = { PMU_HP_PD_TOP, - PMU_HP_PD_AON, PMU_HP_PD_CPU, PMU_HP_PD_WIFI }; @@ -148,8 +143,9 @@ static inline void pmu_power_domain_force_default(pmu_context_t *ctx) 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); } - // /* Isolate all memory banks while sleeping, avoid memory leakage current */ - // pmu_ll_hp_set_memory_no_isolate (ctx->hal->dev, 0); + + /* 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_reset (ctx->hal->dev, false); pmu_ll_lp_set_power_force_isolate (ctx->hal->dev, false); @@ -219,7 +215,4 @@ void pmu_init() pmu_lp_system_init_default(PMU_instance()); pmu_power_domain_force_default(PMU_instance()); - - REG_SET_FIELD(PMU_SLP_WAKEUP_CNTL5_REG, PMU_LP_ANA_WAIT_TARGET, 15); // wait lp ldo stable when wakeup from sleep, need about 100us (slow clk) - REG_SET_FIELD(PMU_SLP_WAKEUP_CNTL7_REG, PMU_ANA_WAIT_TARGET, 1700); // wait hp ldo stable when wakeup from sleep, need about 100us (fast clk) } diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index b2d8c11fff..d1e9b51723 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -4,4 +4,227 @@ * SPDX-License-Identifier: Apache-2.0 */ -// TODO: IDF-6267 +#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 "esp_private/esp_pmu.h" + +#define HP(state) (PMU_MODE_HP_ ## state) +#define LP(state) (PMU_MODE_LP_ ## state) + + +void pmu_sleep_enable_regdma_backup(void) +{ + assert(PMU_instance()->hal); + /* entry 0 is used by pmu HP_SLEEP and HP_ACTIVE states switching. + * entry 1, 2, 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 pd_flags, uint32_t slowclk_period, uint32_t fastclk_period) +{ + const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc; + + /* LP core hardware wait time, microsecond */ + const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period); + const int lp_clk_power_on_wait_time_us = (pd_flags & PMU_SLEEP_PD_XTAL) ? 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; + const int hp_regdma_wait_time_us = mc->hp.regdma_s2a_work_time_us; + const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us; + + const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(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 pd_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_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_us, fastclk_period); + } else { + param->hp_lp.xtal_stable_wait_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.xtal_wait_stable_time_us, slowclk_period); + } + return param; +} + +const pmu_sleep_config_t* pmu_sleep_config_default( + pmu_sleep_config_t *config, + uint32_t pd_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(pd_flags); + + uint32_t iram_pd_flags = 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G0) ? BIT(0) : 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0; + config->power = power_default; + + pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags); + config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period); + + if (dslp) { + pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags); + config->analog = analog_default; + } else { + pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags); + config->digital = digital_default; + + pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags); + if (!(pd_flags & PMU_SLEEP_PD_TOP) || !(pd_flags & PMU_SLEEP_PD_MODEM)){ + analog_default.hp_sys.analog.xpd = 1; + analog_default.hp_sys.analog.dbias = 2; + } + 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_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd); + pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd); + pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd); + pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_dbias); + pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias); + pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); + pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b); + + pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_xpd); + pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias); + pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.xpd); + pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias); + pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b); + + pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur); + pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep); + pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd); + pmu_ll_lp_set_regulator_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_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); + + 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 ESP_OK; +} + +bool pmu_sleep_finish(void) +{ + return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev); +} diff --git a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h index d0dd78ac40..e79adc6404 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h2/private_include/pmu_param.h @@ -70,6 +70,22 @@ typedef struct { const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode); +#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 { @@ -84,6 +100,65 @@ typedef struct { } lp_sys[PMU_MODE_LP_MAX]; } pmu_sleep_power_config_t; +#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .dig_power = { \ + .vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .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_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .dig_power = { \ + .peri_pd_en = 0, \ + .mem_dslp = 0 \ + }, \ + .clk_power = { \ + .xpd_xtal32k = 1, \ + .xpd_rc32k = 1, \ + .xpd_fosc = 1 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .dig_power = { \ + .peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ + .mem_dslp = 1 \ + }, \ + .clk_power = { \ + .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_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; @@ -93,18 +168,168 @@ typedef struct { } lp_sys[PMU_MODE_LP_MAX]; } pmu_sleep_analog_config_t; +#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .xpd_bias = 0x0, \ + .dbg_atten = 0x0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .slp_mem_xpd = 1, \ + .slp_logic_xpd = 1, \ + .slp_mem_dbias = 0x4, \ + .slp_logic_dbias = 0x4, \ + .xpd = 0, \ + .dbias = 0, \ + .drv_b = 0 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .analog = { \ + .slp_xpd = 0, \ + .slp_dbias = 0xc, \ + .xpd = 1, \ + .dbias = 0x1a, \ + .drv_b = 0x0 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .xpd = 0, \ + .dbias = 0x1c, \ + .slp_xpd = 1, \ + .slp_dbias = 0x3, \ + .drv_b = 0x0 \ + } \ + } \ +} + +#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x3, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .xpd = 0, \ + .dbias = 0x15, \ + .slp_mem_xpd = 1, \ + .slp_mem_dbias = 0xc, \ + .slp_logic_xpd = 1, \ + .slp_logic_dbias = 0x5, \ + .drv_b = 0x18c \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .analog = { \ + .xpd = 1, \ + .dbias = 0x1a, \ + .slp_xpd = 0, \ + .slp_dbias = 0, \ + .drv_b = 0x7 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .xpd_bias = 0, \ + .dbg_atten = 0xe, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .xpd = 0, \ + .dbias = 0, \ + .slp_xpd = 1, \ + .slp_dbias = 0xe, \ + .drv_b = 0 \ + } \ + } \ +} + 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_analog_config_t analog; - pmu_sleep_param_config_t param; + 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; /* Mininum sleep protection time (unit: microsecond) */ + uint8_t reserved0; + uint16_t reserved1; + uint16_t analog_wait_time_us; /* LP LDO power up wait time (unit: microsecond) */ + uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint8_t clk_switch_cycle; /* Clock switch to FOSC (unit: slow clock cycle) */ + uint8_t clk_power_on_wait_cycle; /* Clock power on wait cycle (unit: slow clock cycle) */ + 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; /* Mininum sleep protection time (unit: microsecond) */ + uint16_t clock_domain_sync_time_us; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */ + uint16_t system_dfs_up_work_time_us; /* System DFS up scaling work time (unit: microsecond) */ + uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */ + 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, \ + .power_supply_wait_time_us = 2, \ + .power_up_wait_time_us = 2 \ + }, \ + .hp = { \ + .min_slp_time_us = 450, \ + .clock_domain_sync_time_us = 150, \ + .system_dfs_up_work_time_us = 124, \ + .analog_wait_time_us = 154, \ + .power_supply_wait_time_us = 2, \ + .power_up_wait_time_us = 2, \ + .regdma_s2a_work_time_us = 430, \ + .regdma_a2s_work_time_us = 338, \ + .xtal_wait_stable_time_us = 250, \ + .pll_wait_stable_time_us = 1 \ + } \ +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index f8d2e8d7bb..8a420fce9b 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -24,8 +24,10 @@ #if SOC_LP_AON_SUPPORTED #include "hal/lp_aon_hal.h" #else +#if !CONFIG_IDF_TARGET_ESP32H2 #include "hal/rtc_hal.h" #endif +#endif #include "esp_private/gpio.h" #include "esp_private/sleep_gpio.h" diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 2f02c8f14b..6703c0a443 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -32,9 +32,11 @@ #if SOC_LP_AON_SUPPORTED #include "hal/lp_aon_hal.h" #else +#if !CONFIG_IDF_TARGET_ESP32H2 #include "hal/rtc_cntl_ll.h" #include "hal/rtc_hal.h" #endif +#endif #include "driver/uart.h" @@ -89,6 +91,15 @@ #include "esp32h2/rom/cache.h" #include "esp32h2/rom/rtc.h" #include "soc/extmem_reg.h" +#if SOC_LP_TIMER_SUPPORTED +#include "hal/lp_timer_hal.h" +#endif + +#if SOC_PMU_SUPPORTED +#include "esp_private/esp_pmu.h" +#include "esp_private/sleep_sys_periph.h" +#include "esp_private/sleep_clock.h" +#endif #endif // If light sleep time is less than that, don't power down flash @@ -243,6 +254,7 @@ static void touch_wakeup_prepare(void); static void gpio_deep_sleep_wakeup_prepare(void); #endif +#if !CONFIG_IDF_TARGET_ESP32H2 #if SOC_RTC_FAST_MEM_SUPPORTED #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY static RTC_FAST_ATTR esp_deep_sleep_wake_stub_fn_t wake_stub_fn_handler = NULL; @@ -348,6 +360,7 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void); #endif // SOC_RTC_FAST_MEM_SUPPORTED +#endif // !CONFIG_IDF_TARGET_ESP32H2 void esp_deep_sleep(uint64_t time_in_us) { @@ -679,6 +692,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m esp_sleep_isolate_digital_gpio(); #endif +#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6268 #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY esp_set_deep_sleep_wake_stub_default_entry(); // Enter Deep Sleep @@ -699,9 +713,10 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers); #endif #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY - +#else // !CONFIG_IDF_TARGET_ESP32H2 + result = ESP_OK; +#endif // !CONFIG_IDF_TARGET_ESP32H2 } else { - /* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode. In order to avoid the leakage of the SPI cs pin, hold it here */ #if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND) @@ -709,11 +724,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m rtcio_ll_force_hold_enable(SPI_CS0_GPIO_NUM); } #endif +#endif +#if SOC_PMU_SUPPORTED #if SOC_PM_CPU_RETENTION_BY_SW if (pd_flags & PMU_SLEEP_PD_CPU) { result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); } else { +#endif result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); } #else @@ -1391,15 +1409,20 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void) #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP uint64_t esp_sleep_get_gpio_wakeup_status(void) { +#if CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6268 + return 0; +#else if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_GPIO) { return 0; } return rtc_hal_gpio_get_wakeup_status(); +#endif // !CONFIG_IDF_TARGET_ESP32H2 } static void gpio_deep_sleep_wakeup_prepare(void) { +#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6268 for (gpio_num_t gpio_idx = GPIO_NUM_0; gpio_idx < GPIO_NUM_MAX; gpio_idx++) { if (((1ULL << gpio_idx) & s_config.gpio_wakeup_mask) == 0) { continue; @@ -1415,6 +1438,7 @@ static void gpio_deep_sleep_wakeup_prepare(void) } // Clear state from previous wakeup rtc_hal_gpio_clear_wakeup_status(); +#endif // !CONFIG_IDF_TARGET_ESP32H2 } esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode) @@ -1600,6 +1624,7 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_ return ESP_ERR_INVALID_ARG; } portENTER_CRITICAL_SAFE(&s_config.lock); + int refs = (option == ESP_PD_OPTION_ON) ? s_config.domain[domain].refs++ \ : (option == ESP_PD_OPTION_OFF) ? --s_config.domain[domain].refs \ : s_config.domain[domain].refs; diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 8f3cc5dc2b..9a74b02922 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -5,7 +5,7 @@ menu "Power Management" # ESP32H2 currently does not support power management IDF-6270 # Note. Disabling this option for H2 will also cause all sdkconfig.release test cases run without pm enabled # ORed with __DOXYGEN__ to pass H2 docs build, need to remove when pm is supported on H2 - depends on (!FREERTOS_SMP && !IDF_TARGET_ESP32H2) || __DOXYGEN__ + depends on !FREERTOS_SMP || __DOXYGEN__ default n help If enabled, application is compiled with support for power management. diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 0ebd883b70..79b3e0c272 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -274,7 +274,7 @@ esp_err_t esp_pm_configure(const void* vconfig) const int apb_clk_freq = MAX(soc_apb_clk_freq, modem_apb_clk_freq); int apb_max_freq = MIN(max_freq_mhz, apb_clk_freq); /* CPU frequency in APB_MAX mode */ #else - int apb_max_freq = MIN(max_freq_mhz, 80); /* CPU frequency in APB_MAX mode */ + int apb_max_freq = MIN(max_freq_mhz, APB_CLK_FREQ / MHZ); /* CPU frequency in APB_MAX mode */ #endif apb_max_freq = MAX(apb_max_freq, min_freq_mhz); diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index d3fdbc77d3..0c1d1e4a69 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -591,12 +591,10 @@ void IRAM_ATTR call_start_cpu0(void) #endif #endif -#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6268 // Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins if (rst_reas[0] == RESET_REASON_CORE_DEEP_SLEEP) { esp_deep_sleep_wakeup_io_reset(); } -#endif #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP esp_cache_err_int_init(); diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index 75cb5e9075..1622c5aced 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -658,4 +658,4 @@ TEST_CASE("wake up using GPIO (2 or 4 low)", "[deepsleep][ignore]") esp_deep_sleep_start(); } #endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) TODO: IDF-5349 +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) TODO: IDF-6268 diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 29f7b1edc1..ad524aaf43 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -236,7 +236,6 @@ if(NOT BOOTLOADER_BUILD) list(REMOVE_ITEM srcs "esp32h2/rtc_cntl_hal.c" - "esp32h2/pmu_hal.c" # TODO: IDF-6267 ) endif() endif() diff --git a/components/hal/esp32h2/include/hal/lp_timer_hal.h b/components/hal/esp32h2/include/hal/lp_timer_hal.h new file mode 100644 index 0000000000..39fa017ab5 --- /dev/null +++ b/components/hal/esp32h2/include/hal/lp_timer_hal.h @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "soc/soc.h" +#include "hal/lp_timer_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @brief set alarm target value + * + * @param timer_id timer num of lp_timer, 0 or 1 for esp32h2 + * + * @param value when counter reaches alarm value, alarm event will be triggered + */ +void lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value); + +/** + * @brief get current counter value + */ +uint64_t lp_timer_hal_get_cycle_count(void); + +/** + * @brief clear alarm interrupt status + */ +void lp_timer_hal_clear_alarm_intr_status(void); + +/** + * @brief clear overflow interrupt status + */ +void lp_timer_hal_clear_overflow_intr_status(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/lp_timer_ll.h b/components/hal/esp32h2/include/hal/lp_timer_ll.h new file mode 100644 index 0000000000..c57588c78f --- /dev/null +++ b/components/hal/esp32h2/include/hal/lp_timer_ll.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2023 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 "soc/soc.h" +#include "soc/rtc.h" +#include "soc/lp_timer_struct.h" +#include "soc/lp_aon_reg.h" +#include "hal/lp_timer_types.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) +{ + dev->target[timer_id].hi.target_hi = (value >> 32) & 0xFFFF; + 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 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 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; +} + +FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us) +{ + uint32_t slow_clk_value = REG_READ(LP_AON_STORE1_REG); + return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/pmu_hal.h b/components/hal/esp32h2/include/hal/pmu_hal.h index 9151e20ed1..3ac236a24b 100644 --- a/components/hal/esp32h2/include/hal/pmu_hal.h +++ b/components/hal/esp32h2/include/hal/pmu_hal.h @@ -20,6 +20,18 @@ typedef struct { pmu_dev_t *dev; } pmu_hal_context_t; +void pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle); + +uint32_t pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal); + +void pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle); + +uint32_t pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal); + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/pmu_ll.h b/components/hal/esp32h2/include/hal/pmu_ll.h index a0503d0563..d666973e2f 100644 --- a/components/hal/esp32h2/include/hal/pmu_ll.h +++ b/components/hal/esp32h2/include/hal/pmu_ll.h @@ -6,7 +6,6 @@ // The LL layer for ESP32-H2 PMU register operations -//TODO: IDF-6267 #pragma once #include @@ -124,55 +123,25 @@ FORCE_INLINE_ATTR void pmu_ll_hp_set_retention_param(pmu_dev_t *hw, pmu_hp_mode_ 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_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_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_modem_to_active_backup_enable(pmu_dev_t *hw) -// { -// hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 1; -// } +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_modem_to_active_backup_disable(pmu_dev_t *hw) -// { -// hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 0; -// } - -// FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_enable(pmu_dev_t *hw) -// { -// hw->hp_sys[PMU_MODE_HP_MODEM].backup.hp_sleep2modem_backup_en = 1; -// } - -// FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_disable(pmu_dev_t *hw) -// { -// hw->hp_sys[PMU_MODE_HP_MODEM].backup.hp_sleep2modem_backup_en = 0; -// } - -// FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_enable(pmu_dev_t *hw) -// { -// hw->hp_sys[PMU_MODE_HP_SLEEP].backup.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_modem_to_sleep_backup_enable(pmu_dev_t *hw) -// { -// hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 1; -// } - -// FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_disable(pmu_dev_t *hw) -// { -// hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 0; -// } +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) { @@ -303,7 +272,6 @@ FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_lp_mod 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; @@ -323,10 +291,10 @@ FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_sysclk_sel(pmu_dev_t *hw, bool upda 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_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) { @@ -370,7 +338,6 @@ FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_pad_hold_all(pmu_dev_t *hw, bool hold_a } } -/*** */ 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; @@ -451,7 +418,6 @@ 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; @@ -473,10 +439,10 @@ FORCE_INLINE_ATTR void pmu_ll_hp_set_wakeup_enable(pmu_dev_t *hw, uint32_t wakeu 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_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) { @@ -518,140 +484,130 @@ 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) -// { -// hw->wakeup.cntl3.lp_min_slp_val = slow_clk_cycle; -// } +FORCE_INLINE_ATTR void pmu_ll_lp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + 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) -// { -// hw->hp_ext.clk_cntl.modify_icg_cntl_wait = cycle; -// } +FORCE_INLINE_ATTR void pmu_ll_hp_set_modify_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + 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 hw->hp_ext.clk_cntl.modify_icg_cntl_wait; -// } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_modify_icg_cntl_wait_cycle(pmu_dev_t *hw) +{ + return 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) -// { -// hw->hp_ext.clk_cntl.switch_icg_cntl_wait = cycle; -// } +FORCE_INLINE_ATTR void pmu_ll_hp_set_switch_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + 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 hw->hp_ext.clk_cntl.switch_icg_cntl_wait; -// } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_switch_icg_cntl_wait_cycle(pmu_dev_t *hw) +{ + return 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 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 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 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 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) -// { -// hw->wakeup.cntl5.lp_ana_wait_target = slow_clk_cycle; -// } +FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + 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 hw->wakeup.cntl5.lp_ana_wait_target; -// } +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl5.lp_ana_wait_target; +} -// FORCE_INLINE_ATTR void pmu_ll_set_modem_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->wakeup.cntl5.modem_wait_target = cycle; -// } +FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.clk_wait.wait_xtal_stable = cycle; +} -// FORCE_INLINE_ATTR uint32_t pmu_ll_get_modem_wait_target_cycle(pmu_dev_t *hw) -// { -// return hw->wakeup.cntl5.modem_wait_target; -// } +FORCE_INLINE_ATTR uint32_t pmu_ll_get_xtal_stable_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.clk_wait.wait_xtal_stable; +} -// FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->power.clk_wait.wait_xtal_stable = cycle; -// } +FORCE_INLINE_ATTR void pmu_ll_set_pll_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.clk_wait.wait_pll_stable = cycle; +} -// FORCE_INLINE_ATTR uint32_t pmu_ll_get_xtal_stable_wait_cycle(pmu_dev_t *hw) -// { -// return hw->power.clk_wait.wait_xtal_stable; -// } +FORCE_INLINE_ATTR uint32_t pmu_ll_get_pll_stable_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.clk_wait.wait_pll_stable; +} -// FORCE_INLINE_ATTR void pmu_ll_set_pll_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->power.clk_wait.wait_pll_stable = cycle; -// } +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_get_pll_stable_wait_cycle(pmu_dev_t *hw) -// { -// return hw->power.clk_wait.wait_pll_stable; -// } +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_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->power.wait_timer1.wait_timer = cycle; -// } +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_supply_wait_cycle(pmu_dev_t *hw) -// { -// return hw->power.wait_timer1.wait_timer; -// } +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_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->power.wait_timer1.powerup_timer = cycle; -// } +FORCE_INLINE_ATTR void pmu_ll_hp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->wakeup.cntl7.ana_wait_target = 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 uint32_t pmu_ll_hp_get_analog_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl7.ana_wait_target; +} -// FORCE_INLINE_ATTR void pmu_ll_hp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->wakeup.cntl7.ana_wait_target = cycle; -// } +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_analog_wait_target_cycle(pmu_dev_t *hw) -// { -// return hw->wakeup.cntl7.ana_wait_target; -// } +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_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->power.wait_timer0.wait_timer = cycle; -// } +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_supply_wait_cycle(pmu_dev_t *hw) -// { -// return hw->power.wait_timer0.wait_timer; -// } - -// FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle) -// { -// hw->power.wait_timer0.powerup_timer = cycle; -// } - -// FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t *hw) -// { -// return hw->power.wait_timer0.powerup_timer; -// } +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer0.powerup_timer; +} #ifdef __cplusplus } diff --git a/components/hal/esp32h2/lp_timer_hal.c b/components/hal/esp32h2/lp_timer_hal.c new file mode 100644 index 0000000000..c27e7bcc2d --- /dev/null +++ b/components/hal/esp32h2/lp_timer_hal.c @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2023 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 "hal/lp_timer_ll.h" + +static DRAM_ATTR struct { + lp_timer_dev_t *dev; +} lp_timer_context = { .dev = &LP_TIMER }; + +void IRAM_ATTR lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value) +{ + lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev); + lp_timer_ll_set_alarm_target(lp_timer_context.dev, timer_id, value); + lp_timer_ll_set_target_enable(lp_timer_context.dev, timer_id, true); +} + +uint64_t IRAM_ATTR lp_timer_hal_get_cycle_count(void) +{ + lp_timer_ll_counter_snapshot(lp_timer_context.dev); + uint32_t lo = lp_timer_ll_get_counter_value_low(lp_timer_context.dev, 0); + uint32_t hi = lp_timer_ll_get_counter_value_high(lp_timer_context.dev, 0); + lp_timer_counter_value_t result = { + .lo = lo, + .hi = hi + }; + return result.val; +} + +void IRAM_ATTR lp_timer_hal_clear_alarm_intr_status(void) +{ + lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev); +} + +void IRAM_ATTR lp_timer_hal_clear_overflow_intr_status(void) +{ + lp_timer_ll_clear_overflow_intr_status(lp_timer_context.dev); +} diff --git a/components/hal/esp32h2/pmu_hal.c b/components/hal/esp32h2/pmu_hal.c new file mode 100644 index 0000000000..9da9eaed80 --- /dev/null +++ b/components/hal/esp32h2/pmu_hal.c @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2023 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 IRAM_ATTR pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle) +{ + pmu_ll_hp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle); + pmu_ll_hp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle); +} + +uint32_t IRAM_ATTR pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal) +{ + uint32_t power_supply_wait_cycle = pmu_ll_hp_get_digital_power_supply_wait_cycle(hal->dev); + uint32_t power_up_wait_cycle = pmu_ll_hp_get_digital_power_up_wait_cycle(hal->dev); + return power_supply_wait_cycle + power_up_wait_cycle; +} + +void IRAM_ATTR pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle) +{ + pmu_ll_lp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle); + pmu_ll_lp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle); +} + +uint32_t IRAM_ATTR pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal) +{ + uint32_t power_supply_wait_cycle = pmu_ll_lp_get_digital_power_supply_wait_cycle(hal->dev); + uint32_t power_up_wait_cycle = pmu_ll_lp_get_digital_power_up_wait_cycle(hal->dev); + return power_supply_wait_cycle + power_up_wait_cycle; +} + +void 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/hal/include/hal/pmu_types.h b/components/hal/include/hal/pmu_types.h index 75aacbd101..5c4c44e81f 100644 --- a/components/hal/include/hal/pmu_types.h +++ b/components/hal/include/hal/pmu_types.h @@ -11,6 +11,7 @@ extern "C" { #endif #include +#include "soc/soc_caps.h" /** * @brief PMU modes of HP system @@ -32,12 +33,13 @@ typedef enum { } pmu_lp_mode_t; typedef enum { - PMU_HP_PD_TOP = 0, /* Power domain of digital top */ - PMU_HP_PD_AON, /* Power domain of always-on */ - PMU_HP_PD_CPU, /* Power domain of HP CPU */ - PMU_HP_PD_RESERVED, /* Reserved power domain*/ - PMU_HP_PD_WIFI, /* Power domain of WIFI */ - PMU_HP_PD_MAX + PMU_HP_PD_TOP = 0, /*!< Power domain of digital top */ +#if SOC_PM_SUPPORT_HP_AON_PD + PMU_HP_PD_HP_AON = 1, /*!< Power domain of always-on */ +#endif + PMU_HP_PD_CPU = 2, /*!< Power domain of HP CPU */ + PMU_HP_PD_RESERVED = 3, /*!< Reserved power domain */ + PMU_HP_PD_WIFI = 4, /*!< Power domain of WIFI */ } pmu_hp_power_domain_t; @@ -135,7 +137,9 @@ typedef struct { } pmu_lp_analog_t; typedef struct { +#if SOC_PM_SUPPORT_PMU_MODEM_STATE uint32_t modem_wakeup_wait_cycle; +#endif uint16_t analog_wait_target_cycle; uint16_t digital_power_down_wait_cycle; uint16_t digital_power_supply_wait_cycle; diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 6c94bda2b3..12d60c0e62 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1135,6 +1135,10 @@ config SOC_PM_SUPPORT_TOP_PD bool default y +config SOC_PM_SUPPORT_HP_AON_PD + bool + default y + config SOC_PM_SUPPORT_MAC_BB_PD bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index fb715701ba..d2a5c68b4e 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -468,6 +468,7 @@ #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) #define SOC_PM_SUPPORT_TOP_PD (1) +#define SOC_PM_SUPPORT_HP_AON_PD (1) #define SOC_PM_SUPPORT_MAC_BB_PD (1) #define SOC_PM_SUPPORT_RTC_PERIPH_PD (1) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 8986d415e6..9c43a8b7f3 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -167,6 +167,14 @@ config SOC_PMU_SUPPORTED bool default y +config SOC_LP_TIMER_SUPPORTED + bool + default y + +config SOC_CLK_TREE_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_32M bool default y @@ -715,14 +723,6 @@ config SOC_PARLIO_TRANS_BIT_ALIGN bool default y -config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH - int - default 128 - -config SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM - int - default 108 - config SOC_RTCIO_PIN_COUNT int default 0 @@ -907,6 +907,14 @@ config SOC_SYSTIMER_SUPPORT_ETM bool default y +config SOC_LP_TIMER_BIT_WIDTH_LO + int + default 32 + +config SOC_LP_TIMER_BIT_WIDTH_HI + int + default 16 + config SOC_TIMER_GROUPS int default 2 @@ -1047,21 +1055,13 @@ config SOC_PHY_DIG_REGS_MEM_SIZE int default 21 -config SOC_PM_SUPPORT_WIFI_WAKEUP - bool - default y - config SOC_PM_SUPPORT_BT_WAKEUP bool default y config SOC_PM_SUPPORT_CPU_PD bool - default y - -config SOC_PM_SUPPORT_BT_PD - bool - default y + default n config SOC_PM_SUPPORT_XTAL32K_PD bool @@ -1079,10 +1079,6 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y -config SOC_PM_CPU_RETENTION_BY_RTCCNTL - bool - default y - config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y diff --git a/components/soc/esp32h2/include/soc/lp_timer_struct.h b/components/soc/esp32h2/include/soc/lp_timer_struct.h index 1c24dafa1a..9efef9b169 100644 --- a/components/soc/esp32h2/include/soc/lp_timer_struct.h +++ b/components/soc/esp32h2/include/soc/lp_timer_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,238 +10,99 @@ extern "C" { #endif -/** Group: configure_register */ -/** Type of tar0_low register - * need_des - */ -typedef union { - struct { - /** main_timer_tar_low0 : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t 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 tar0_high register - * need_des - */ typedef union { struct { - /** main_timer_tar_high0 : R/W; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t main_timer_tar_high0:16; - uint32_t reserved_16:15; - /** main_timer_tar_en0 : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_tar_en0:1; - }; - uint32_t val; -} lp_timer_tar0_high_reg_t; - -/** Type of update register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** main_timer_update : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t main_timer_update:1; - /** main_timer_xtal_off : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t main_timer_xtal_off:1; - /** main_timer_sys_stall : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t main_timer_sys_stall:1; - /** main_timer_sys_rst : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_sys_rst:1; + uint32_t reserved0: 28; + uint32_t update : 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 main_buf0_low register - * need_des - */ -typedef union { - struct { - /** main_timer_buf0_low : RO; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf0_low:32; - }; - uint32_t val; -} lp_timer_main_buf0_low_reg_t; - -/** Type of main_buf0_high register - * need_des - */ -typedef union { - struct { - /** main_timer_buf0_high : RO; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf0_high:16; - uint32_t reserved_16:16; - }; - uint32_t val; -} lp_timer_main_buf0_high_reg_t; - -/** Type of main_buf1_low register - * need_des - */ -typedef union { - struct { - /** main_timer_buf1_low : RO; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf1_low:32; - }; - uint32_t val; -} lp_timer_main_buf1_low_reg_t; - -/** Type of main_buf1_high register - * need_des - */ -typedef union { - struct { - /** main_timer_buf1_high : RO; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf1_high:16; - uint32_t reserved_16:16; - }; - uint32_t val; -} lp_timer_main_buf1_high_reg_t; - -/** Type of main_overflow register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** main_timer_alarm_load : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_alarm_load:1; - }; - uint32_t val; -} lp_timer_main_overflow_reg_t; - -/** Type of int_raw register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_raw : R/WTC/SS; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_raw:1; - /** soc_wakeup_int_raw : R/WTC/SS; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_raw:1; - }; - uint32_t val; -} lp_timer_int_raw_reg_t; - -/** Type of int_st register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_st : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_st:1; - /** soc_wakeup_int_st : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_st:1; - }; - uint32_t val; -} lp_timer_int_st_reg_t; - -/** Type of int_ena register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_ena : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_ena:1; - /** soc_wakeup_int_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_ena:1; - }; - uint32_t val; -} lp_timer_int_ena_reg_t; - -/** Type of int_clr register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_clr : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_clr:1; - /** soc_wakeup_int_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_clr:1; - }; - uint32_t val; -} lp_timer_int_clr_reg_t; - -/** Type of date register - * need_des - */ -typedef union { - struct { - /** date : R/W; bitpos: [30:0]; default: 34672976; - * need_des - */ - uint32_t date:31; - /** clk_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t clk_en:1; - }; - uint32_t val; -} lp_timer_date_reg_t; - - typedef struct { - volatile lp_timer_tar0_low_reg_t tar0_low; - volatile lp_timer_tar0_high_reg_t tar0_high; - uint32_t reserved_008[2]; - volatile lp_timer_update_reg_t update; - volatile lp_timer_main_buf0_low_reg_t main_buf0_low; - volatile lp_timer_main_buf0_high_reg_t main_buf0_high; - volatile lp_timer_main_buf1_low_reg_t main_buf1_low; - volatile lp_timer_main_buf1_high_reg_t main_buf1_high; - volatile lp_timer_main_overflow_reg_t main_overflow; - volatile lp_timer_int_raw_reg_t int_raw; - volatile lp_timer_int_st_reg_t int_st; - volatile lp_timer_int_ena_reg_t int_ena; - volatile lp_timer_int_clr_reg_t int_clr; - uint32_t reserved_038[241]; - volatile lp_timer_date_reg_t date; + 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 reserved0: 30; + uint32_t overflow : 1; + uint32_t alarm : 1; + }; + uint32_t val; +} lp_timer_lp_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[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; + volatile lp_timer_lp_intr_reg_t lp_int_raw; + volatile lp_timer_lp_intr_reg_t lp_int_st; + volatile lp_timer_lp_intr_reg_t lp_int_en; + volatile lp_timer_lp_intr_reg_t lp_int_clr; + uint32_t reserved[237]; + volatile lp_timer_date_clken_reg_t date_clken; } lp_timer_dev_t; extern lp_timer_dev_t LP_TIMER; diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index d92a570dc3..6e97635e7a 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -67,6 +67,8 @@ #define SOC_BOD_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 +#define SOC_LP_TIMER_SUPPORTED 1 +#define SOC_CLK_TREE_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_32M 1 @@ -296,15 +298,6 @@ #define SOC_PARLIO_TX_CLK_SUPPORT_GATING 1 /*!< Support gating TX clock */ #define SOC_PARLIO_TRANS_BIT_ALIGN 1 /*!< Support bit alignment in transaction */ -// TODO: IDF-6267 (Copy from esp32c6, need check) -/*-------------------------- RTC CAPS --------------------------------------*/ -#define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) -#define SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM (108) -#define SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) -#define SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) - -#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) - /*-------------------------- RTCIO CAPS --------------------------------------*/ /* No dedicated LP_IO subsystem on ESP32-H2. LP functions are still supported * for hold, wake & 32kHz crystal functions - via LP_AON registers */ @@ -388,6 +381,10 @@ #define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current) #define SOC_SYSTIMER_SUPPORT_ETM 1 // Systimer comparator can generate ETM event +/*-------------------------- LP_TIMER CAPS ----------------------------------*/ +#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part +#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part + /*--------------------------- TIMER GROUP CAPS ---------------------------------------*/ #define SOC_TIMER_GROUPS (2) #define SOC_TIMER_GROUP_TIMERS_PER_GROUP (1U) @@ -450,15 +447,12 @@ // TODO: IDF-6270 (Copy from esp32c6, need check) /*-------------------------- Power Management CAPS ----------------------------*/ -#define SOC_PM_SUPPORT_WIFI_WAKEUP (1) #define SOC_PM_SUPPORT_BT_WAKEUP (1) -#define SOC_PM_SUPPORT_CPU_PD (1) -#define SOC_PM_SUPPORT_BT_PD (1) +#define SOC_PM_SUPPORT_CPU_PD (0) #define SOC_PM_SUPPORT_XTAL32K_PD (1) #define SOC_PM_SUPPORT_RC32K_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) -#define SOC_PM_CPU_RETENTION_BY_RTCCNTL (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!