From cfecbc99ce45749b5a74fddefcf244dbfdfee3e4 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Fri, 29 Aug 2025 11:09:24 +0800 Subject: [PATCH] change(esp_hw_support): update sleep cpu flow --- .../lowpower/port/esp32c5/sleep_cpu_static.c | 8 +- .../lowpower/port/esp32h4/rvsleep-frames.h | 2 - .../lowpower/port/esp32h4/sleep_cpu.c | 277 +++--------------- .../lowpower/port/esp32h4/sleep_cpu_asm.S | 46 +-- .../lowpower/port/esp32h4/sleep_cpu_dynamic.c | 199 +++++++++++++ .../port/esp32h4/sleep_cpu_retention.h | 59 ++++ .../lowpower/port/esp32h4/sleep_cpu_static.c | 237 +++++++++++++++ .../soc/esp32h4/register/soc/cache_reg.h | 1 - 8 files changed, 544 insertions(+), 285 deletions(-) create mode 100644 components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_dynamic.c create mode 100644 components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_retention.h create mode 100644 components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_static.c diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_static.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_static.c index fa3f5c4cb3..e78b6335d0 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_static.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_static.c @@ -97,10 +97,10 @@ static void * cache_sleep_frame_init(void) static void * clint_sleep_frame_init(void) { const static cpu_domain_dev_regs_region_t regions[] = { - { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_SIP_REG + 4 }, - { .start = CLINT_MINT_MTIMECMP_L_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 }, - { .start = CLINT_MINT_TIMECTL_REG, .end = CLINT_MINT_TIMECTL_REG + 4 }, - { .start = CLINT_MINT_MTIME_L_REG, .end = CLINT_MINT_MTIME_H_REG + 4 } + { .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 }, + { .start = CPU_DOMAIN_DEV_START_ADDR1, .end = CPU_DOMAIN_DEV_END_ADDR1 }, + { .start = CPU_DOMAIN_DEV_START_ADDR2, .end = CPU_DOMAIN_DEV_END_ADDR2 }, + { .start = CPU_DOMAIN_DEV_START_ADDR3, .end = CPU_DOMAIN_DEV_END_ADDR3 } }; static uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(4)] __attribute__((aligned(4))); return cpu_domain_dev_sleep_frame_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame); diff --git a/components/esp_hw_support/lowpower/port/esp32h4/rvsleep-frames.h b/components/esp_hw_support/lowpower/port/esp32h4/rvsleep-frames.h index e7521996e0..95cffbef85 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/rvsleep-frames.h +++ b/components/esp_hw_support/lowpower/port/esp32h4/rvsleep-frames.h @@ -162,7 +162,6 @@ STRUCT_BEGIN STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2) STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3) -#if SOC_CPU_HAS_PMA STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR0, pmaaddr0) STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR1, pmaaddr1) STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR2, pmaaddr2) @@ -195,7 +194,6 @@ STRUCT_BEGIN STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG13, pmacfg13) STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG14, pmacfg14) STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG15, pmacfg15) -#endif // SOC_CPU_HAS_PMA STRUCT_FIELD (long, 4, RV_SLP_CTX_MCYCLE, mcycle) STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVT, mtvt) diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu.c index 0801d8e84e..6cfb020a7d 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu.c @@ -12,86 +12,44 @@ #include "esp_attr.h" #include "esp_check.h" +#include "esp_ipc_isr.h" #include "esp_sleep.h" #include "esp_log.h" -#include "esp_crc.h" +#include "esp_rom_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_heap_caps.h" +#include "riscv/csr.h" #include "soc/soc_caps.h" +#include "soc/intpri_reg.h" +#include "soc/cache_reg.h" +#include "soc/clint_reg.h" +#include "soc/clic_reg.h" +#include "soc/pcr_reg.h" +#include "soc/rtc_periph.h" +#include "esp_private/esp_pmu.h" #include "esp_private/sleep_cpu.h" #include "esp_private/sleep_event.h" #include "sdkconfig.h" -#if SOC_PMU_SUPPORTED -#include "esp_private/esp_pmu.h" -#else -#include "hal/rtc_hal.h" -#endif +#include "esp32h4/rom/rtc.h" +#include "esp32h4/rom/cache.h" +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME #include "esp_private/system_internal.h" -#include "hal/clk_gate_ll.h" #include "hal/uart_hal.h" #endif -#include "soc/rtc_periph.h" - -#include "esp32h4/rom/rtc.h" -#include "rvsleep-frames.h" -#include "soc/intpri_reg.h" -#include "soc/cache_reg.h" -#include "soc/clint_reg.h" -#include "esp32h4/rom/cache.h" -#include "esp_ipc_isr.h" -#include "soc/pcr_reg.h" - -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE -#include -#include "soc/hp_system_reg.h" -typedef enum { - SMP_IDLE, - SMP_BACKUP_START, - SMP_BACKUP_DONE, - SMP_RESTORE_START, - SMP_RESTORE_DONE, - SMP_SKIP_RETENTION, -} smp_retention_state_t; - +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE static DRAM_ATTR smp_retention_state_t s_smp_retention_state[portNUM_PROCESSORS]; #endif static __attribute__((unused)) const char *TAG = "sleep"; -typedef struct { - uint32_t start; - uint32_t end; -} cpu_domain_dev_regs_region_t; - -typedef struct { - cpu_domain_dev_regs_region_t *region; - int region_num; - uint32_t *regs_frame; -} cpu_domain_dev_sleep_frame_t; - -/** - * Internal structure which holds all requested light sleep cpu retention parameters - */ -typedef struct { - struct { - RvCoreCriticalSleepFrame *critical_frame[portNUM_PROCESSORS]; - RvCoreNonCriticalSleepFrame *non_critical_frame[portNUM_PROCESSORS]; - cpu_domain_dev_sleep_frame_t *cache_config_frame; - cpu_domain_dev_sleep_frame_t *clint_frame[portNUM_PROCESSORS]; - cpu_domain_dev_sleep_frame_t *clic_frame[portNUM_PROCESSORS]; - } retent; -} sleep_cpu_retention_t; - static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; - -#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW - #define CUSTOM_CSR_MTVT (0x307) #define CUSTOM_CSR_MNXTI (0x345) #define CUSTOM_CSR_MINTTHRESH (0x347) @@ -107,155 +65,14 @@ static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS]; -static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num) +FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void) { - const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num; - int regs_frame_sz = 0; - for (int num = 0; num < region_num; num++) { - regs_frame_sz += regions[num].end - regions[num].start; - } - void *frame = heap_caps_malloc(sizeof(cpu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); - if (frame) { - cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t)); - memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t)); - void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz; - memset(regs_frame, 0, regs_frame_sz); - *(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) { - .region = region, - .region_num = region_num, - .regs_frame = (uint32_t *)regs_frame - }; - } - return frame; + return RV_READ_MSTATUS_AND_DISABLE_INTR(); } -static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) +FORCE_INLINE_ATTR void restore_mstatus(uint32_t mstatus_val) { - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = CACHE_L1_ICACHE_CTRL_REG, .end = CACHE_L1_DCACHE_CTRL_REG + 4 }, - { .start = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(uint8_t core_id) -{ - const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][3] = { - [0 ... portNUM_PROCESSORS - 1] = { - { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_SIP_REG + 4 }, - { .start = CLINT_MINT_MTIMECMP_L_REG, .end = CLINT_MINT_TIMECTL_REG + 4 }, - { .start = CLINT_MINT_MTIME_L_REG, .end = CLINT_MINT_MTIME_H_REG + 4 }, - } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(cpu_domain_dev_regs_region_t)); -} - -static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id) -{ - const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][4] = { - [0 ... portNUM_PROCESSORS - 1] = { - { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, - { .start = CLIC_INT_CTRL_REG(3), .end = CLIC_INT_CTRL_REG(3) + 4 }, - { .start = CLIC_INT_CTRL_REG(7), .end = CLIC_INT_CTRL_REG(7) + 4 }, - { .start = CLIC_INT_CTRL_REG(16), .end = CLIC_INT_CTRL_REG(47) + 4 }, - } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(cpu_domain_dev_regs_region_t)); -} - -static esp_err_t esp_sleep_cpu_retention_init_impl(void) -{ - for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { - if (s_cpu_retention.retent.critical_frame[core_id] == NULL) { - void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame; - rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.non_critical_frame[core_id] == NULL) { - void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.clic_frame[core_id] == NULL) { - void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; - } - if (s_cpu_retention.retent.clint_frame[core_id] == NULL) { - void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; - } - } - if (s_cpu_retention.retent.cache_config_frame == NULL) { - void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !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); - } -#endif - return ESP_OK; -err: - esp_sleep_cpu_retention_deinit(); - return ESP_ERR_NO_MEM; -} - -static esp_err_t esp_sleep_cpu_retention_deinit_impl(void) -{ - for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { - if (s_cpu_retention.retent.critical_frame[core_id]) { - heap_caps_free((void *)s_cpu_retention.retent.critical_frame[core_id]); - s_cpu_retention.retent.critical_frame[core_id] = NULL; - rv_core_critical_regs_frame[core_id] = NULL; - } - if (s_cpu_retention.retent.non_critical_frame[core_id]) { - heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame[core_id]); - s_cpu_retention.retent.non_critical_frame[core_id] = NULL; - } - if (s_cpu_retention.retent.clic_frame[core_id]) { - heap_caps_free((void *)s_cpu_retention.retent.clic_frame[core_id]); - s_cpu_retention.retent.clic_frame[core_id] = NULL; - } - if (s_cpu_retention.retent.clint_frame[core_id]) { - heap_caps_free((void *)s_cpu_retention.retent.clint_frame[core_id]); - s_cpu_retention.retent.clint_frame[core_id] = NULL; - } - } - if (s_cpu_retention.retent.cache_config_frame) { - heap_caps_free((void *)s_cpu_retention.retent.cache_config_frame); - s_cpu_retention.retent.cache_config_frame = NULL; - } - return ESP_OK; -} - -static inline IRAM_ATTR uint32_t save_mstatus_and_disable_global_int(void) -{ - uint32_t mstatus; - __asm__ __volatile__ ( - "csrr %0, mstatus\n" - "csrci mstatus, 0x8\n" - : "=r"(mstatus) - ); - return mstatus; -} - -static inline IRAM_ATTR void restore_mstatus(uint32_t mstatus) -{ - __asm__ __volatile__ ("csrw mstatus, %0\n" :: "r"(mstatus)); + RV_WRITE_CSR(mstatus, mstatus_val); } static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void) @@ -313,7 +130,6 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi frame->pmpcfg2 = RV_READ_CSR(pmpcfg2); frame->pmpcfg3 = RV_READ_CSR(pmpcfg3); -#if SOC_CPU_HAS_PMA frame->pmaaddr0 = RV_READ_CSR(CSR_PMAADDR(0)); frame->pmaaddr1 = RV_READ_CSR(CSR_PMAADDR(1)); frame->pmaaddr2 = RV_READ_CSR(CSR_PMAADDR(2)); @@ -346,7 +162,6 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi frame->pmacfg13 = RV_READ_CSR(CSR_PMACFG(13)); frame->pmacfg14 = RV_READ_CSR(CSR_PMACFG(14)); frame->pmacfg15 = RV_READ_CSR(CSR_PMACFG(15)); -#endif // SOC_CPU_HAS_PMA frame->mcycle = RV_READ_CSR(mcycle); frame->mtvt = RV_READ_CSR(CUSTOM_CSR_MTVT); @@ -414,7 +229,6 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(void) RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2); RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3); -#if SOC_CPU_HAS_PMA RV_WRITE_CSR(CSR_PMAADDR(0), frame->pmaaddr0); RV_WRITE_CSR(CSR_PMAADDR(1), frame->pmaaddr1); RV_WRITE_CSR(CSR_PMAADDR(2), frame->pmaaddr2); @@ -447,7 +261,6 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(void) RV_WRITE_CSR(CSR_PMACFG(13), frame->pmacfg13); RV_WRITE_CSR(CSR_PMACFG(14), frame->pmacfg14); RV_WRITE_CSR(CSR_PMACFG(15), frame->pmacfg15); -#endif //SOC_CPU_HAS_PMA RV_WRITE_CSR(mcycle, frame->mcycle); @@ -491,12 +304,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) { - *(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size); + *(frame_crc_ptr) = esp_rom_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) { - if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ + if(*(frame_crc_ptr) != esp_rom_crc32_le(0, (void *)(frame_ptr), frame_check_size)){ // resume uarts for (int i = 0; i < SOC_UART_NUM; ++i) { #ifndef CONFIG_IDF_TARGET_ESP32 @@ -522,7 +335,11 @@ static 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) { __attribute__((unused)) uint8_t core_id = esp_cpu_get_core_id(); - RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save(); + /* mstatus is core privated CSR, do it near the core critical regs restore */ + uint32_t mstatus = save_mstatus_and_disable_global_int(); + rv_core_critical_regs_save(); + + RvCoreCriticalSleepFrame * frame = s_cpu_retention.retent.critical_frame[core_id]; if ((frame->pmufunc & 0x3) == 0x1) { esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0); #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME @@ -531,7 +348,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, #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) { ; @@ -545,7 +362,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc)); } #endif - + restore_mstatus(mstatus); return pmu_sleep_finish(dslp); } @@ -553,9 +370,8 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin 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 @@ -576,7 +392,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(PCR_CORE1_CONF_REG, PCR_CORE1_CLK_EN); @@ -590,38 +406,27 @@ 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.cache_config_frame); cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]); cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_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; } -#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW - - -#if SOC_PM_SUPPORT_CPU_PD - esp_err_t esp_sleep_cpu_retention_init(void) { - esp_err_t err = ESP_OK; -#if SOC_PM_CPU_RETENTION_BY_SW - err = esp_sleep_cpu_retention_init_impl(); +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE + return esp_sleep_cpu_retention_init_impl(& s_cpu_retention, s_smp_retention_state); +#else + return esp_sleep_cpu_retention_init_impl(& s_cpu_retention); #endif - return err; } esp_err_t esp_sleep_cpu_retention_deinit(void) { - esp_err_t err = ESP_OK; -#if SOC_PM_CPU_RETENTION_BY_SW - err = esp_sleep_cpu_retention_deinit_impl(); -#endif - return err; + return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention); } - bool cpu_domain_pd_allowed(void) { bool allowed = true; @@ -639,7 +444,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 { @@ -649,10 +454,8 @@ esp_err_t sleep_cpu_configure(bool light_sleep_enable) return ESP_OK; } -#endif - #if !CONFIG_FREERTOS_UNICORE -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#if ESP_SLEEP_POWER_DOWN_CPU static IRAM_ATTR void smp_core_do_retention(void) { uint8_t core_id = esp_cpu_get_core_id(); @@ -726,7 +529,7 @@ IRAM_ATTR void esp_sleep_cpu_skip_retention(void) { 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) { ; } @@ -738,7 +541,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/port/esp32h4/sleep_cpu_asm.S b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_asm.S index 31a6f32832..4fece9393a 100644 --- a/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_asm.S +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_asm.S @@ -6,14 +6,11 @@ #include "soc/soc.h" #include "rvsleep-frames.h" -#include "soc/soc_caps.h" -#include "sdkconfig.h" #include "freertos/FreeRTOSConfig.h" -#define MTVT (0x307) -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5 && !CONFIG_IDF_TARGET_ESP32H4 -#include "soc/lp_aon_reg.h" -#include "soc/extmem_reg.h" -#endif +#include "sdkconfig.h" + +#include "soc/cache_reg.h" +#define CACHE_MAP_L1_CACHE_MASK (BIT(0) | BIT(1) | BIT(4)) .section .data1,"aw" .global rv_core_critical_regs_frame @@ -24,6 +21,7 @@ rv_core_critical_regs_frame: .word 0 .endr + /* -------------------------------------------------------------------------------- This assembly subroutine is used to save the critical registers of the CPU @@ -65,7 +63,6 @@ rv_core_critical_regs_save: */ mv a0, t0 sw a0, RV_SLP_CTX_A0(t0) - sw a1, RV_SLP_CTX_A1(t0) sw a2, RV_SLP_CTX_A2(t0) sw a3, RV_SLP_CTX_A3(t0) @@ -120,30 +117,6 @@ rv_core_critical_regs_save: mv t3, t0 csrr t0, mscratch sw t0, RV_SLP_CTX_T0(t3) - -#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5 && !CONFIG_IDF_TARGET_ESP32H4 - /* writeback dcache is required here!!! */ - la t0, EXTMEM_CACHE_SYNC_MAP_REG - li t1, 0x10 - sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */ - la t2, EXTMEM_CACHE_SYNC_ADDR_REG - sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */ - la t0, EXTMEM_CACHE_SYNC_SIZE_REG - sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */ - - la t1, EXTMEM_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 -#endif - - 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) @@ -152,14 +125,6 @@ wait_sync_done: .size rv_core_critical_regs_save, . - rv_core_critical_regs_save - -#define CSR_PCER_U 0x800 -#define CSR_PCMR_U 0x801 -#define PCER_CYCLES (1<<0) /* count clock cycles */ -#define PCMR_GLOBAL_EN (1<<0) /* enable count */ -#define pcer CSR_PCER_U -#define pcmr CSR_PCMR_U - /* -------------------------------------------------------------------------------- This assembly subroutine is used to restore the CPU core critical register @@ -183,7 +148,6 @@ _rv_core_critical_regs_restore: /* export a strong symbol to jump to here, used nop rv_core_critical_regs_restore: - la t0, rv_core_critical_regs_frame csrr t1, mhartid slli t1, t1, 2 diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_dynamic.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_dynamic.c new file mode 100644 index 0000000000..e606633cc1 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_dynamic.c @@ -0,0 +1,199 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" +#include "esp_heap_caps.h" +#include "soc/cache_reg.h" +#include "soc/clint_reg.h" +#include "soc/clic_reg.h" +#include "esp_sleep.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS]; + +static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num) +{ + const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num; + int regs_frame_sz = 0; + for (int num = 0; num < region_num; num++) { + regs_frame_sz += regions[num].end - regions[num].start; + } + void *frame = heap_caps_malloc(sizeof(cpu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame) { + cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t)); + memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t)); + void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz; + memset(regs_frame, 0, regs_frame_sz); + *(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) { + .region = region, + .region_num = region_num, + .regs_frame = (uint32_t *)regs_frame + }; + } + return frame; +} + +static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CACHE_L1_ICACHE_CTRL_REG, .end = CACHE_L1_DCACHE_CTRL_REG + 4 }, + { .start = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(uint8_t core_id) +{ + const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][3] = { + [0 ... portNUM_PROCESSORS - 1] = { + { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_SIP_REG + 4 }, + { .start = CLINT_MINT_MTIMECMP_L_REG, .end = CLINT_MINT_TIMECTL_REG + 4 }, + { .start = CLINT_MINT_MTIME_L_REG, .end = CLINT_MINT_MTIME_H_REG + 4 }, + } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0])); +} + +static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id) +{ + const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][4] = { + [0 ... portNUM_PROCESSORS - 1] = { + { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, + { .start = CLIC_INT_CTRL_REG(3), .end = CLIC_INT_CTRL_REG(3) + 4 }, + { .start = CLIC_INT_CTRL_REG(7), .end = CLIC_INT_CTRL_REG(7) + 4 }, + { .start = CLIC_INT_CTRL_REG(16), .end = CLIC_INT_CTRL_REG(47) + 4 }, + } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0])); +} + +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state) +{ + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) { + void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame; + rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) { + void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) { + void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + atomic_init(&s_smp_retention_state[core_id], SMP_IDLE); + } + return ESP_OK; +err: + esp_sleep_cpu_retention_deinit(); + return ESP_ERR_NO_MEM; +} +#else +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) { + void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame; + rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) { + void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) { + void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +err: + esp_sleep_cpu_retention_deinit(); + return ESP_ERR_NO_MEM; +} +#endif + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.critical_frame[core_id]) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.critical_frame[core_id]); + sleep_cpu_retention_ptr->retent.critical_frame[core_id] = NULL; + rv_core_critical_regs_frame[core_id] = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]); + sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = NULL; + } + if (sleep_cpu_retention_ptr->retent.clic_frame[core_id]) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clic_frame[core_id]); + sleep_cpu_retention_ptr->retent.clic_frame[core_id] = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame[core_id]) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clint_frame[core_id]); + sleep_cpu_retention_ptr->retent.clint_frame[core_id] = NULL; + } + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.cache_config_frame); + sleep_cpu_retention_ptr->retent.cache_config_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_retention.h b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_retention.h new file mode 100644 index 0000000000..7d31580212 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_retention.h @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SLEEP_CPU_RETENTION_H__ +#define __SLEEP_CPU_RETENTION_H__ + +#include "rvsleep-frames.h" +#include "freertos/FreeRTOS.h" +#include "esp_err.h" + +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE +#include +#include "soc/hp_system_reg.h" +typedef enum { + SMP_IDLE, + SMP_BACKUP_START, + SMP_BACKUP_DONE, + SMP_RESTORE_START, + SMP_RESTORE_DONE, + SMP_SKIP_RETENTION, +} smp_retention_state_t; +#endif + +typedef struct { + uint32_t start; + uint32_t end; +} cpu_domain_dev_regs_region_t; + +typedef struct { + cpu_domain_dev_regs_region_t *region; + int region_num; + uint32_t *regs_frame; +} cpu_domain_dev_sleep_frame_t; + +/** + * Internal structure which holds all requested light sleep cpu retention parameters + */ +typedef struct { + struct { + RvCoreCriticalSleepFrame *critical_frame[portNUM_PROCESSORS]; + RvCoreNonCriticalSleepFrame *non_critical_frame[portNUM_PROCESSORS]; + cpu_domain_dev_sleep_frame_t *cache_config_frame; + cpu_domain_dev_sleep_frame_t *clic_frame[portNUM_PROCESSORS]; + cpu_domain_dev_sleep_frame_t *clint_frame[portNUM_PROCESSORS]; + } retent; +} sleep_cpu_retention_t; + +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE + esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state); +#else + esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr); +#endif + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr); + +#endif /* #ifndef __SLEEP_CPU_RETENTION_H__ */ diff --git a/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_static.c b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_static.c new file mode 100644 index 0000000000..2ee118750d --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h4/sleep_cpu_static.c @@ -0,0 +1,237 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" +#include "esp_heap_caps.h" +#include "soc/cache_reg.h" +#include "soc/clint_reg.h" +#include "soc/clic_reg.h" +#include "esp_sleep.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS]; + +#define R_CONCAT(s1, s2) _R_CONCAT(s1, s2) +#define _R_CONCAT(s1, s2) s1 ## s2 + +#define CPU_DOMAIN_DEV_SZ0 (CPU_DOMAIN_DEV_END_ADDR0 - CPU_DOMAIN_DEV_START_ADDR0) +#define CPU_DOMAIN_DEV_SZ1 (CPU_DOMAIN_DEV_END_ADDR1 - CPU_DOMAIN_DEV_START_ADDR1) +#define CPU_DOMAIN_DEV_SZ2 (CPU_DOMAIN_DEV_END_ADDR2 - CPU_DOMAIN_DEV_START_ADDR2) +#define CPU_DOMAIN_DEV_SZ3 (CPU_DOMAIN_DEV_END_ADDR3 - CPU_DOMAIN_DEV_START_ADDR3) +#define CPU_DOMAIN_DEV_SZ4 (CPU_DOMAIN_DEV_END_ADDR4 - CPU_DOMAIN_DEV_START_ADDR4) +#define CPU_DOMAIN_DEV_SZ5 (CPU_DOMAIN_DEV_END_ADDR5 - CPU_DOMAIN_DEV_START_ADDR5) +#define CPU_DOMAIN_DEV_SZ6 (CPU_DOMAIN_DEV_END_ADDR6 - CPU_DOMAIN_DEV_START_ADDR6) +#define CPU_DOMAIN_DEV_SZ7 (CPU_DOMAIN_DEV_END_ADDR7 - CPU_DOMAIN_DEV_START_ADDR7) + +#define CPU_DOMAIN_DEV_TOTAL_SZ(n) (R_CONCAT(__TOTAL_SZ, n)) + +#define __TOTAL_SZ0 (sizeof(cpu_domain_dev_sleep_frame_t)) +#define __TOTAL_SZ1 ((__TOTAL_SZ0) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ0) +#define __TOTAL_SZ2 ((__TOTAL_SZ1) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ1) +#define __TOTAL_SZ3 ((__TOTAL_SZ2) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ2) +#define __TOTAL_SZ4 ((__TOTAL_SZ3) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ3) +#define __TOTAL_SZ5 ((__TOTAL_SZ4) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ4) +#define __TOTAL_SZ6 ((__TOTAL_SZ5) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ5) +#define __TOTAL_SZ7 ((__TOTAL_SZ6) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ6) +#define __TOTAL_SZ8 ((__TOTAL_SZ7) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ7) + +static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num, void * frame) +{ + const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num; + int regs_frame_sz = 0; + for (int num = 0; num < region_num; num++) { + regs_frame_sz += regions[num].end - regions[num].start; + } + if (frame) { + cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t)); + memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t)); + void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz; + memset(regs_frame, 0, regs_frame_sz); + *(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) { + .region = region, + .region_num = region_num, + .regs_frame = (uint32_t *)regs_frame + }; + } + return frame; +} + +#undef CPU_DOMAIN_DEV_START_ADDR0 +#undef CPU_DOMAIN_DEV_END_ADDR0 +#undef CPU_DOMAIN_DEV_START_ADDR1 +#undef CPU_DOMAIN_DEV_END_ADDR1 + +#define CPU_DOMAIN_DEV_START_ADDR0 (CACHE_L1_ICACHE_CTRL_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CACHE_L1_DCACHE_CTRL_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4) + +static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 }, + { .start = CPU_DOMAIN_DEV_START_ADDR1, .end = CPU_DOMAIN_DEV_END_ADDR1 } + }; + static uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame); +} + +#undef CPU_DOMAIN_DEV_START_ADDR0 +#undef CPU_DOMAIN_DEV_END_ADDR0 +#undef CPU_DOMAIN_DEV_START_ADDR1 +#undef CPU_DOMAIN_DEV_END_ADDR1 +#undef CPU_DOMAIN_DEV_START_ADDR2 +#undef CPU_DOMAIN_DEV_END_ADDR2 + +#define CPU_DOMAIN_DEV_START_ADDR0 (CLINT_MINT_SIP_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CLINT_MINT_SIP_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (CLINT_MINT_MTIMECMP_L_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (CLINT_MINT_TIMECTL_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR2 (CLINT_MINT_MTIME_L_REG) +#define CPU_DOMAIN_DEV_END_ADDR2 (CLINT_MINT_MTIME_H_REG + 4) + +static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(uint8_t core_id) +{ + const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][3] = { + [0 ... portNUM_PROCESSORS - 1] = { + { .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 }, + { .start = CPU_DOMAIN_DEV_START_ADDR1, .end = CPU_DOMAIN_DEV_END_ADDR1 }, + { .start = CPU_DOMAIN_DEV_START_ADDR2, .end = CPU_DOMAIN_DEV_END_ADDR2 }, + } + }; + static DRAM_ATTR uint8_t sleep_frame[portNUM_PROCESSORS][CPU_DOMAIN_DEV_TOTAL_SZ(3)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0]), sleep_frame[core_id]); +} + +#undef CPU_DOMAIN_DEV_START_ADDR0 +#undef CPU_DOMAIN_DEV_END_ADDR0 +#undef CPU_DOMAIN_DEV_START_ADDR1 +#undef CPU_DOMAIN_DEV_END_ADDR1 +#undef CPU_DOMAIN_DEV_START_ADDR2 +#undef CPU_DOMAIN_DEV_END_ADDR2 +#undef CPU_DOMAIN_DEV_START_ADDR3 +#undef CPU_DOMAIN_DEV_END_ADDR3 + +#define CPU_DOMAIN_DEV_START_ADDR0 (CLIC_INT_CONFIG_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CLIC_INT_THRESH_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (CLIC_INT_CTRL_REG(3)) +#define CPU_DOMAIN_DEV_END_ADDR1 (CLIC_INT_CTRL_REG(3) + 4) +#define CPU_DOMAIN_DEV_START_ADDR2 (CLIC_INT_CTRL_REG(7)) +#define CPU_DOMAIN_DEV_END_ADDR2 (CLIC_INT_CTRL_REG(7) + 4) +#define CPU_DOMAIN_DEV_START_ADDR3 (CLIC_INT_CTRL_REG(16)) +#define CPU_DOMAIN_DEV_END_ADDR3 (CLIC_INT_CTRL_REG(47) + 4) + +static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id) +{ + const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][4] = { + [0 ... portNUM_PROCESSORS - 1] = { + { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, + { .start = CLIC_INT_CTRL_REG(3), .end = CLIC_INT_CTRL_REG(3) + 4 }, + { .start = CLIC_INT_CTRL_REG(7), .end = CLIC_INT_CTRL_REG(7) + 4 }, + { .start = CLIC_INT_CTRL_REG(16), .end = CLIC_INT_CTRL_REG(47) + 4 }, + } + }; + static DRAM_ATTR uint8_t sleep_frame[portNUM_PROCESSORS][CPU_DOMAIN_DEV_TOTAL_SZ(4)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0]), sleep_frame[core_id]); +} + +#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state) +{ + static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ * portNUM_PROCESSORS] __attribute__((aligned(4))); + static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)* portNUM_PROCESSORS] __attribute__((aligned(4))); + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) { + void * regs = rv_core_critical_regs + core_id * RV_SLEEP_CTX_FRMSZ; + sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *) regs; + rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *) regs; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) { + sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)(rv_core_non_critical_regs+core_id * sizeof(RvCoreNonCriticalSleepFrame)); + } + } + + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id); + sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) { + void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id); + sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init(); + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + atomic_init(&s_smp_retention_state[core_id], SMP_IDLE); + } + return ESP_OK; +} +#else +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ * portNUM_PROCESSORS] __attribute__((aligned(4))); + static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)* portNUM_PROCESSORS] __attribute__((aligned(4))); + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) { + void * regs = rv_core_critical_regs + core_id * RV_SLEEP_CTX_FRMSZ; + sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *) regs; + rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *) regs; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) { + sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)(rv_core_non_critical_regs+core_id * sizeof(RvCoreNonCriticalSleepFrame)); + } + } + + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id); + sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) { + void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id); + sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame; + } + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init(); + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +} +#endif + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.critical_frame[core_id]) { + sleep_cpu_retention_ptr->retent.critical_frame[core_id] = NULL; + rv_core_critical_regs_frame[core_id] = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]) { + sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = NULL; + } + } + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + if (sleep_cpu_retention_ptr->retent.clint_frame[core_id]) { + sleep_cpu_retention_ptr->retent.clint_frame[core_id] = NULL; + } + if (sleep_cpu_retention_ptr->retent.clic_frame[core_id]) { + sleep_cpu_retention_ptr->retent.clic_frame[core_id] = NULL; + } + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame) { + sleep_cpu_retention_ptr->retent.cache_config_frame = NULL; + } + return ESP_OK; +} diff --git a/components/soc/esp32h4/register/soc/cache_reg.h b/components/soc/esp32h4/register/soc/cache_reg.h index df662576b0..19e563df05 100644 --- a/components/soc/esp32h4/register/soc/cache_reg.h +++ b/components/soc/esp32h4/register/soc/cache_reg.h @@ -5,7 +5,6 @@ */ #pragma once -#include #include "soc/soc.h" #ifdef __cplusplus extern "C" {