From 63d32ab620d5cece6a8fa3dbea1deab9d350a6fb Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Mon, 22 May 2023 14:17:02 +0800 Subject: [PATCH 01/19] Power Management: support DFS and PMU feature for esp32h2 --- components/esp_hw_support/CMakeLists.txt | 2 - .../include/esp_private/esp_pmu.h | 6 +- .../esp_hw_support/port/esp32c6/pmu_init.c | 2 +- .../esp_hw_support/port/esp32c6/pmu_sleep.c | 10 - .../port/esp32c6/private_include/pmu_param.h | 2 +- .../esp_hw_support/port/esp32h2/pmu_init.c | 25 +- .../esp_hw_support/port/esp32h2/pmu_sleep.c | 225 ++++++++++++- .../port/esp32h2/private_include/pmu_param.h | 231 ++++++++++++- components/esp_hw_support/sleep_gpio.c | 2 + components/esp_hw_support/sleep_modes.c | 29 +- components/esp_pm/Kconfig | 2 +- components/esp_pm/pm_impl.c | 2 +- components/esp_system/port/cpu_start.c | 2 - .../esp_system_unity_tests/main/test_sleep.c | 2 +- components/hal/CMakeLists.txt | 1 - .../hal/esp32h2/include/hal/lp_timer_hal.h | 45 +++ .../hal/esp32h2/include/hal/lp_timer_ll.h | 66 ++++ components/hal/esp32h2/include/hal/pmu_hal.h | 12 + components/hal/esp32h2/include/hal/pmu_ll.h | 292 +++++++--------- components/hal/esp32h2/lp_timer_hal.c | 46 +++ components/hal/esp32h2/pmu_hal.c | 50 +++ components/hal/include/hal/pmu_types.h | 16 +- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c6/include/soc/soc_caps.h | 1 + .../esp32h2/include/soc/Kconfig.soc_caps.in | 34 +- .../soc/esp32h2/include/soc/lp_timer_struct.h | 311 +++++------------- components/soc/esp32h2/include/soc/soc_caps.h | 19 +- .../system/inc/power_management_esp32h2.rst | 34 +- .../system/inc/power_management_esp32h2.rst | 34 +- 29 files changed, 1025 insertions(+), 482 deletions(-) create mode 100644 components/hal/esp32h2/include/hal/lp_timer_hal.h create mode 100644 components/hal/esp32h2/include/hal/lp_timer_ll.h create mode 100644 components/hal/esp32h2/lp_timer_hal.c create mode 100644 components/hal/esp32h2/pmu_hal.c diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 4a1ce9570e..68dbb2d110 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -125,9 +125,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 92d88eea38..17b631c781 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 14eb8eb9ae..9c1c7c83bb 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 @@ -245,6 +256,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; @@ -350,6 +362,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) { @@ -674,6 +687,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 @@ -694,9 +708,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) @@ -704,11 +719,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 e49568f7ec..97765a25d6 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 76098ee2b6..11c670fe41 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 577c211e1c..b5394c903c 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 6a4483eb21..1c6997902c 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -245,7 +245,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 bc5e9f21a7..402e01d122 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1167,6 +1167,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 85f7e5ebf9..683c9465fc 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -478,6 +478,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 1a92530dc1..dc56946f90 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -167,6 +167,10 @@ config SOC_PMU_SUPPORTED bool default y +config SOC_LP_TIMER_SUPPORTED + bool + default y + config SOC_CLK_TREE_SUPPORTED bool default y @@ -723,14 +727,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 @@ -923,6 +919,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 @@ -1067,21 +1071,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 @@ -1099,10 +1095,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 c0569795a3..5e704c6cba 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -67,6 +67,7 @@ #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 ---------------------------------------*/ @@ -298,15 +299,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 */ @@ -394,6 +386,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) @@ -457,15 +453,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) /*! Date: Mon, 22 May 2023 10:47:31 +0800 Subject: [PATCH 02/19] Power Management: support CPU powered down in light sleep for esp32h2 --- components/esp_hw_support/CMakeLists.txt | 3 +-- components/esp_hw_support/sleep_cpu.c | 13 +++++++++++++ components/esp_hw_support/sleep_cpu_asm.S | 4 ++-- components/esp_hw_support/sleep_modes.c | 1 - components/esp_pm/Kconfig | 2 +- components/esp_rom/include/esp32h2/rom/rtc.h | 1 + .../soc/esp32h2/include/soc/Kconfig.soc_caps.in | 6 +++++- components/soc/esp32h2/include/soc/soc_caps.h | 3 ++- 8 files changed, 25 insertions(+), 8 deletions(-) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 68dbb2d110..4d908d266d 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -124,8 +124,7 @@ if(NOT BOOTLOADER_BUILD) if(CONFIG_IDF_TARGET_ESP32H2) list(REMOVE_ITEM srcs - "sleep_cpu.c" # TODO: IDF-6267 - "sleep_wake_stub.c" # TODO: IDF-6267 + "sleep_wake_stub.c" # TODO: IDF-6268 ) endif() else() diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c index 1bc2037d6d..eb4cbbdfb1 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -46,6 +46,14 @@ #include "soc/plic_reg.h" #include "soc/clint_reg.h" #include "esp32c6/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32H2 +#include "esp32h2/rom/rtc.h" +#include "riscv/rvsleep-frames.h" +#include "soc/intpri_reg.h" +#include "soc/extmem_reg.h" +#include "soc/plic_reg.h" +#include "soc/clint_reg.h" +#include "esp32h2/rom/cache.h" #endif static __attribute__((unused)) const char *TAG = "sleep"; @@ -317,8 +325,13 @@ static inline void * cpu_domain_intpri_sleep_frame_alloc_and_init(void) static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) { const static cpu_domain_dev_regs_region_t regions[] = { +#if CONFIG_IDF_TARGET_ESP32C6 { .start = EXTMEM_L1_CACHE_CTRL_REG, .end = EXTMEM_L1_CACHE_CTRL_REG + 4 }, { .start = EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 } +#elif CONFIG_IDF_TARGET_ESP32H2 + { .start = CACHE_L1_CACHE_CTRL_REG, .end = CACHE_L1_CACHE_CTRL_REG + 4 }, + { .start = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 } +#endif }; return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); } diff --git a/components/esp_hw_support/sleep_cpu_asm.S b/components/esp_hw_support/sleep_cpu_asm.S index 3a24e917db..b84dd4d421 100644 --- a/components/esp_hw_support/sleep_cpu_asm.S +++ b/components/esp_hw_support/sleep_cpu_asm.S @@ -9,7 +9,7 @@ #include "soc/soc_caps.h" #include "sdkconfig.h" -#if !CONFIG_IDF_TARGET_ESP32C6 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 #include "soc/lp_aon_reg.h" #include "soc/extmem_reg.h" #endif @@ -115,7 +115,7 @@ rv_core_critical_regs_save: csrr t0, mscratch sw t0, RV_SLP_CTX_T0(t3) -#if !CONFIG_IDF_TARGET_ESP32C6 +#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 /* writeback dcache is required here!!! */ la t0, EXTMEM_CACHE_SYNC_MAP_REG li t1, 0x10 diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 9c1c7c83bb..1d1688610d 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -825,7 +825,6 @@ void IRAM_ATTR esp_deep_sleep_start(void) #else uint32_t force_pd_flags = RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | RTC_SLEEP_PD_INT_8M | RTC_SLEEP_PD_XTAL; #endif - /** * If all wireless modules share one power domain, we name this power domain "modem". * If wireless modules have their own power domain, we give these power domains separate diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 97765a25d6..a930c65ab7 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -109,7 +109,7 @@ menu "Power Management" config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP bool "Power down CPU in light sleep" - depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 + depends on SOC_PM_SUPPORT_CPU_PD select PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB default y help diff --git a/components/esp_rom/include/esp32h2/rom/rtc.h b/components/esp_rom/include/esp32h2/rom/rtc.h index 1a89e39891..8648cf3e7b 100644 --- a/components/esp_rom/include/esp32h2/rom/rtc.h +++ b/components/esp_rom/include/esp32h2/rom/rtc.h @@ -61,6 +61,7 @@ extern "C" { #define RTC_ENTRY_ADDR_REG LP_AON_STORE6_REG #define RTC_RESET_CAUSE_REG LP_AON_STORE6_REG #define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG +#define LIGHT_SLEEP_WAKE_STUB_ADDR_REG LP_AON_STORE8_REG #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index dc56946f90..5d4f24bf18 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1077,7 +1077,7 @@ config SOC_PM_SUPPORT_BT_WAKEUP config SOC_PM_SUPPORT_CPU_PD bool - default n + default y config SOC_PM_SUPPORT_XTAL32K_PD bool @@ -1095,6 +1095,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_PM_CPU_RETENTION_BY_SW + bool + default y + config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 5e704c6cba..000a59ce04 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -454,11 +454,12 @@ // TODO: IDF-6270 (Copy from esp32c6, need check) /*-------------------------- Power Management CAPS ----------------------------*/ #define SOC_PM_SUPPORT_BT_WAKEUP (1) -#define SOC_PM_SUPPORT_CPU_PD (0) +#define SOC_PM_SUPPORT_CPU_PD (1) #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_SW (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Tue, 16 May 2023 16:21:11 +0800 Subject: [PATCH 03/19] Power Management: support PAU REGDMA feature for esp32h2 --- .../include/esp_private/esp_pau.h | 20 +++ .../esp_hw_support/port/esp32h2/pmu_sleep.c | 11 +- components/esp_hw_support/port/pau_regdma.c | 23 +++- .../hal/esp32h2/include/hal/clk_gate_ll.h | 8 ++ components/hal/esp32h2/include/hal/pau_ll.h | 125 ++++++++++++++++++ components/hal/esp32h2/pau_hal.c | 59 +++++++++ components/hal/include/hal/pau_hal.h | 26 ++++ .../esp32h2/include/soc/Kconfig.soc_caps.in | 12 ++ .../soc/esp32h2/include/soc/pau_struct.h | 4 +- .../soc/esp32h2/include/soc/periph_defs.h | 1 + components/soc/esp32h2/include/soc/soc_caps.h | 3 + 11 files changed, 283 insertions(+), 9 deletions(-) create mode 100644 components/hal/esp32h2/include/hal/pau_ll.h create mode 100644 components/hal/esp32h2/pau_hal.c diff --git a/components/esp_hw_support/include/esp_private/esp_pau.h b/components/esp_hw_support/include/esp_private/esp_pau.h index 66c5e6ab3a..db6b059d27 100644 --- a/components/esp_hw_support/include/esp_private/esp_pau.h +++ b/components/esp_hw_support/include/esp_private/esp_pau.h @@ -25,6 +25,7 @@ extern "C" { */ void pau_regdma_set_entry_link_addr(pau_regdma_link_addr_t *link_entries); +#if SOC_PM_SUPPORT_PMU_MODEM_STATE /** * @brief Set the address of WiFi MAC REGDMA Link in modem state * @param link_addr linked lists address @@ -40,6 +41,25 @@ void pau_regdma_trigger_modem_link_backup(void); * @brief Software trigger regdma to perform modem link restore */ void pau_regdma_trigger_modem_link_restore(void); +#endif + +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +/** + * @brief Set the address of system REGDMA Link in active state + * @param link_addr linked lists address + */ +void pau_regdma_set_system_link_addr(void *link_addr); + +/** + * @brief Software trigger regdma to perform system link backup + */ +void pau_regdma_trigger_system_link_backup(void); + +/** + * @brief Software trigger regdma to perform system link restore + */ +void pau_regdma_trigger_system_link_restore(void); +#endif /** * @brief Set the address of extra REGDMA Link in active state diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index d1e9b51723..117ff51adb 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -22,16 +22,15 @@ 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); + /* ESP32H2 does not have PMU HP_AON power domain. because the registers + * of PAU REGDMA is included to PMU TOP power domain, cause the contents + * of PAU REGDMA registers will be lost when the TOP domain is powered down + * during light sleep, so we does not need to enable REGDMA backup here. + * We will use the software to trigger REGDMA to backup or restore. */ } 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) diff --git a/components/esp_hw_support/port/pau_regdma.c b/components/esp_hw_support/port/pau_regdma.c index 5d340c1b0a..6e8e4c8970 100644 --- a/components/esp_hw_support/port/pau_regdma.c +++ b/components/esp_hw_support/port/pau_regdma.c @@ -21,7 +21,7 @@ typedef struct { pau_hal_context_t *hal; } pau_context_t; -pau_context_t * __attribute__((weak)) PAU_instance(void) +pau_context_t * __attribute__((weak)) IRAM_ATTR PAU_instance(void) { static pau_hal_context_t pau_hal = { .dev = NULL }; static pau_context_t pau_context = { .hal = &pau_hal }; @@ -40,6 +40,7 @@ void pau_regdma_set_entry_link_addr(pau_regdma_link_addr_t *link_entries) pau_hal_set_regdma_entry_link_addr(PAU_instance()->hal, link_entries); } +#if SOC_PM_SUPPORT_PMU_MODEM_STATE void pau_regdma_set_modem_link_addr(void *link_addr) { pau_hal_set_regdma_modem_link_addr(PAU_instance()->hal, link_addr); @@ -56,6 +57,26 @@ void pau_regdma_trigger_modem_link_restore(void) pau_hal_start_regdma_modem_link(PAU_instance()->hal, false); pau_hal_stop_regdma_modem_link(PAU_instance()->hal); } +#endif + +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +void IRAM_ATTR pau_regdma_set_system_link_addr(void *link_addr) +{ + pau_hal_set_regdma_system_link_addr(PAU_instance()->hal, link_addr); +} + +void IRAM_ATTR pau_regdma_trigger_system_link_backup(void) +{ + pau_hal_start_regdma_system_link(PAU_instance()->hal, true); + pau_hal_stop_regdma_system_link(PAU_instance()->hal); +} + +void IRAM_ATTR pau_regdma_trigger_system_link_restore(void) +{ + pau_hal_start_regdma_system_link(PAU_instance()->hal, false); + pau_hal_stop_regdma_system_link(PAU_instance()->hal); +} +#endif void pau_regdma_set_extra_link_addr(void *link_addr) { diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index 08b7894c55..7a8cf3b84d 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -75,6 +75,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return PCR_ECDSA_CLK_EN; case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_CLK_EN; + case PERIPH_REGDMA_MODULE: + return PCR_REGDMA_CLK_EN; // case PERIPH_RNG_MODULE: // return PCR_WIFI_CLK_RNG_EN; // case PERIPH_WIFI_MODULE: @@ -146,6 +148,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN); } return PCR_ECC_RST_EN; + case PERIPH_REGDMA_MODULE: + return PCR_REGDMA_RST_EN; case PERIPH_AES_MODULE: if (enable == true) { // Clear reset on digital signature, otherwise AES unit is held in reset @@ -257,6 +261,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return PCR_ECDSA_CONF_REG; case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_CLK_CONF_REG; + case PERIPH_REGDMA_MODULE: + return PCR_REGDMA_CONF_REG; default: return 0; } @@ -322,6 +328,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return PCR_ECDSA_CONF_REG; case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_CLK_CONF_REG; + case PERIPH_REGDMA_MODULE: + return PCR_REGDMA_CONF_REG; default: return 0; } diff --git a/components/hal/esp32h2/include/hal/pau_ll.h b/components/hal/esp32h2/include/hal/pau_ll.h new file mode 100644 index 0000000000..98f730ff25 --- /dev/null +++ b/components/hal/esp32h2/include/hal/pau_ll.h @@ -0,0 +1,125 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-H2 PAU(Power Assist Unit) register operations + +#pragma once + +#include +#include +#include "soc/soc.h" +#include "soc/pau_reg.h" +#include "soc/pau_struct.h" +#include "hal/pau_types.h" +#include "hal/assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline __attribute__((always_inline)) uint32_t pau_ll_get_regdma_backup_flow_error(pau_dev_t *dev) +{ + return dev->regdma_conf.flow_err; +} + +static inline __attribute__((always_inline)) void pau_ll_select_regdma_entry_link(pau_dev_t *dev, int link) +{ + dev->regdma_conf.link_sel = link; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_entry_link_backup_direction(pau_dev_t *dev, bool to_mem) +{ + dev->regdma_conf.to_mem = to_mem ? 1 : 0; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_entry_link_backup_start_enable(pau_dev_t *dev) +{ + dev->regdma_conf.start = 1; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_entry_link_backup_start_disable(pau_dev_t *dev) +{ + dev->regdma_conf.start = 0; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_link0_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_0_addr.val = (uint32_t)link_addr; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_link1_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_1_addr.val = (uint32_t)link_addr; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_link2_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_2_addr.val = (uint32_t)link_addr; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_link3_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_3_addr.val = (uint32_t)link_addr; +} + +static inline __attribute__((always_inline)) uint32_t pau_ll_get_regdma_current_link_addr(pau_dev_t *dev) +{ + return dev->regdma_current_link_addr.val; +} + +static inline __attribute__((always_inline)) uint32_t pau_ll_get_regdma_backup_addr(pau_dev_t *dev) +{ + return dev->regdma_backup_addr.val; +} + +static inline __attribute__((always_inline)) uint32_t pau_ll_get_regdma_memory_addr(pau_dev_t *dev) +{ + return dev->regdma_mem_addr.val; +} + +static inline __attribute__((always_inline)) uint32_t pau_ll_get_regdma_intr_raw_signal(pau_dev_t *dev) +{ + return dev->int_raw.val; +} + +static inline __attribute__((always_inline)) uint32_t pau_ll_get_regdma_intr_status(pau_dev_t *dev) +{ + return dev->int_st.val; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_backup_done_intr_enable(pau_dev_t *dev) +{ + dev->int_ena.done_int_ena = 1; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_backup_done_intr_disable(pau_dev_t *dev) +{ + dev->int_ena.done_int_ena = 0; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_backup_error_intr_enable(pau_dev_t *dev) +{ + dev->int_ena.error_int_ena = 1; +} + +static inline __attribute__((always_inline)) void pau_ll_set_regdma_backup_error_intr_disable(pau_dev_t *dev) +{ + dev->int_ena.error_int_ena = 0; +} + +static inline __attribute__((always_inline)) void pau_ll_clear_regdma_backup_done_intr_state(pau_dev_t *dev) +{ + dev->int_clr.done_int_clr = 1; +} + +static inline __attribute__((always_inline)) void pau_ll_clear_regdma_backup_error_intr_state(pau_dev_t *dev) +{ + dev->int_clr.error_int_clr = 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/pau_hal.c b/components/hal/esp32h2/pau_hal.c new file mode 100644 index 0000000000..3f7ba1aab2 --- /dev/null +++ b/components/hal/esp32h2/pau_hal.c @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for PAU (ESP32-H2 specific part) + +#include "soc/soc.h" +#include "esp_attr.h" +#include "hal/pau_hal.h" +#include "hal/pau_types.h" + +void pau_hal_set_regdma_entry_link_addr(pau_hal_context_t *hal, pau_regdma_link_addr_t *link_addr) +{ + /* ESP32H2 does not have PMU HP_AON power domain. because the registers + * of PAU REGDMA is included to PMU TOP power domain, cause the contents + * of PAU REGDMA registers will be lost when the TOP domain is powered down + * during light sleep, so we does not need to enable REGDMA backup here. + * We will use the software to trigger REGDMA to backup or restore. */ +} + +void IRAM_ATTR pau_hal_start_regdma_system_link(pau_hal_context_t *hal, bool backup_or_restore) +{ + pau_ll_clear_regdma_backup_done_intr_state(hal->dev); + + pau_ll_select_regdma_entry_link(hal->dev, 0); + pau_ll_set_regdma_entry_link_backup_direction(hal->dev, backup_or_restore); + pau_ll_set_regdma_entry_link_backup_start_enable(hal->dev); + + while (!(pau_ll_get_regdma_intr_raw_signal(hal->dev) & PAU_DONE_INT_RAW)); +} + +void IRAM_ATTR pau_hal_stop_regdma_system_link(pau_hal_context_t *hal) +{ + pau_ll_set_regdma_entry_link_backup_start_disable(hal->dev); + pau_ll_select_regdma_entry_link(hal->dev, 0); /* restore link select to default */ + pau_ll_clear_regdma_backup_done_intr_state(hal->dev); +} + +void pau_hal_start_regdma_extra_link(pau_hal_context_t *hal, bool backup_or_restore) +{ + pau_ll_clear_regdma_backup_done_intr_state(hal->dev); + /* The link 3 of REGDMA is reserved, we use it as an extra linked list to + * provide backup and restore services for BLE, IEEE802.15.4 and possibly + * other modules */ + pau_ll_select_regdma_entry_link(hal->dev, 3); + pau_ll_set_regdma_entry_link_backup_direction(hal->dev, backup_or_restore); + pau_ll_set_regdma_entry_link_backup_start_enable(hal->dev); + + while (!(pau_ll_get_regdma_intr_raw_signal(hal->dev) & PAU_DONE_INT_RAW)); +} + +void pau_hal_stop_regdma_extra_link(pau_hal_context_t *hal) +{ + pau_ll_set_regdma_entry_link_backup_start_disable(hal->dev); + pau_ll_select_regdma_entry_link(hal->dev, 0); /* restore link select to default */ + pau_ll_clear_regdma_backup_done_intr_state(hal->dev); +} diff --git a/components/hal/include/hal/pau_hal.h b/components/hal/include/hal/pau_hal.h index 403765eef6..5b28a957d2 100644 --- a/components/hal/include/hal/pau_hal.h +++ b/components/hal/include/hal/pau_hal.h @@ -28,6 +28,7 @@ typedef struct { */ void pau_hal_set_regdma_entry_link_addr(pau_hal_context_t *hal, pau_regdma_link_addr_t *link_addr); +#if SOC_PM_SUPPORT_PMU_MODEM_STATE /** * @brief Set regdma modem link address * @@ -50,6 +51,31 @@ void pau_hal_start_regdma_modem_link(pau_hal_context_t *hal, bool backup_or_rest * @param hal regdma hal context */ void pau_hal_stop_regdma_modem_link(pau_hal_context_t *hal); +#endif + +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +/** + * @brief Set regdma system link address + * + * @param hal regdma hal context + * @param link_addr main link address value + */ +#define pau_hal_set_regdma_system_link_addr(hal, addr) pau_ll_set_regdma_link0_addr(hal->dev, (addr)) + +/** + * @brief Start transmission on regdma system link + * + * @param hal regdma hal context + * @param backup_or_restore false:restore true:backup + */ +void pau_hal_start_regdma_system_link(pau_hal_context_t *hal, bool backup_or_restore); +/** + * @brief Stop transmission on regdma system link + * + * @param hal regdma hal context + */ +void pau_hal_stop_regdma_system_link(pau_hal_context_t *hal); +#endif /** * @brief Set regdma extra link address diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 5d4f24bf18..3965daeb40 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -171,6 +171,10 @@ config SOC_LP_TIMER_SUPPORTED bool default y +config SOC_PAU_SUPPORTED + bool + default y + config SOC_CLK_TREE_SUPPORTED bool default y @@ -1095,6 +1099,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_PM_PAU_LINK_NUM + int + default 4 + config SOC_PM_CPU_RETENTION_BY_SW bool default y @@ -1103,6 +1111,10 @@ config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y +config SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG + bool + default y + config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32h2/include/soc/pau_struct.h b/components/soc/esp32h2/include/soc/pau_struct.h index 610b0e4e07..9fd6347265 100644 --- a/components/soc/esp32h2/include/soc/pau_struct.h +++ b/components/soc/esp32h2/include/soc/pau_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 */ @@ -334,7 +334,7 @@ typedef union { } pau_date_reg_t; -typedef struct { +typedef struct pau_dev_t { volatile pau_regdma_conf_reg_t regdma_conf; volatile pau_regdma_clk_conf_reg_t regdma_clk_conf; volatile pau_regdma_etm_ctrl_reg_t regdma_etm_ctrl; diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index 5a954b200d..b4f30cd754 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -41,6 +41,7 @@ typedef enum { PERIPH_SYSTIMER_MODULE, PERIPH_SARADC_MODULE, PERIPH_TEMPSENSOR_MODULE, + PERIPH_REGDMA_MODULE, /* Peripherals clock managed by the modem_clock driver must be listed last in the enumeration */ PERIPH_BT_MODULE, PERIPH_IEEE802154_MODULE, diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 000a59ce04..a039ed8c76 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -68,6 +68,7 @@ #define SOC_APM_SUPPORTED 1 #define SOC_PMU_SUPPORTED 1 #define SOC_LP_TIMER_SUPPORTED 1 +#define SOC_PAU_SUPPORTED 1 #define SOC_CLK_TREE_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ @@ -459,8 +460,10 @@ #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_PAU_LINK_NUM (4) #define SOC_PM_CPU_RETENTION_BY_SW (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Mon, 24 Apr 2023 11:43:06 +0800 Subject: [PATCH 04/19] Power Management: support TOP domain powered down in light sleep for esp32h2 --- components/esp_hw_support/sleep_clock.c | 5 ++++- components/esp_hw_support/sleep_system_peripheral.c | 8 +++++++- components/soc/esp32h2/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32h2/include/soc/soc_caps.h | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c index 47866bfc32..655fcee5de 100644 --- a/components/esp_hw_support/sleep_clock.c +++ b/components/esp_hw_support/sleep_clock.c @@ -27,8 +27,11 @@ static __attribute__((unused)) const char *TAG = "sleep_clock"; esp_err_t sleep_clock_system_retention_init(void) { +#if CONFIG_IDF_TARGET_ESP32C6 #define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_REG - DR_REG_PCR_BASE) / 4) + 1) - +#elif CONFIG_IDF_TARGET_ESP32H2 + #define N_REGS_PCR() (((PCR_PWDET_SAR_CLK_CONF_REG - DR_REG_PCR_BASE) / 4) + 1) +#endif const static sleep_retention_entries_config_t pcr_regs_retention[] = { [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* pcr */ }; diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index fd18212774..8f472d84d8 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -118,11 +118,17 @@ esp_err_t sleep_sys_periph_tg0_retention_init(void) esp_err_t sleep_sys_periph_iomux_retention_init(void) { +#if CONFIG_IDF_TARGET_ESP32C6 #define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_SPID_U - REG_IO_MUX_BASE) / 4) + 1) #define N_REGS_IOMUX_1() (((GPIO_FUNC34_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) #define N_REGS_IOMUX_2() (((GPIO_FUNC124_IN_SEL_CFG_REG - GPIO_STATUS_NEXT_REG) / 4) + 1) #define N_REGS_IOMUX_3() (((GPIO_PIN34_REG - DR_REG_GPIO_BASE) / 4) + 1) - +#elif CONFIG_IDF_TARGET_ESP32H2 + #define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_SPID_U - REG_IO_MUX_BASE) / 4) + 1) + #define N_REGS_IOMUX_1() (((GPIO_FUNC31_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) + #define N_REGS_IOMUX_2() (((GPIO_FUNC124_IN_SEL_CFG_REG - GPIO_STATUS_NEXT_REG) / 4) + 1) + #define N_REGS_IOMUX_3() (((GPIO_PIN31_REG - DR_REG_GPIO_BASE) / 4) + 1) +#endif const static sleep_retention_entries_config_t iomux_regs_retention[] = { [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */ [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 3965daeb40..f431cb030e 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1099,6 +1099,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_PM_SUPPORT_TOP_PD + bool + default y + config SOC_PM_PAU_LINK_NUM int default 4 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index a039ed8c76..80554fc7aa 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -460,6 +460,7 @@ #define SOC_PM_SUPPORT_RC32K_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) +#define SOC_PM_SUPPORT_TOP_PD (1) #define SOC_PM_PAU_LINK_NUM (4) #define SOC_PM_CPU_RETENTION_BY_SW (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Mon, 24 Apr 2023 14:56:50 +0800 Subject: [PATCH 05/19] Power Management: fix REGDMA power issue when TOP domain powered down during light sleep for esp32h2 --- .../include/esp_private/sleep_retention.h | 10 ++++++++++ components/esp_hw_support/sleep_modes.c | 7 +++++++ components/esp_hw_support/sleep_retention.c | 17 +++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_retention.h index 98ed4b01c9..2c1bb7fecf 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -123,6 +123,16 @@ void sleep_retention_do_extra_retention(bool backup_or_restore); */ uint32_t sleep_retention_get_modules(void); +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +/** + * @brief Software trigger REGDMA to do system linked list retention + * + * @param backup_or_restore true for backup register context to memory + * or false for restore to register from memory + */ +void sleep_retention_do_system_retention(bool backup_or_restore); +#endif + #endif // SOC_PAU_SUPPORTED #ifdef __cplusplus diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 1d1688610d..c573890955 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -87,6 +87,7 @@ #include "esp_private/sleep_sys_periph.h" #include "esp_private/sleep_clock.h" #elif CONFIG_IDF_TARGET_ESP32H2 +#include "esp_private/sleep_retention.h" #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/cache.h" #include "esp32h2/rom/rtc.h" @@ -509,6 +510,9 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(bool deep_sleep) #endif #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_read(); +#endif +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG + sleep_retention_do_system_retention(true); #endif } @@ -523,6 +527,9 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(bool deep_sleep) */ inline static void IRAM_ATTR misc_modules_wake_prepare(void) { +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG + sleep_retention_do_system_retention(false); +#endif sar_periph_ctrl_power_enable(); #if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL sleep_disable_cpu_retention(); diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index 76d4327b0f..af357efb3b 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -530,3 +530,20 @@ void sleep_retention_do_extra_retention(bool backup_or_restore) assert(refs >= 0 && refs <= cnt_modules); } #endif + +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +void IRAM_ATTR sleep_retention_do_system_retention(bool backup_or_restore) +{ + #define SYSTEM_LINK_NUM (0) + if (s_retention.highpri >= SLEEP_RETENTION_REGDMA_LINK_HIGHEST_PRIORITY && + s_retention.highpri <= SLEEP_RETENTION_REGDMA_LINK_LOWEST_PRIORITY) { + // Set extra linked list head pointer to hardware + pau_regdma_set_system_link_addr(s_retention.lists[s_retention.highpri].entries[SYSTEM_LINK_NUM]); + if (backup_or_restore) { + pau_regdma_trigger_system_link_backup(); + } else { + pau_regdma_trigger_system_link_restore(); + } + } +} +#endif From d3ca0656c8e98282455e9a27af7be60e13b449f8 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Sun, 21 May 2023 18:42:03 +0800 Subject: [PATCH 06/19] Power Management: support MODEM domain powered down in light sleep for esp32h2 --- components/soc/esp32h2/include/soc/Kconfig.soc_caps.in | 8 ++++++++ components/soc/esp32h2/include/soc/soc_caps.h | 7 +++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index f431cb030e..3713255145 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1083,6 +1083,10 @@ config SOC_PM_SUPPORT_CPU_PD bool default y +config SOC_PM_SUPPORT_MODEM_PD + bool + default y + config SOC_PM_SUPPORT_XTAL32K_PD bool default y @@ -1111,6 +1115,10 @@ config SOC_PM_CPU_RETENTION_BY_SW bool default y +config SOC_PM_MODEM_RETENTION_BY_REGDMA + bool + default y + config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 80554fc7aa..7f9e65303d 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -452,10 +452,10 @@ /*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/ #define SOC_PHY_DIG_REGS_MEM_SIZE (21*4) -// TODO: IDF-6270 (Copy from esp32c6, need check) /*-------------------------- Power Management CAPS ----------------------------*/ #define SOC_PM_SUPPORT_BT_WAKEUP (1) #define SOC_PM_SUPPORT_CPU_PD (1) +#define SOC_PM_SUPPORT_MODEM_PD (1) /*! Date: Fri, 19 May 2023 15:39:12 +0800 Subject: [PATCH 07/19] Power Management: fix REGDMA clock issue when wake up form light sleep --- components/esp_hw_support/port/pau_regdma.c | 10 ++++++++++ components/hal/esp32h2/pau_hal.c | 8 ++++++++ components/hal/include/hal/pau_hal.h | 9 +++++++++ components/soc/esp32h2/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32h2/include/soc/soc_caps.h | 1 + 5 files changed, 32 insertions(+) diff --git a/components/esp_hw_support/port/pau_regdma.c b/components/esp_hw_support/port/pau_regdma.c index 6e8e4c8970..aab6b17860 100644 --- a/components/esp_hw_support/port/pau_regdma.c +++ b/components/esp_hw_support/port/pau_regdma.c @@ -26,6 +26,9 @@ pau_context_t * __attribute__((weak)) IRAM_ATTR PAU_instance(void) static pau_hal_context_t pau_hal = { .dev = NULL }; static pau_context_t pau_context = { .hal = &pau_hal }; + /* periph_module_enable don not need to be put in iram because it is + * called before the flash is powered off and will not be called again. */ + if (pau_hal.dev == NULL) { pau_hal.dev = &PAU; periph_module_enable(PERIPH_REGDMA_MODULE); @@ -62,6 +65,13 @@ void pau_regdma_trigger_modem_link_restore(void) #if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG void IRAM_ATTR pau_regdma_set_system_link_addr(void *link_addr) { + /* ESP32H2 use software to trigger REGDMA to restore instead of PMU, + * because regdma has power bug, so we need to manually set the clock + * for regdma before using it after the chip wakes up. We use + * pau_hal_clock_configure because periph_module_enable will consume + * a relatively large amount of memory space. */ + + pau_hal_regdma_clock_configure(PAU_instance()->hal, true); pau_hal_set_regdma_system_link_addr(PAU_instance()->hal, link_addr); } diff --git a/components/hal/esp32h2/pau_hal.c b/components/hal/esp32h2/pau_hal.c index 3f7ba1aab2..cbfecc77e6 100644 --- a/components/hal/esp32h2/pau_hal.c +++ b/components/hal/esp32h2/pau_hal.c @@ -7,7 +7,9 @@ // The HAL layer for PAU (ESP32-H2 specific part) #include "soc/soc.h" +#include "soc/pcr_struct.h" #include "esp_attr.h" +#include "hal/misc.h" #include "hal/pau_hal.h" #include "hal/pau_types.h" @@ -57,3 +59,9 @@ void pau_hal_stop_regdma_extra_link(pau_hal_context_t *hal) pau_ll_select_regdma_entry_link(hal->dev, 0); /* restore link select to default */ pau_ll_clear_regdma_backup_done_intr_state(hal->dev); } + +void IRAM_ATTR pau_hal_regdma_clock_configure(pau_hal_context_t *hal, bool enable) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.regdma_conf, regdma_rst_en, !enable); + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.regdma_conf, regdma_clk_en, enable); +} diff --git a/components/hal/include/hal/pau_hal.h b/components/hal/include/hal/pau_hal.h index 5b28a957d2..5aae8900f5 100644 --- a/components/hal/include/hal/pau_hal.h +++ b/components/hal/include/hal/pau_hal.h @@ -100,6 +100,15 @@ void pau_hal_start_regdma_extra_link(pau_hal_context_t *hal, bool backup_or_rest */ void pau_hal_stop_regdma_extra_link(pau_hal_context_t *hal); +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +/** + * @brief Enable or disable PAU module clock + * + * @param hal regdma hal context + */ +void pau_hal_regdma_clock_configure(pau_hal_context_t *hal, bool enable); +#endif + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 3713255145..69465be938 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1127,6 +1127,10 @@ config SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG bool default y +config SOC_PM_RETENTION_HAS_CLOCK_BUG + bool + default y + config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 7f9e65303d..de630affcb 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -466,6 +466,7 @@ #define SOC_PM_MODEM_RETENTION_BY_REGDMA (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Mon, 29 May 2023 12:01:36 +0800 Subject: [PATCH 08/19] Power Management: update pmu init and sleep parameter --- .../esp_hw_support/port/esp32h2/pmu_param.c | 6 ++-- .../port/esp32h2/private_include/pmu_param.h | 32 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/components/esp_hw_support/port/esp32h2/pmu_param.c b/components/esp_hw_support/port/esp32h2/pmu_param.c index 7ddd9296ab..715c5552ca 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_param.c +++ b/components/esp_hw_support/port/esp32h2/pmu_param.c @@ -166,7 +166,7 @@ const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mod .syscntl = { \ .uart_wakeup_en = 1, \ .lp_pad_hold_all = 0, \ - .hp_pad_hold_all = 1, \ + .hp_pad_hold_all = 0, \ .dig_pad_slp_sel = 1, \ .dig_pause_wdt = 1, \ .dig_cpu_stall = 1 \ @@ -176,8 +176,8 @@ const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mod #define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \ .syscntl = { \ .uart_wakeup_en = 1, \ - .lp_pad_hold_all = 1, \ - .hp_pad_hold_all = 1, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ .dig_pad_slp_sel = 0, \ .dig_pause_wdt = 1, \ .dig_cpu_stall = 1 \ 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 e79adc6404..57bea2061c 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 @@ -172,38 +172,36 @@ typedef struct { .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, \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .xpd = 1, \ .dbias = 0, \ - .drv_b = 0 \ + .drv_b = 0xFFFFF8 \ } \ }, \ .lp_sys[PMU_MODE_LP_ACTIVE] = { \ .analog = { \ .slp_xpd = 0, \ - .slp_dbias = 0xc, \ + .slp_dbias = 0x0, \ .xpd = 1, \ - .dbias = 0x1a, \ + .dbias = 0xe, \ .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, \ + .dbias = 0, \ .slp_xpd = 1, \ - .slp_dbias = 0x3, \ - .drv_b = 0x0 \ + .slp_dbias = 0x5, \ + .drv_b = 0x7 \ } \ } \ } @@ -294,8 +292,6 @@ typedef struct pmu_sleep_machine_constant { } 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) */ @@ -318,13 +314,11 @@ typedef struct pmu_sleep_machine_constant { }, \ .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, \ + .regdma_s2a_work_time_us = 0, \ + .regdma_a2s_work_time_us = 0, \ .xtal_wait_stable_time_us = 250, \ .pll_wait_stable_time_us = 1 \ } \ From 2657d8f3079c1668a3444945b45cdc110e15e8cc Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Fri, 19 May 2023 16:26:58 +0800 Subject: [PATCH 09/19] Power Management: change the IO hold interface for esp32c6 --- components/esp_hw_support/Kconfig | 7 ++++--- components/esp_hw_support/sleep_modes.c | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 328d6e708f..ec7038736e 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -76,11 +76,12 @@ menu "Hardware Settings" config ESP_SLEEP_GPIO_RESET_WORKAROUND bool "light sleep GPIO reset workaround" - default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 + default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || \ + IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 select PM_SLP_DISABLE_GPIO if FREERTOS_USE_TICKLESS_IDLE help - esp32c2, esp32c3 and esp32s3 will reset at wake-up if GPIO is received a small electrostatic - pulse during light sleep, with specific condition + esp32c2, esp32c3, esp32s3, esp32c6 and esp32h2 will reset at wake-up if GPIO is received + a small electrostatic pulse during light sleep, with specific condition - GPIO needs to be configured as input-mode only - The pin receives a small electrostatic pulse, and reset occurs when the pulse diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index c573890955..1a09e0e5b9 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -86,6 +86,7 @@ #include "esp_private/esp_pmu.h" #include "esp_private/sleep_sys_periph.h" #include "esp_private/sleep_clock.h" +#include "hal/gpio_ll.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp_private/sleep_retention.h" #include "esp32h2/rom/rtc.h" @@ -722,8 +723,9 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m /* 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) +#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) { - rtcio_ll_force_hold_enable(SPI_CS0_GPIO_NUM); + gpio_ll_hold_en(&GPIO, SPI_CS0_GPIO_NUM); } #endif #endif @@ -742,9 +744,11 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m /* Unhold the SPI CS pin */ #if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND) +#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) { - rtcio_ll_force_hold_disable(SPI_CS0_GPIO_NUM); + gpio_ll_hold_dis(&GPIO, SPI_CS0_GPIO_NUM); } +#endif #endif } From 7fd74057a3275deaad93e796ed3deb2b9a591438 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Mon, 22 May 2023 19:14:42 +0800 Subject: [PATCH 10/19] example: bringup light sleep example for esp32h2 --- .../src/esp32h2/bootloader_esp32h2.c | 1 - components/driver/ledc/ledc.c | 4 ---- components/driver/test_apps/gpio/main/test_gpio.c | 2 -- components/esp_hw_support/modem_clock.c | 8 -------- components/esp_hw_support/sleep_modes.c | 13 +++++-------- components/esp_pm/.build-test-rules.yml | 7 ------- components/esp_pm/Kconfig | 5 +---- components/esp_pm/test_apps/esp_pm/README.md | 4 ++-- components/esp_pm/test_apps/esp_pm/main/test_pm.c | 2 ++ components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py | 13 ++++++------- .../esp_system_unity_tests/main/test_sleep.c | 8 ++++---- components/hal/esp32h2/include/hal/uart_ll.h | 2 +- .../soc/esp32h2/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32h2/include/soc/soc_caps.h | 2 +- examples/system/.build-test-rules.yml | 6 ------ examples/system/light_sleep/README.md | 4 ++-- examples/system/light_sleep/pytest_light_sleep.py | 7 +------ 17 files changed, 29 insertions(+), 63 deletions(-) delete mode 100644 components/esp_pm/.build-test-rules.yml diff --git a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c index 6fcdfcc8c4..022f796892 100644 --- a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c +++ b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c @@ -86,7 +86,6 @@ static void bootloader_super_wdt_auto_feed(void) static inline void bootloader_hardware_init(void) { - // TODO: IDF-6267 /* Enable analog i2c master clock */ SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN); } diff --git a/components/driver/ledc/ledc.c b/components/driver/ledc/ledc.c index 39f9a95e2d..f7afd11736 100644 --- a/components/driver/ledc/ledc.c +++ b/components/driver/ledc/ledc.c @@ -440,9 +440,7 @@ static uint32_t ledc_auto_clk_divisor(ledc_mode_t speed_mode, int freq_hz, uint3 return ret; } -#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6267 Remove when H2 light sleep supported extern void esp_sleep_periph_use_8m(bool use_or_not); -#endif /** * @brief Function setting the LEDC timer divisor with the given source clock, @@ -559,9 +557,7 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n ESP_LOGD(LEDC_TAG, "In slow speed mode, global clk set: %d", glb_clk); /* keep ESP_PD_DOMAIN_RC_FAST on during light sleep */ -#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6267 Remove when H2 light sleep supported esp_sleep_periph_use_8m(glb_clk == LEDC_SLOW_CLK_RC_FAST); -#endif } /* The divisor is correct, we can write in the hardware. */ diff --git a/components/driver/test_apps/gpio/main/test_gpio.c b/components/driver/test_apps/gpio/main/test_gpio.c index ede7e2e527..b62b90c729 100644 --- a/components/driver/test_apps/gpio/main/test_gpio.c +++ b/components/driver/test_apps/gpio/main/test_gpio.c @@ -844,7 +844,6 @@ TEST_CASE("GPIO_USB_DP_pin_pullup_disable_test", "[gpio]") } #endif //SOC_USB_SERIAL_JTAG_SUPPORTED -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2) // TODO: IDF-6267 Remove when light sleep is supported // Ignored in CI because it needs manually connect TEST_GPIO_INPUT_LEVEL_LOW_PIN to 3.3v to wake up from light sleep TEST_CASE("GPIO_light_sleep_wake_up_test", "[gpio][ignore]") { @@ -861,4 +860,3 @@ TEST_CASE("GPIO_light_sleep_wake_up_test", "[gpio][ignore]") printf("Waked up from light sleep\n"); TEST_ASSERT(esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_GPIO); } -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(...) diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index fdb0319826..dec1c3c332 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -318,7 +318,6 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = src; portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); -#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6267 /* The power domain of the low-power clock source required by the modem * module remains powered on during sleep */ esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) ( \ @@ -335,9 +334,6 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl : ESP_PD_DOMAIN_MAX); esp_sleep_pd_config(pd_domain, ESP_PD_OPTION_OFF); esp_sleep_pd_config(pu_domain, ESP_PD_OPTION_ON); -#else - (void)last_src; // Only for bypass compile warning, delete if IDF-6267 resloved -#endif //!CONFIG_IDF_TARGET_ESP32H2 } void modem_clock_deselect_lp_clock_source(periph_module_t module) @@ -370,7 +366,6 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = MODEM_CLOCK_LPCLK_SRC_INVALID; portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); -#if !CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-6267 esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) ( \ (last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST \ : (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL \ @@ -378,7 +373,4 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) : (last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K \ : ESP_PD_DOMAIN_MAX); esp_sleep_pd_config(pd_domain, ESP_PD_OPTION_OFF); -#else - (void)last_src; // Only for bypass compile warning, delete if IDF-6267 resloved -#endif //!CONFIG_IDF_TARGET_ESP32H2 } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 1a09e0e5b9..1cb4dd4215 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -83,16 +83,14 @@ #elif CONFIG_IDF_TARGET_ESP32C6 #include "esp32c6/rom/rtc.h" #include "hal/lp_timer_hal.h" -#include "esp_private/esp_pmu.h" -#include "esp_private/sleep_sys_periph.h" -#include "esp_private/sleep_clock.h" #include "hal/gpio_ll.h" #elif CONFIG_IDF_TARGET_ESP32H2 -#include "esp_private/sleep_retention.h" #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/cache.h" #include "esp32h2/rom/rtc.h" #include "soc/extmem_reg.h" +#endif + #if SOC_LP_TIMER_SUPPORTED #include "hal/lp_timer_hal.h" #endif @@ -102,6 +100,9 @@ #include "esp_private/sleep_sys_periph.h" #include "esp_private/sleep_clock.h" #endif + +#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG +#include "esp_private/sleep_retention.h" #endif // If light sleep time is less than that, don't power down flash @@ -1569,9 +1570,6 @@ esp_err_t esp_sleep_disable_bt_wakeup(void) esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) { -#if CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-5645 - return ESP_SLEEP_WAKEUP_UNDEFINED; -#else if (esp_rom_get_reset_reason(0) != RESET_REASON_CORE_DEEP_SLEEP && !s_light_sleep_wakeup) { return ESP_SLEEP_WAKEUP_UNDEFINED; } @@ -1625,7 +1623,6 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) } else { return ESP_SLEEP_WAKEUP_UNDEFINED; } -#endif } esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_t option) diff --git a/components/esp_pm/.build-test-rules.yml b/components/esp_pm/.build-test-rules.yml deleted file mode 100644 index 421533b5af..0000000000 --- a/components/esp_pm/.build-test-rules.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps - -components/esp_pm/test_apps/esp_pm: - disable: - - if: IDF_TARGET in ["esp32h2"] - temporary: true - reason: Not supported yet diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index a930c65ab7..4541fb3347 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -2,10 +2,7 @@ menu "Power Management" config PM_ENABLE bool "Support for power management" # SMP FreeRTOS currently does not support power management IDF-4997 - # 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 || __DOXYGEN__ + depends on !FREERTOS_SMP default n help If enabled, application is compiled with support for power management. diff --git a/components/esp_pm/test_apps/esp_pm/README.md b/components/esp_pm/test_apps/esp_pm/README.md index 7e7523ec85..a8b7833fa3 100644 --- a/components/esp_pm/test_apps/esp_pm/README.md +++ b/components/esp_pm/test_apps/esp_pm/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_pm/test_apps/esp_pm/main/test_pm.c b/components/esp_pm/test_apps/esp_pm/main/test_pm.c index 43f9df74e6..5245c7527a 100644 --- a/components/esp_pm/test_apps/esp_pm/main/test_pm.c +++ b/components/esp_pm/test_apps/esp_pm/main/test_pm.c @@ -64,6 +64,8 @@ static void switch_freq(int mhz) #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 static const int test_freqs[] = {40, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, 80, 40, 80, 10, 80, 20, 40}; +#elif CONFIG_IDF_TARGET_ESP32H2 +static const int test_freqs[] = {32, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, 64, 48, 32, 64, 48, 8, 64, 48, 16, 32}; #elif CONFIG_IDF_TARGET_ESP32C2 static const int test_freqs[] = {CONFIG_XTAL_FREQ, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, 80, CONFIG_XTAL_FREQ, 80, CONFIG_XTAL_FREQ / 2, CONFIG_XTAL_FREQ}; // C2 xtal has 40/26MHz option diff --git a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py index fea31fc4b8..3e6d410793 100644 --- a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py +++ b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py @@ -4,14 +4,13 @@ import pytest from pytest_embedded import Dut -CONFIGS = [ - pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]), - pytest.param('limits', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]), - pytest.param('options', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]), -] - @pytest.mark.generic -@pytest.mark.parametrize('config', CONFIGS, indirect=True) +@pytest.mark.supported_targets +@pytest.mark.parametrize('config', [ + 'default', + 'limits', + 'options', +], indirect=True) def test_esp_pm(dut: Dut) -> None: dut.run_all_single_board_cases() 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 b5394c903c..681ae8a81d 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 @@ -41,7 +41,7 @@ __attribute__((unused)) static struct timeval tv_start, tv_stop; -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2) static void check_sleep_reset(void) { @@ -308,7 +308,7 @@ static void check_wake_stub(void) { TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason()); TEST_ASSERT_EQUAL_HEX32((uint32_t) &wake_stub, s_wake_stub_var); -#if !CONFIG_IDF_TARGET_ESP32S3 +#if !CONFIG_IDF_TARGET_ESP32S3 && !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 /* ROM code clears wake stub entry address */ TEST_ASSERT_NULL(esp_get_deep_sleep_wake_stub()); #endif @@ -463,7 +463,7 @@ __attribute__((unused)) static uint32_t get_cause(void) return wakeup_cause; } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C6, ESP32H2) // Fails on S2 IDF-2903 // This test case verifies deactivation of trigger for wake up sources @@ -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-6268 +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2) TODO: IDF-6268 diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index f079d53f70..677f4df75e 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -75,7 +75,7 @@ typedef enum { UART_INTR_RS485_FRM_ERR = (0x1 << 16), UART_INTR_RS485_CLASH = (0x1 << 17), UART_INTR_CMD_CHAR_DET = (0x1 << 18), - // UART_INTR_WAKEUP = (0x1 << 19), // TODO: IDF-6267 + UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; /** diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 69465be938..9e37c11849 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1063,6 +1063,10 @@ config SOC_UART_SUPPORT_XTAL_CLK bool default y +config SOC_UART_SUPPORT_WAKEUP_INT + bool + default y + config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index de630affcb..cd3cc4762d 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -439,7 +439,7 @@ #define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ #define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ -// #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ // TODO: IDF-6267 +#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 6e0cc7570b..24bf39b4c3 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -72,12 +72,6 @@ examples/system/ipc/ipc_isr: temporary: true reason: the other targets are not tested yet -examples/system/light_sleep: - disable: - - if: IDF_TARGET in ["esp32h2"] - temporary: true - reason: target(s) not supported yet - examples/system/ota/advanced_https_ota: disable: - if: IDF_TARGET == "esp32h2" diff --git a/examples/system/light_sleep/README.md b/examples/system/light_sleep/README.md index 15af3fe6f7..628813c07f 100644 --- a/examples/system/light_sleep/README.md +++ b/examples/system/light_sleep/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # Light Sleep Example diff --git a/examples/system/light_sleep/pytest_light_sleep.py b/examples/system/light_sleep/pytest_light_sleep.py index f2c743ad16..aee220741f 100644 --- a/examples/system/light_sleep/pytest_light_sleep.py +++ b/examples/system/light_sleep/pytest_light_sleep.py @@ -8,12 +8,7 @@ import pytest from pytest_embedded import Dut -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32s3 -@pytest.mark.esp32c3 -@pytest.mark.esp32c2 -@pytest.mark.esp32c6 +@pytest.mark.supported_targets @pytest.mark.generic def test_light_sleep(dut: Dut) -> None: From 9613692350ca867c1ca99646e437e079ea720956 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Mon, 22 May 2023 20:13:05 +0800 Subject: [PATCH 11/19] codeclean: fix prefix to LP_AON and add LP_AON_STORE8_REG --- components/esp_rom/include/esp32h2/rom/rtc.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/components/esp_rom/include/esp32h2/rom/rtc.h b/components/esp_rom/include/esp32h2/rom/rtc.h index 8648cf3e7b..7f516d704b 100644 --- a/components/esp_rom/include/esp32h2/rom/rtc.h +++ b/components/esp_rom/include/esp32h2/rom/rtc.h @@ -42,14 +42,15 @@ extern "C" { * ************************************************************************************* * RTC store registers usage - * RTC_CNTL_STORE0_REG Reserved - * RTC_CNTL_STORE1_REG RTC_SLOW_CLK calibration value - * RTC_CNTL_STORE2_REG Boot time, low word - * RTC_CNTL_STORE3_REG Boot time, high word - * RTC_CNTL_STORE4_REG External XTAL frequency - * RTC_CNTL_STORE5_REG APB bus frequency - * RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY - * RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC + * LP_AON_STORE0_REG Reserved + * LP_AON_STORE1_REG RTC_SLOW_CLK calibration value + * LP_AON_STORE2_REG Boot time, low word + * LP_AON_STORE3_REG Boot time, high word + * LP_AON_STORE4_REG External XTAL frequency + * LP_AON_STORE5_REG APB bus frequency + * LP_AON_STORE6_REG FAST_RTC_MEMORY_ENTRY + * LP_AON_STORE7_REG FAST_RTC_MEMORY_CRC + * LP_AON_STORE8_REG Store light sleep wake stub addr ************************************************************************************* */ From b5a293ab69419aa60298d76eb4f42bccffb3b011 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Mon, 29 May 2023 10:59:24 +0800 Subject: [PATCH 12/19] Power Management: support RC32K or Crystal32K powered down --- components/esp_system/port/soc/esp32h2/clk.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/esp_system/port/soc/esp32h2/clk.c b/components/esp_system/port/soc/esp32h2/clk.c index 4486b893b1..7b3e363685 100644 --- a/components/esp_system/port/soc/esp32h2/clk.c +++ b/components/esp_system/port/soc/esp32h2/clk.c @@ -26,6 +26,7 @@ #include "esp_private/esp_pmu.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" +#include "esp_sleep.h" /* Number of cycles to wait from the 32k XTAL oscillator to consider it running. * Larger values increase startup delay. Smaller values may cause false positive @@ -179,6 +180,13 @@ void rtc_clk_select_rtc_slow_clk(void) */ __attribute__((weak)) void esp_perip_clk_init(void) { + soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); + esp_sleep_pd_domain_t pu_domain = (esp_sleep_pd_domain_t) (\ + (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K \ + : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K \ + : ESP_PD_DOMAIN_MAX); + esp_sleep_pd_config(pu_domain, ESP_PD_OPTION_ON); + ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet"); // ESP32H2-TODO: IDF-5658 #if 0 From 01fb28b65bb9fb485c50a24acfaaefece6ec907d Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Tue, 13 Jun 2023 20:36:28 +0800 Subject: [PATCH 13/19] Power Management: move lp_timer_hal.c to upper hal layer for esp32h2 and esp32c6 --- components/hal/CMakeLists.txt | 6 +-- .../hal/esp32h2/include/hal/lp_timer_hal.h | 45 ------------------ components/hal/esp32h2/lp_timer_hal.c | 46 ------------------- .../{esp32c6 => }/include/hal/lp_timer_hal.h | 3 +- components/hal/{esp32c6 => }/lp_timer_hal.c | 0 5 files changed, 2 insertions(+), 98 deletions(-) delete mode 100644 components/hal/esp32h2/include/hal/lp_timer_hal.h delete mode 100644 components/hal/esp32h2/lp_timer_hal.c rename components/hal/{esp32c6 => }/include/hal/lp_timer_hal.h (91%) rename components/hal/{esp32c6 => }/lp_timer_hal.c (100%) diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 1c6997902c..8ceb53b3aa 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -30,10 +30,6 @@ if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) endif() endif() -if(${target} STREQUAL "esp32c6") - list(APPEND srcs "esp32c6/lp_timer_hal.c") -endif() - if(NOT BOOTLOADER_BUILD) list(APPEND srcs "rtc_io_hal.c" @@ -143,7 +139,7 @@ if(NOT BOOTLOADER_BUILD) endif() if(CONFIG_SOC_LP_TIMER_SUPPORTED) - list(APPEND srcs "${target}/lp_timer_hal.c") + list(APPEND srcs "lp_timer_hal.c") endif() if(CONFIG_SOC_PAU_SUPPORTED) diff --git a/components/hal/esp32h2/include/hal/lp_timer_hal.h b/components/hal/esp32h2/include/hal/lp_timer_hal.h deleted file mode 100644 index 39fa017ab5..0000000000 --- a/components/hal/esp32h2/include/hal/lp_timer_hal.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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/lp_timer_hal.c b/components/hal/esp32h2/lp_timer_hal.c deleted file mode 100644 index c27e7bcc2d..0000000000 --- a/components/hal/esp32h2/lp_timer_hal.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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/esp32c6/include/hal/lp_timer_hal.h b/components/hal/include/hal/lp_timer_hal.h similarity index 91% rename from components/hal/esp32c6/include/hal/lp_timer_hal.h rename to components/hal/include/hal/lp_timer_hal.h index 6acc565f51..b9e551c5dd 100644 --- a/components/hal/esp32c6/include/hal/lp_timer_hal.h +++ b/components/hal/include/hal/lp_timer_hal.h @@ -19,7 +19,7 @@ extern "C" { /* * @brief set alarm target value * - * @param timer_id timer num of lp_timer, 0 or 1 for esp32c6 + * @param timer_id timer num of lp_timer, 0 or 1 for esp32c6 and esp32h2 * * @param value when counter reaches alarm value, alarm event will be triggered */ @@ -27,7 +27,6 @@ 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); diff --git a/components/hal/esp32c6/lp_timer_hal.c b/components/hal/lp_timer_hal.c similarity index 100% rename from components/hal/esp32c6/lp_timer_hal.c rename to components/hal/lp_timer_hal.c From 117008143b19525b8a772248491730361afe1408 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Fri, 2 Jun 2023 14:19:01 +0800 Subject: [PATCH 14/19] bugfix: remove the workaround implemented in MR 22773 about the lp_timer --- .../bootloader_support/src/bootloader_random.c | 18 ++---------------- components/esp_hw_support/hw_random.c | 18 ++---------------- components/hal/CMakeLists.txt | 8 ++++---- 3 files changed, 8 insertions(+), 36 deletions(-) diff --git a/components/bootloader_support/src/bootloader_random.c b/components/bootloader_support/src/bootloader_random.c index 4bc121450e..33fecd77aa 100644 --- a/components/bootloader_support/src/bootloader_random.c +++ b/components/bootloader_support/src/bootloader_random.c @@ -8,7 +8,7 @@ #include "esp_cpu.h" #include "soc/wdev_reg.h" -#if defined CONFIG_IDF_TARGET_ESP32C6 +#if SOC_LP_TIMER_SUPPORTED #include "hal/lp_timer_hal.h" #endif @@ -34,20 +34,6 @@ #define RNG_CPU_WAIT_CYCLE_NUM (80 * 23) /* 45 KHz reading frequency is the maximum we have tested so far on S3 */ #endif -#if defined CONFIG_IDF_TARGET_ESP32H2 - -// TODO: temporary definition until IDF-6270 is implemented -#include "soc/lp_timer_reg.h" - -static inline uint32_t lp_timer_hal_get_cycle_count(void) -{ - REG_SET_BIT(LP_TIMER_UPDATE_REG, LP_TIMER_MAIN_TIMER_UPDATE); - - uint32_t lo = REG_GET_FIELD(LP_TIMER_MAIN_BUF0_LOW_REG, LP_TIMER_MAIN_TIMER_BUF0_LOW); - return lo; -} -#endif - __attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length) { uint8_t *buffer_bytes = (uint8_t *)buffer; @@ -57,7 +43,7 @@ static inline uint32_t lp_timer_hal_get_cycle_count(void) assert(buffer != NULL); for (size_t i = 0; i < length; i++) { -#if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2) +#if SOC_LP_TIMER_SUPPORTED random = REG_READ(WDEV_RND_REG); start = esp_cpu_get_cycle_count(); do { diff --git a/components/esp_hw_support/hw_random.c b/components/esp_hw_support/hw_random.c index fa83bfc0d9..046ff12dba 100644 --- a/components/esp_hw_support/hw_random.c +++ b/components/esp_hw_support/hw_random.c @@ -14,7 +14,7 @@ #include "soc/wdev_reg.h" #include "esp_private/esp_clk.h" -#if defined CONFIG_IDF_TARGET_ESP32C6 +#if SOC_LP_TIMER_SUPPORTED #include "hal/lp_timer_hal.h" #endif @@ -34,20 +34,6 @@ #define APB_CYCLE_WAIT_NUM (16) #endif -#if defined CONFIG_IDF_TARGET_ESP32H2 - -// TODO: temporary definition until IDF-6270 is implemented -#include "soc/lp_timer_reg.h" - -static uint32_t IRAM_ATTR lp_timer_hal_get_cycle_count(void) -{ - REG_SET_BIT(LP_TIMER_UPDATE_REG, LP_TIMER_MAIN_TIMER_UPDATE); - - uint32_t lo = REG_GET_FIELD(LP_TIMER_MAIN_BUF0_LOW_REG, LP_TIMER_MAIN_TIMER_BUF0_LOW); - return lo; -} -#endif - uint32_t IRAM_ATTR esp_random(void) { /* The PRNG which implements WDEV_RANDOM register gets 2 bits @@ -73,7 +59,7 @@ uint32_t IRAM_ATTR esp_random(void) static uint32_t last_ccount = 0; uint32_t ccount; uint32_t result = 0; -#if (defined CONFIG_IDF_TARGET_ESP32C6 || defined CONFIG_IDF_TARGET_ESP32H2) +#if SOC_LP_TIMER_SUPPORTED for (size_t i = 0; i < sizeof(result); i++) { do { ccount = esp_cpu_get_cycle_count(); diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 8ceb53b3aa..892a368377 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -30,6 +30,10 @@ if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) endif() endif() +if(CONFIG_SOC_LP_TIMER_SUPPORTED) + list(APPEND srcs "lp_timer_hal.c") +endif() + if(NOT BOOTLOADER_BUILD) list(APPEND srcs "rtc_io_hal.c" @@ -138,10 +142,6 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "${target}/modem_clock_hal.c") endif() - if(CONFIG_SOC_LP_TIMER_SUPPORTED) - list(APPEND srcs "lp_timer_hal.c") - endif() - if(CONFIG_SOC_PAU_SUPPORTED) list(APPEND srcs "${target}/pau_hal.c") endif() From a329b15e7ef40e1c86594641309a41d3598833ab Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Tue, 13 Jun 2023 11:10:26 +0800 Subject: [PATCH 15/19] Power Management: support pu xtal in light sleep for esp32h2 --- .../port/esp32c6/private_include/pmu_param.h | 124 +++++++++++ .../esp_hw_support/port/esp32h2/pmu_sleep.c | 13 ++ .../port/esp32h2/private_include/pmu_param.h | 197 ++++++++++++++---- components/hal/include/hal/pmu_types.h | 123 ----------- 4 files changed, 297 insertions(+), 160 deletions(-) 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 298fdf1b44..2608204a7a 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 @@ -62,6 +62,8 @@ typedef struct { 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; @@ -70,6 +72,128 @@ typedef struct { 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 : 21; + uint32_t vdd_spi_pd_en: 1; + uint32_t mem_dslp : 1; + uint32_t mem_pd_en : 4; + uint32_t wifi_pd_en : 1; + uint32_t reserved1 : 1; + uint32_t cpu_pd_en : 1; + uint32_t aon_pd_en : 1; + uint32_t top_pd_en : 1; + }; + struct { + uint32_t reserved2 : 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 reserved3 : 1; + }; + struct { + uint32_t reserved4 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_hp_power_t; + +typedef union { + struct { + uint32_t reserved0 : 30; + uint32_t mem_dslp : 1; + uint32_t peri_pd_en: 1; + }; + struct { + uint32_t reserved1 : 28; + uint32_t xpd_xtal32k: 1; + uint32_t xpd_rc32k : 1; + uint32_t xpd_fosc : 1; + uint32_t pd_osc : 1; + }; + struct { + uint32_t reserved2 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_lp_power_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1 : 16; + 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 reserved2: 8; + uint32_t drv_b : 24; + }; +} pmu_hp_analog_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1: 21; + uint32_t slp_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 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; +} 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; +} 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) diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index 117ff51adb..6e9c27324e 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -123,6 +123,18 @@ const pmu_sleep_config_t* pmu_sleep_config_default( analog_default.hp_sys.analog.xpd = 1; analog_default.hp_sys.analog.dbias = 2; } + if (!(pd_flags & PMU_SLEEP_PD_XTAL)){ + analog_default.hp_sys.analog.xpd_trx = 1; + analog_default.hp_sys.analog.xpd = 1; + analog_default.hp_sys.analog.dbias = 25; + analog_default.hp_sys.analog.pd_cur = 0; + analog_default.hp_sys.analog.bias_sleep = 0; + + analog_default.lp_sys[LP(SLEEP)].analog.xpd = 1; + analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = 0; + analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = 0; + analog_default.lp_sys[LP(SLEEP)].analog.dbias = 26; + } config->analog = analog_default; } return config; @@ -159,6 +171,7 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con 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_hp_set_trx_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd_trx); 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); 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 57bea2061c..22ca4216e4 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,129 @@ typedef struct { 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 : 21; + uint32_t vdd_spi_pd_en: 1; + uint32_t mem_dslp : 1; + uint32_t mem_pd_en : 4; + uint32_t wifi_pd_en : 1; + uint32_t reserved1 : 1; + uint32_t cpu_pd_en : 1; + uint32_t aon_pd_en : 1; + uint32_t top_pd_en : 1; + }; + struct { + uint32_t reserved2 : 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 reserved3 : 1; + }; + struct { + uint32_t reserved4 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_hp_power_t; + +typedef union { + struct { + uint32_t reserved0 : 30; + uint32_t mem_dslp : 1; + uint32_t peri_pd_en: 1; + }; + struct { + uint32_t reserved1 : 28; + uint32_t xpd_xtal32k: 1; + uint32_t xpd_rc32k : 1; + uint32_t xpd_fosc : 1; + uint32_t pd_osc : 1; + }; + struct { + uint32_t reserved2 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_lp_power_t; + +typedef struct { + struct { + uint32_t reserved0 : 24; + uint32_t xpd_trx : 1; + uint32_t xpd_bias : 1; + uint32_t reserved1 : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved2 : 16; + 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 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1: 21; + uint32_t slp_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 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; +} 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; +} 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) @@ -168,49 +291,49 @@ 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, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .slp_mem_xpd = 0, \ - .slp_logic_xpd = 0, \ - .slp_mem_dbias = 0, \ - .slp_logic_dbias = 0, \ - .xpd = 1, \ - .dbias = 0, \ - .drv_b = 0xFFFFF8 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_ACTIVE] = { \ - .analog = { \ - .slp_xpd = 0, \ - .slp_dbias = 0x0, \ - .xpd = 1, \ - .dbias = 0xe, \ - .drv_b = 0x0 \ - } \ - }, \ - .lp_sys[PMU_MODE_LP_SLEEP] = { \ - .analog = { \ - .xpd_bias = 0, \ - .pd_cur = 1, \ - .bias_sleep = 1, \ - .xpd = 0, \ - .dbias = 0, \ - .slp_xpd = 1, \ - .slp_dbias = 0x5, \ - .drv_b = 0x7 \ - } \ - } \ +#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .xpd_trx = 0, \ + .xpd_bias = 0x0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .slp_mem_dbias = 0, \ + .slp_logic_dbias = 0, \ + .xpd = 1, \ + .dbias = 0, \ + .drv_b = 0xFFFFF8 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .analog = { \ + .slp_xpd = 0, \ + .slp_dbias = 0x0, \ + .xpd = 1, \ + .dbias = 0xe, \ + .drv_b = 0x0 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .xpd_bias = 0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .xpd = 0, \ + .dbias = 0, \ + .slp_xpd = 1, \ + .slp_dbias = 0x5, \ + .drv_b = 0x7 \ + } \ + } \ } #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, \ diff --git a/components/hal/include/hal/pmu_types.h b/components/hal/include/hal/pmu_types.h index 5c4c44e81f..cd21975232 100644 --- a/components/hal/include/hal/pmu_types.h +++ b/components/hal/include/hal/pmu_types.h @@ -42,129 +42,6 @@ typedef enum { PMU_HP_PD_WIFI = 4, /*!< Power domain of WIFI */ } pmu_hp_power_domain_t; - -/* Software configuration instance type from pmu_struct.h */ -typedef union { - struct { - uint32_t reserved0 : 21; - uint32_t vdd_spi_pd_en: 1; - uint32_t mem_dslp : 1; - uint32_t mem_pd_en : 4; - uint32_t wifi_pd_en : 1; - uint32_t reserved1 : 1; - uint32_t cpu_pd_en : 1; - uint32_t aon_pd_en : 1; - uint32_t top_pd_en : 1; - }; - struct { - uint32_t reserved2 : 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 reserved3 : 1; - }; - struct { - uint32_t reserved4 : 31; - uint32_t xpd_xtal : 1; - }; - uint32_t val; -} pmu_hp_power_t; - -typedef union { - struct { - uint32_t reserved0 : 30; - uint32_t mem_dslp : 1; - uint32_t peri_pd_en: 1; - }; - struct { - uint32_t reserved1 : 28; - uint32_t xpd_xtal32k: 1; - uint32_t xpd_rc32k : 1; - uint32_t xpd_fosc : 1; - uint32_t pd_osc : 1; - }; - struct { - uint32_t reserved2 : 31; - uint32_t xpd_xtal : 1; - }; - uint32_t val; -} pmu_lp_power_t; - -typedef struct { - struct { - uint32_t reserved0 : 25; - uint32_t xpd_bias : 1; - uint32_t dbg_atten : 4; - uint32_t pd_cur : 1; - uint32_t bias_sleep: 1; - }; - struct { - uint32_t reserved1 : 16; - 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 reserved2: 8; - uint32_t drv_b : 24; - }; -} pmu_hp_analog_t; - -typedef struct { - struct { - uint32_t reserved0 : 25; - uint32_t xpd_bias : 1; - uint32_t dbg_atten : 4; - uint32_t pd_cur : 1; - uint32_t bias_sleep: 1; - }; - struct { - uint32_t reserved1: 21; - uint32_t slp_xpd : 1; - uint32_t xpd : 1; - uint32_t slp_dbias: 4; - uint32_t dbias : 5; - }; - struct { - uint32_t reserved2: 28; - uint32_t drv_b : 4; - }; -} 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; - 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; -} 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; -} 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; - #ifdef __cplusplus } #endif From 6ee0f89676f47ae2f5cd8de6098c6ac27550ef6d Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Tue, 13 Jun 2023 11:13:24 +0800 Subject: [PATCH 16/19] Power Management: fix hp xtal wait bug for esp32h2 and esp32c6 --- components/esp_hw_support/port/esp32c6/pmu_sleep.c | 4 ++-- components/esp_hw_support/port/esp32h2/pmu_sleep.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index 17b631c781..07f96f4803 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -126,9 +126,9 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default( 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); + } else { + param->hp_lp.xtal_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_us, fastclk_period); } return param; } diff --git a/components/esp_hw_support/port/esp32h2/pmu_sleep.c b/components/esp_hw_support/port/esp32h2/pmu_sleep.c index 6e9c27324e..30ef282da7 100644 --- a/components/esp_hw_support/port/esp32h2/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h2/pmu_sleep.c @@ -83,9 +83,9 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default( 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); + } else { + param->hp_lp.xtal_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_us, fastclk_period); } return param; } From d585861d228ac408a7e3ed3a7428c9616dd139a0 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Mon, 26 Jun 2023 11:09:16 +0800 Subject: [PATCH 17/19] TODO: IDF-7555 --- components/esp_phy/src/btbb_init.c | 14 +++++++------- components/esp_pm/test_apps/esp_pm/main/test_pm.c | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/components/esp_phy/src/btbb_init.c b/components/esp_phy/src/btbb_init.c index efe7b19013..1853f9dcb6 100644 --- a/components/esp_phy/src/btbb_init.c +++ b/components/esp_phy/src/btbb_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,7 +17,7 @@ static _lock_t s_btbb_access_lock; static uint8_t s_btbb_access_ref = 0; -#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE && !CONFIG_IDF_TARGET_ESP32H2 #include "esp_private/sleep_retention.h" #include "btbb_retention_reg.h" static const char* TAG = "btbb_init"; @@ -45,7 +45,7 @@ static void btbb_sleep_retention_deinit(void) { sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_BB); } -#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE && !CONFIG_IDF_TARGET_ESP32H2 void esp_btbb_enable(void) @@ -53,9 +53,9 @@ void esp_btbb_enable(void) _lock_acquire(&s_btbb_access_lock); if (s_btbb_access_ref == 0) { bt_bb_v2_init_cmplx(BTBB_ENABLE_VERSION_PRINT); -#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE && !CONFIG_IDF_TARGET_ESP32H2 btbb_sleep_retention_init(); -#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE && !CONFIG_IDF_TARGET_ESP32H2 } s_btbb_access_ref++; _lock_release(&s_btbb_access_lock); @@ -65,9 +65,9 @@ void esp_btbb_disable(void) { _lock_acquire(&s_btbb_access_lock); if (s_btbb_access_ref && (--s_btbb_access_ref == 0)) { -#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE && !CONFIG_IDF_TARGET_ESP32H2 btbb_sleep_retention_deinit(); -#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // SOC_PM_MODEM_RETENTION_BY_REGDMA && CONFIG_FREERTOS_USE_TICKLESS_IDLE && !CONFIG_IDF_TARGET_ESP32H2 } _lock_release(&s_btbb_access_lock); } diff --git a/components/esp_pm/test_apps/esp_pm/main/test_pm.c b/components/esp_pm/test_apps/esp_pm/main/test_pm.c index 5245c7527a..d3bc4ea1c7 100644 --- a/components/esp_pm/test_apps/esp_pm/main/test_pm.c +++ b/components/esp_pm/test_apps/esp_pm/main/test_pm.c @@ -111,6 +111,7 @@ static void light_sleep_disable(void) ESP_ERROR_CHECK( esp_pm_configure(&pm_config) ); } +#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2-TODO: IDF-7555 TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]") { gptimer_handle_t gptimer = NULL; @@ -165,6 +166,7 @@ TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]") TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); } +#endif #if CONFIG_ULP_COPROC_TYPE_FSM #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) From 5c608f0f50a93fe2b40dae9c162f110a8256a9c1 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Tue, 27 Jun 2023 16:31:56 +0800 Subject: [PATCH 18/19] TODO: IDF-7657 --- components/esp_pm/.build-test-rules.yml | 7 +++++++ components/esp_pm/test_apps/esp_pm/README.md | 4 ++-- components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py | 13 +++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 components/esp_pm/.build-test-rules.yml diff --git a/components/esp_pm/.build-test-rules.yml b/components/esp_pm/.build-test-rules.yml new file mode 100644 index 0000000000..421533b5af --- /dev/null +++ b/components/esp_pm/.build-test-rules.yml @@ -0,0 +1,7 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/esp_pm/test_apps/esp_pm: + disable: + - if: IDF_TARGET in ["esp32h2"] + temporary: true + reason: Not supported yet diff --git a/components/esp_pm/test_apps/esp_pm/README.md b/components/esp_pm/test_apps/esp_pm/README.md index a8b7833fa3..7e7523ec85 100644 --- a/components/esp_pm/test_apps/esp_pm/README.md +++ b/components/esp_pm/test_apps/esp_pm/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py index 3e6d410793..cd13ea0edd 100644 --- a/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py +++ b/components/esp_pm/test_apps/esp_pm/pytest_esp_pm.py @@ -4,13 +4,14 @@ import pytest from pytest_embedded import Dut +CONFIGS = [ + pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='TODO: IDF-7657')]), + pytest.param('limits', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='TODO: IDF-7657')]), + pytest.param('options', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='TODO: IDF-7657')]), +] + @pytest.mark.generic -@pytest.mark.supported_targets -@pytest.mark.parametrize('config', [ - 'default', - 'limits', - 'options', -], indirect=True) +@pytest.mark.parametrize('config', CONFIGS, indirect=True) def test_esp_pm(dut: Dut) -> None: dut.run_all_single_board_cases() From c7c937ea75a0c4e741bd730e5f4d77f349b6b541 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Tue, 27 Jun 2023 17:31:38 +0800 Subject: [PATCH 19/19] bugfix: set FORCE_INLINE_ATTR for resume_uart --- components/hal/esp32h2/include/hal/uart_ll.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index 677f4df75e..8609f21b30 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -16,6 +16,7 @@ #include "soc/uart_reg.h" #include "soc/uart_struct.h" #include "soc/pcr_struct.h" +#include "esp_attr.h" #ifdef __cplusplus extern "C" { @@ -85,7 +86,7 @@ typedef enum { * * @return None. */ -static inline void uart_ll_update(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) { hw->reg_update.reg_update = 1; while (hw->reg_update.reg_update); @@ -1052,7 +1053,7 @@ static inline void uart_ll_force_xoff(uart_port_t uart_num) * * @return None. */ -static inline void uart_ll_force_xon(uart_port_t uart_num) +FORCE_INLINE_ATTR void uart_ll_force_xon(uart_port_t uart_num) { REG_CLR_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XOFF); REG_SET_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XON);