diff --git a/components/esp_hw_support/include/esp_private/sleep_cpu.h b/components/esp_hw_support/include/esp_private/sleep_cpu.h index 136c034103..cc2dd35980 100644 --- a/components/esp_hw_support/include/esp_private/sleep_cpu.h +++ b/components/esp_hw_support/include/esp_private/sleep_cpu.h @@ -9,6 +9,7 @@ #include #include "sdkconfig.h" #include "esp_err.h" +#include "esp_sleep.h" #include "soc/soc_caps.h" #ifdef __cplusplus @@ -21,7 +22,7 @@ extern "C" { * This file contains declarations of cpu retention related functions in light sleep mode. */ -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || SOC_PM_SUPPORT_CPU_PD +#if ESP_SLEEP_POWER_DOWN_CPU || SOC_PM_SUPPORT_CPU_PD /** * @brief Whether to allow the cpu power domain to be powered off. * @@ -31,7 +32,7 @@ extern "C" { bool cpu_domain_pd_allowed(void); #endif -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU /** * @brief Configure the parameters of the CPU domain during the sleep process * @@ -64,9 +65,9 @@ void sleep_disable_cpu_retention(void); esp_err_t esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool), uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp); #endif // SOC_PM_CPU_RETENTION_BY_SW -#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#endif // ESP_SLEEP_POWER_DOWN_CPU -#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU /** * Do sleep prepare for other smp cores */ @@ -77,13 +78,11 @@ void sleep_smp_cpu_sleep_prepare(void); */ void sleep_smp_cpu_wakeup_prepare(void); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP /** * Notify the other core that this sleep does not require retention. */ void esp_sleep_cpu_skip_retention(void); -#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP -#endif // !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#endif // !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU #ifdef __cplusplus } diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 018820e364..61579a8e4a 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -133,6 +133,8 @@ enum { ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION = ESP_ERR_INVALID_ARG, }; +#define ESP_SLEEP_POWER_DOWN_CPU (CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || (SOC_CPU_IN_TOP_DOMAIN && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)) + /** * @brief Disable wakeup source * @@ -713,7 +715,7 @@ void esp_default_wake_deep_sleep(void); */ void esp_deep_sleep_disable_rom_logging(void); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU #if SOC_PM_CPU_RETENTION_BY_RTCCNTL /** @@ -752,7 +754,7 @@ esp_err_t esp_sleep_cpu_retention_init(void); * Release system retention memory. */ esp_err_t esp_sleep_cpu_retention_deinit(void); -#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#endif // ESP_SLEEP_POWER_DOWN_CPU /** * @brief Configure to isolate all GPIO pins in sleep state diff --git a/components/esp_hw_support/lowpower/CMakeLists.txt b/components/esp_hw_support/lowpower/CMakeLists.txt index 6727506080..3ba4d4d6a8 100644 --- a/components/esp_hw_support/lowpower/CMakeLists.txt +++ b/components/esp_hw_support/lowpower/CMakeLists.txt @@ -4,7 +4,8 @@ endif() set(srcs) -if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP) +if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP OR + (CONFIG_SOC_CPU_IN_TOP_DOMAIN AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)) list(APPEND srcs "cpu_retention/port/${target}/sleep_cpu.c") if(CONFIG_SOC_PM_CPU_RETENTION_BY_SW) list(APPEND srcs "cpu_retention/port/${target}/sleep_cpu_asm.S") diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c index 4547bd1f9e..9fdd1d3a76 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c3/sleep_cpu.c @@ -102,7 +102,7 @@ bool cpu_domain_pd_allowed(void) esp_err_t sleep_cpu_configure(bool light_sleep_enable) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU if (light_sleep_enable) { ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep."); } else { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c index d12d2d47f8..fbb67fd089 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c5/sleep_cpu.c @@ -489,7 +489,7 @@ bool cpu_domain_pd_allowed(void) esp_err_t sleep_cpu_configure(bool light_sleep_enable) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU if (light_sleep_enable) { ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep."); } else { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c index 87642de1d7..e97de1c0eb 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32c6/sleep_cpu.c @@ -532,7 +532,7 @@ bool cpu_domain_pd_allowed(void) esp_err_t sleep_cpu_configure(bool light_sleep_enable) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU if (light_sleep_enable) { ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep."); } else { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c index 3734807b88..b30913b233 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32h2/sleep_cpu.c @@ -532,7 +532,7 @@ bool cpu_domain_pd_allowed(void) esp_err_t sleep_cpu_configure(bool light_sleep_enable) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU if (light_sleep_enable) { ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep."); } else { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c index f27af1d5dc..e7ea617a9d 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu.c @@ -41,7 +41,7 @@ #endif -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE #include #include "soc/hp_system_reg.h" typedef enum { @@ -81,7 +81,7 @@ typedef struct { } retent; } sleep_cpu_retention_t; -static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; +static TCM_DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS]; @@ -162,7 +162,7 @@ static esp_err_t esp_sleep_cpu_retention_init_impl(void) s_cpu_retention.retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; } } -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { atomic_init(&s_smp_retention_state[core_id], SMP_IDLE); } @@ -209,7 +209,7 @@ FORCE_INLINE_ATTR void restore_mstatus(uint32_t mstatus_val) RV_WRITE_CSR(mstatus, mstatus_val); } -static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void) +static TCM_IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void) { RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()]; @@ -277,7 +277,7 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi return frame; } -static IRAM_ATTR void rv_core_noncritical_regs_restore(void) +static TCM_IRAM_ATTR void rv_core_noncritical_regs_restore(void) { RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()]; @@ -343,7 +343,7 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(void) RV_WRITE_CSR(mcycle, frame->mcycle); } -static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame) +static TCM_IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame) { assert(frame); cpu_domain_dev_regs_region_t *region = frame->region; @@ -357,7 +357,7 @@ static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *fra } } -static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame) +static TCM_IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame) { assert(frame); cpu_domain_dev_regs_region_t *region = frame->region; @@ -372,12 +372,12 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t * } #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME -static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) +static TCM_IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { *(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size); } -static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) +static TCM_IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr) { if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ // resume uarts @@ -399,7 +399,7 @@ extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void); extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void); typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool); -static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, +static TCM_IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) { uint8_t core_id = esp_cpu_get_core_id(); @@ -410,11 +410,11 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0); #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME /* Minus 2 * sizeof(long) is for bypass `pmufunc` and `frame_crc` field */ - update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc)); + update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc)); #endif REG_WRITE(RTC_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_DONE); while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_BACKUP_DONE) { ; @@ -425,20 +425,20 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, } #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME else { - validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc)); + validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc)); } #endif return pmu_sleep_finish(); } -esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool), +esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool), uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) { esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0); uint32_t mstatus = save_mstatus_and_disable_global_int(); uint8_t core_id = esp_cpu_get_core_id(); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START); #endif cpu_domain_dev_regs_save(s_cpu_retention.retent.clic_frame[core_id]); @@ -457,7 +457,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin validate_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc)); #endif -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE // Start core1 if (core_id == 0) { REG_SET_BIT(HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_CPU_CLK_EN); @@ -472,7 +472,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]); restore_mstatus(mstatus); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE); #endif return err; @@ -504,7 +504,7 @@ bool cpu_domain_pd_allowed(void) esp_err_t sleep_cpu_configure(bool light_sleep_enable) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU if (light_sleep_enable) { ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep."); } else { @@ -515,7 +515,7 @@ esp_err_t sleep_cpu_configure(bool light_sleep_enable) } #if !CONFIG_FREERTOS_UNICORE -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU static TCM_IRAM_ATTR void smp_core_do_retention(void) { uint8_t core_id = esp_cpu_get_core_id(); @@ -572,14 +572,14 @@ static TCM_IRAM_ATTR void smp_core_do_retention(void) } -IRAM_ATTR void esp_sleep_cpu_skip_retention(void) { +TCM_IRAM_ATTR void esp_sleep_cpu_skip_retention(void) { atomic_store(&s_smp_retention_state[esp_cpu_get_core_id()], SMP_SKIP_RETENTION); } #endif void sleep_smp_cpu_sleep_prepare(void) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU while (atomic_load(&s_smp_retention_state[!esp_cpu_get_core_id()]) != SMP_IDLE) { ; } @@ -591,7 +591,7 @@ void sleep_smp_cpu_sleep_prepare(void) void sleep_smp_cpu_wakeup_prepare(void) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU uint8_t core_id = esp_cpu_get_core_id(); if (atomic_load(&s_smp_retention_state[core_id]) == SMP_RESTORE_DONE) { while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_RESTORE_DONE) { diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu_asm.S b/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu_asm.S index ed46453f31..046ef61777 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu_asm.S +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32p4/sleep_cpu_asm.S @@ -117,28 +117,6 @@ rv_core_critical_regs_save: mv t3, t0 csrr t0, mscratch sw t0, RV_SLP_CTX_T0(t3) - - /* writeback dcache is required here!!! */ - la t0, CACHE_SYNC_MAP_REG - li t1, 0x10 /* map l1 dcache */ - sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */ - la t2, CACHE_SYNC_ADDR_REG - sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */ - la t0, CACHE_SYNC_SIZE_REG - sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */ - - la t1, CACHE_SYNC_CTRL_REG - lw t2, 0x0(t1) - ori t2, t2, 0x4 - sw t2, 0x0(t1) - - li t0, 0x10 /* SYNC_DONE bit */ -wait_sync_done: - lw t2, 0x0(t1) - and t2, t0, t2 - beqz t2, wait_sync_done - - lw t0, RV_SLP_CTX_T0(t3) lw t1, RV_SLP_CTX_T1(t3) lw t2, RV_SLP_CTX_T2(t3) lw t3, RV_SLP_CTX_T3(t3) diff --git a/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c b/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c index cc0f11b378..2e16de3c67 100644 --- a/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/cpu_retention/port/esp32s3/sleep_cpu.c @@ -232,7 +232,7 @@ bool cpu_domain_pd_allowed(void) esp_err_t sleep_cpu_configure(bool light_sleep_enable) { -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU if (light_sleep_enable) { ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep."); } else { diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index ca93907ae5..a2a55cf83b 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -12,11 +12,13 @@ #include "esp_err.h" #include "esp_attr.h" #include "esp_private/regi2c_ctrl.h" +#include "esp32p4/rom/cache.h" #include "soc/chip_revision.h" #include "soc/soc.h" #include "soc/regi2c_syspll.h" #include "soc/regi2c_cpll.h" #include "soc/rtc.h" +#include "soc/cache_reg.h" #include "soc/pau_reg.h" #include "soc/pmu_reg.h" #include "soc/pmu_struct.h" @@ -285,6 +287,11 @@ void pmu_sleep_shutdown_ldo(void) { CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD); } +FORCE_INLINE_ATTR void sleep_writeback_l1_dcache(void) { + Cache_WriteBack_All(CACHE_MAP_L1_DCACHE); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); +} + TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) { lp_aon_hal_inform_wakeup_type(dslp); @@ -297,6 +304,8 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev); pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev); + sleep_writeback_l1_dcache(); + /* Start entry into sleep mode */ pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev); diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index c049ae73ac..59d6cb22a8 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -878,7 +878,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m if (should_skip_sleep) { result = ESP_ERR_SLEEP_REJECT; -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE && SOC_PM_CPU_RETENTION_BY_SW +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE && SOC_PM_CPU_RETENTION_BY_SW esp_sleep_cpu_skip_retention(); #endif } else { @@ -942,14 +942,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m #endif #if SOC_PMU_SUPPORTED -#if SOC_PM_CPU_RETENTION_BY_SW && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0); if (pd_flags & (PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_TOP)) { 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 { -#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW +#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW // Skip smp retention if CPU power domain power-down is not allowed esp_sleep_cpu_skip_retention(); #endif @@ -1256,7 +1256,7 @@ esp_err_t esp_light_sleep_start(void) #endif #if !CONFIG_FREERTOS_UNICORE -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW +#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW sleep_smp_cpu_sleep_prepare(); #else esp_ipc_isr_stall_other_cpu(); @@ -1374,7 +1374,7 @@ esp_err_t esp_light_sleep_start(void) // Enter sleep, then wait for flash to be ready on wakeup err = esp_light_sleep_inner(pd_flags, flash_enable_time_us); } -#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW +#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW if (err != ESP_OK) { esp_sleep_cpu_skip_retention(); } @@ -1412,7 +1412,7 @@ esp_err_t esp_light_sleep_start(void) #if !CONFIG_FREERTOS_UNICORE esp_ipc_isr_stall_resume(); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW +#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW sleep_smp_cpu_wakeup_prepare(); #else esp_ipc_isr_release_other_cpu(); @@ -2063,7 +2063,7 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_ #if SOC_PM_SUPPORT_TOP_PD FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) { bool top_pd_allowed = true; -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU top_pd_allowed &= cpu_domain_pd_allowed(); #else top_pd_allowed = false; @@ -2179,7 +2179,7 @@ static uint32_t get_power_down_flags(void) } #endif -#if SOC_PM_SUPPORT_CPU_PD +#if SOC_PM_SUPPORT_CPU_PD && ESP_SLEEP_POWER_DOWN_CPU if ((s_config.domain[ESP_PD_DOMAIN_CPU].pd_option != ESP_PD_OPTION_ON) && cpu_domain_pd_allowed()) { pd_flags |= RTC_SLEEP_PD_CPU; } diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 3058381fbd..ab24e4b5bd 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -84,7 +84,8 @@ menu "Power Management" config PM_CHECK_SLEEP_RETENTION_FRAME bool - depends on PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP + depends on (PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || \ + (SOC_CPU_IN_TOP_DOMAIN && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)) default y if IDF_CI_BUILD default n help @@ -142,7 +143,7 @@ menu "Power Management" config PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP bool "Power down Digital Peripheral in light sleep (EXPERIMENTAL)" depends on SOC_PM_SUPPORT_TOP_PD - select PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP + select PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP if !SOC_CPU_IN_TOP_DOMAIN default n #TODO: enable by default if periph init/deinit management supported (WIFI-5252) help If enabled, digital peripherals will be powered down in light sleep, it will reduce sleep diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index d4be371ce4..8216d8a860 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -29,7 +29,7 @@ entries: sleep_gpio:gpio_sleep_mode_config_apply (noflash) if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y && (PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y || SOC_PM_SUPPORT_TAGMEM_PD = y): sleep_cpu:sleep_enable_cpu_retention (noflash) - if PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: + if PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y || (SOC_CPU_IN_TOP_DOMAIN = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP = y): sleep_cpu:cpu_domain_pd_allowed (noflash) if SOC_PM_SUPPORT_TOP_PD = y: sleep_clock:clock_domain_pd_allowed (noflash) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 3159ba3703..37d76df5d1 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -372,7 +372,7 @@ static esp_err_t esp_pm_sleep_configure(const void *vconfig) esp_err_t err = ESP_OK; const esp_pm_config_t* config = (const esp_pm_config_t*) vconfig; -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU err = sleep_cpu_configure(config->light_sleep_enable); if (err != ESP_OK) { return err; diff --git a/components/esp_pm/test_apps/.build-test-rules.yml b/components/esp_pm/test_apps/.build-test-rules.yml index 8aece557bd..67cf500b6c 100644 --- a/components/esp_pm/test_apps/.build-test-rules.yml +++ b/components/esp_pm/test_apps/.build-test-rules.yml @@ -4,6 +4,7 @@ components/esp_pm/test_apps: enable: - if: INCLUDE_DEFAULT == 1 disable: + - if: CONFIG_NAME == "pm_pd_top_sleep" and IDF_TARGET not in ["esp32c6", "esp32h2", "esp32p4"] - if: IDF_TARGET == "esp32c5" temporary: true reason: not support yet # TODO: [ESP32C5] IDF-8643 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 9d7ff9eaff..a2c2fc0f76 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 @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut @@ -42,3 +42,18 @@ def test_esp_attr_xip_psram_esp32s2(dut: Dut) -> None: ) def test_esp_attr_xip_psram_esp32s3(dut: Dut) -> None: dut.run_all_single_board_cases() + + +# power down CPU and TOP domain in auto-lightsleep +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.esp32p4 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'pm_pd_top_sleep' + ], +) +def test_esp_pd_top_and_cpu_sleep(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_pd_top_sleep b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_pd_top_sleep new file mode 100644 index 0000000000..5658858b85 --- /dev/null +++ b/components/esp_pm/test_apps/esp_pm/sdkconfig.ci.pm_pd_top_sleep @@ -0,0 +1 @@ +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index b7f9780319..c8822246f2 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1495,6 +1495,10 @@ config SOC_PAU_IN_TOP_DOMAIN bool default y +config SOC_CPU_IN_TOP_DOMAIN + bool + default y + config SOC_PSRAM_VDD_POWER_MPLL bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 0ac8915371..8d3fece9ed 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -603,6 +603,7 @@ #define SOC_PM_PAU_LINK_NUM (4) #define SOC_PAU_IN_TOP_DOMAIN (1) +#define SOC_CPU_IN_TOP_DOMAIN (1) /*-------------------------- PSRAM CAPS ----------------------------*/ #define SOC_PSRAM_VDD_POWER_MPLL (1)