diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu.c index 2686426b76..cf86f77d1f 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,13 +17,8 @@ #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/clic_reg.h" -#include "soc/clint_reg.h" #include "soc/rtc_periph.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_cpu.h" @@ -33,38 +28,16 @@ #include "esp32c5/rom/rtc.h" #include "esp32c5/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/uart_hal.h" #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; - RvCoreNonCriticalSleepFrame *non_critical_frame; - cpu_domain_dev_sleep_frame_t *cache_config_frame; - cpu_domain_dev_sleep_frame_t *clic_frame; - cpu_domain_dev_sleep_frame_t *clint_frame; - } retent; -} sleep_cpu_retention_t; - static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; #define CUSTOM_CSR_MTVT (0x307) @@ -77,127 +50,6 @@ static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; -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_CACHE_AUTOLOAD_CTRL_REG, .end = CACHE_L1_CACHE_AUTOLOAD_SCT1_SIZE_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(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 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, - { .start = CLIC_INT_CTRL_REG(0), .end = CLIC_INT_CTRL_REG(47) + 4 }, - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static esp_err_t esp_sleep_cpu_retention_init_impl(void) -{ - if (s_cpu_retention.retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; - rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)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 (s_cpu_retention.retent.clic_frame == NULL) { - void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clic_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - if (s_cpu_retention.retent.clint_frame == NULL) { - void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - 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) -{ - if (s_cpu_retention.retent.critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.critical_frame); - s_cpu_retention.retent.critical_frame = NULL; - rv_core_critical_regs_frame = NULL; - } - if (s_cpu_retention.retent.non_critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame); - s_cpu_retention.retent.non_critical_frame = 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; - } - if (s_cpu_retention.retent.clic_frame) { - heap_caps_free((void *)s_cpu_retention.retent.clic_frame); - s_cpu_retention.retent.clic_frame = NULL; - } - if (s_cpu_retention.retent.clint_frame) { - heap_caps_free((void *)s_cpu_retention.retent.clint_frame); - s_cpu_retention.retent.clint_frame = NULL; - } - return ESP_OK; -} - FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void) { return RV_READ_MSTATUS_AND_DISABLE_INTR(); @@ -468,12 +320,12 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin esp_err_t esp_sleep_cpu_retention_init(void) { - return esp_sleep_cpu_retention_init_impl(); + return esp_sleep_cpu_retention_init_impl(& s_cpu_retention); } esp_err_t esp_sleep_cpu_retention_deinit(void) { - return esp_sleep_cpu_retention_deinit_impl(); + return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention); } bool cpu_domain_pd_allowed(void) diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_dynamic.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_dynamic.c new file mode 100644 index 0000000000..1cc914a236 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_dynamic.c @@ -0,0 +1,139 @@ +/* + * 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/intpri_reg.h" +#include "soc/cache_reg.h" +#include "soc/clic_reg.h" +#include "soc/clint_reg.h" +#include "esp_sleep.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +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_CACHE_AUTOLOAD_CTRL_REG, .end = CACHE_L1_CACHE_AUTOLOAD_SCT1_SIZE_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(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 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, + { .start = CLIC_INT_CTRL_REG(0), .end = CLIC_INT_CTRL_REG(47) + 4 }, + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)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; + } + if (sleep_cpu_retention_ptr->retent.clic_frame == NULL) { + void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +err: + esp_sleep_cpu_retention_deinit(); + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.critical_frame); + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.non_critical_frame); + sleep_cpu_retention_ptr->retent.non_critical_frame = 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; + } + if (sleep_cpu_retention_ptr->retent.clic_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clic_frame); + sleep_cpu_retention_ptr->retent.clic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clint_frame); + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_retention.h b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_retention.h new file mode 100644 index 0000000000..2207830e42 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_retention.h @@ -0,0 +1,40 @@ +/* + * 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 "esp_err.h" + +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; + RvCoreNonCriticalSleepFrame *non_critical_frame; + cpu_domain_dev_sleep_frame_t *cache_config_frame; + cpu_domain_dev_sleep_frame_t *clic_frame; + cpu_domain_dev_sleep_frame_t *clint_frame; + } retent; +} sleep_cpu_retention_t; + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr); +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/esp32c5/sleep_cpu_static.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_static.c new file mode 100644 index 0000000000..fa3f5c4cb3 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_cpu_static.c @@ -0,0 +1,174 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" +#include "soc/intpri_reg.h" +#include "soc/cache_reg.h" +#include "soc/clic_reg.h" +#include "soc/clint_reg.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + +#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) + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +static void * cpu_domain_dev_sleep_frame_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 + +#define CPU_DOMAIN_DEV_START_ADDR0 (CACHE_L1_CACHE_AUTOLOAD_CTRL_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CACHE_L1_CACHE_AUTOLOAD_SCT1_SIZE_REG + 4) + +static void * cache_sleep_frame_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 }, + }; + static uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(1)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_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 +#undef CPU_DOMAIN_DEV_START_ADDR3 +#undef CPU_DOMAIN_DEV_END_ADDR3 + +#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_MTIMECMP_H_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR2 (CLINT_MINT_TIMECTL_REG) +#define CPU_DOMAIN_DEV_END_ADDR2 (CLINT_MINT_TIMECTL_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR3 (CLINT_MINT_MTIME_L_REG) +#define CPU_DOMAIN_DEV_END_ADDR3 (CLINT_MINT_MTIME_H_REG + 4) + +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 } + }; + 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); +} + +#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 (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(0)) +#define CPU_DOMAIN_DEV_END_ADDR1 (CLIC_INT_CTRL_REG(47) + 4) + +static void * clic_sleep_frame_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_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == NULL) { + static uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.critical_frame = (RvCoreCriticalSleepFrame *) rv_core_critical_regs; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *) rv_core_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == NULL) { + static uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.non_critical_frame = (RvCoreNonCriticalSleepFrame *) rv_core_non_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cache_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clic_frame == NULL) { + void *frame = clic_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.clic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = clint_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + sleep_cpu_retention_ptr->retent.non_critical_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame) { + sleep_cpu_retention_ptr->retent.cache_config_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clic_frame) { + sleep_cpu_retention_ptr->retent.clic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu.c index 4620afcb37..1b39c68fff 100644 --- a/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu.c @@ -1,9 +1,10 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ + #include #include #include @@ -17,13 +18,8 @@ #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/extmem_reg.h" -#include "soc/plic_reg.h" -#include "soc/clint_reg.h" #include "soc/rtc_periph.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_cpu.h" @@ -33,41 +29,13 @@ #include "esp32c6/rom/rtc.h" #include "esp32c6/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/uart_hal.h" #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; - RvCoreNonCriticalSleepFrame *non_critical_frame; - cpu_domain_dev_sleep_frame_t *intpri_frame; - cpu_domain_dev_sleep_frame_t *cache_config_frame; - cpu_domain_dev_sleep_frame_t *plic_frame; - cpu_domain_dev_sleep_frame_t *clint_frame; - } retent; -} sleep_cpu_retention_t; - -static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; - #define CUSTOM_CSR_PCER_MACHINE 0x7e0 #define CUSTOM_CSR_PCMR_MACHINE 0x7e1 #define CUSTOM_CSR_PCCR_MACHINE 0x7e2 @@ -82,148 +50,11 @@ static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; #define CUSTOM_CSR_CO_HWLP 0x7f1 #define CUSTOM_CSR_CO_AIA 0x7f2 -extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; -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 __attribute__((unused)) const char *TAG = "sleep"; -static inline void * cpu_domain_intpri_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = INTPRI_CORE0_CPU_INT_ENABLE_REG, .end = INTPRI_RND_ECO_LOW_REG + 4 }, - { .start = INTPRI_RND_ECO_HIGH_REG, .end = INTPRI_RND_ECO_HIGH_REG + 4 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} +static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; -static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .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 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static inline void * cpu_domain_plic_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 }, - { .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 }, - { .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 }, - { .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_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(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 }, - { .start = CLINT_UINT_SIP_REG, .end = CLINT_UINT_UTIMECMP_H_REG + 4 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static esp_err_t esp_sleep_cpu_retention_init_impl(void) -{ - if (s_cpu_retention.retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; - rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.intpri_frame == NULL) { - void *frame = cpu_domain_intpri_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.intpri_frame = (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 (s_cpu_retention.retent.plic_frame == NULL) { - void *frame = cpu_domain_plic_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - if (s_cpu_retention.retent.clint_frame == NULL) { - void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - 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) -{ - if (s_cpu_retention.retent.critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.critical_frame); - s_cpu_retention.retent.critical_frame = NULL; - rv_core_critical_regs_frame = NULL; - } - if (s_cpu_retention.retent.non_critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame); - s_cpu_retention.retent.non_critical_frame = NULL; - } - if (s_cpu_retention.retent.intpri_frame) { - heap_caps_free((void *)s_cpu_retention.retent.intpri_frame); - s_cpu_retention.retent.intpri_frame = 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; - } - if (s_cpu_retention.retent.plic_frame) { - heap_caps_free((void *)s_cpu_retention.retent.plic_frame); - s_cpu_retention.retent.plic_frame = NULL; - } - if (s_cpu_retention.retent.clint_frame) { - heap_caps_free((void *)s_cpu_retention.retent.clint_frame); - s_cpu_retention.retent.clint_frame = NULL; - } - return ESP_OK; -} FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void) { @@ -512,12 +343,12 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin esp_err_t esp_sleep_cpu_retention_init(void) { - return esp_sleep_cpu_retention_init_impl(); + return esp_sleep_cpu_retention_init_impl(& s_cpu_retention); } esp_err_t esp_sleep_cpu_retention_deinit(void) { - return esp_sleep_cpu_retention_deinit_impl(); + return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention); } bool cpu_domain_pd_allowed(void) diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_dynamic.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_dynamic.c new file mode 100644 index 0000000000..5419aabb56 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_dynamic.c @@ -0,0 +1,160 @@ +/* + * 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/intpri_reg.h" +#include "soc/extmem_reg.h" +#include "soc/plic_reg.h" +#include "soc/clint_reg.h" +#include "esp_sleep.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +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_intpri_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = INTPRI_CORE0_CPU_INT_ENABLE_REG, .end = INTPRI_RND_ECO_LOW_REG + 4 }, + { .start = INTPRI_RND_ECO_HIGH_REG, .end = INTPRI_RND_ECO_HIGH_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .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 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_plic_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 }, + { .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 }, + { .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 }, + { .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_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(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 }, + { .start = CLINT_UINT_SIP_REG, .end = CLINT_UINT_UTIMECMP_H_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame == NULL) { + void *frame = cpu_domain_intpri_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.intpri_frame = (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; + } + if (sleep_cpu_retention_ptr->retent.plic_frame == NULL) { + void *frame = cpu_domain_plic_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +err: + esp_sleep_cpu_retention_deinit(); + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t * sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.critical_frame); + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.non_critical_frame); + sleep_cpu_retention_ptr->retent.non_critical_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.intpri_frame); + sleep_cpu_retention_ptr->retent.intpri_frame = 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; + } + if (sleep_cpu_retention_ptr->retent.plic_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.plic_frame); + sleep_cpu_retention_ptr->retent.plic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clint_frame); + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_retention.h b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_retention.h new file mode 100644 index 0000000000..d5278df967 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_retention.h @@ -0,0 +1,42 @@ +/* + * 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 "esp_err.h" + +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; + RvCoreNonCriticalSleepFrame *non_critical_frame; + cpu_domain_dev_sleep_frame_t *intpri_frame; + cpu_domain_dev_sleep_frame_t *cache_config_frame; + cpu_domain_dev_sleep_frame_t *plic_frame; + cpu_domain_dev_sleep_frame_t *clint_frame; + } retent; +} sleep_cpu_retention_t; + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr); +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/esp32c6/sleep_cpu_static.c b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_static.c new file mode 100644 index 0000000000..2f155add68 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c6/sleep_cpu_static.c @@ -0,0 +1,207 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" +#include "soc/intpri_reg.h" +#include "soc/extmem_reg.h" +#include "soc/plic_reg.h" +#include "soc/clint_reg.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +#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_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 (INTPRI_CORE0_CPU_INT_ENABLE_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (INTPRI_RND_ECO_LOW_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (INTPRI_RND_ECO_HIGH_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (INTPRI_RND_ECO_HIGH_REG + 4) + +static void * intpri_sleep_frame_init(void) +{ + static const 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 DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_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 + +#define CPU_DOMAIN_DEV_START_ADDR0 (EXTMEM_L1_CACHE_CTRL_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (EXTMEM_L1_CACHE_CTRL_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG + 4) + +static void * cache_sleep_frame_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 DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_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 +#undef CPU_DOMAIN_DEV_START_ADDR3 +#undef CPU_DOMAIN_DEV_END_ADDR3 + +#define CPU_DOMAIN_DEV_START_ADDR0 (PLIC_MXINT_ENABLE_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (PLIC_MXINT_CLAIM_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (PLIC_MXINT_CONF_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (PLIC_MXINT_CONF_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR2 (PLIC_UXINT_ENABLE_REG) +#define CPU_DOMAIN_DEV_END_ADDR2 (PLIC_UXINT_CLAIM_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR3 (PLIC_UXINT_CONF_REG) +#define CPU_DOMAIN_DEV_END_ADDR3 (PLIC_UXINT_CONF_REG + 4) + +static void * plic_sleep_frame_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 }, + { .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 DRAM_ATTR 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); +} + +#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 (CLINT_MINT_SIP_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CLINT_MINT_MTIMECMP_H_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (CLINT_UINT_SIP_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (CLINT_UINT_UTIMECMP_H_REG + 4) + +static void * clint_sleep_frame_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 DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == NULL) { + static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.critical_frame = (RvCoreCriticalSleepFrame *) rv_core_critical_regs; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *) rv_core_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == NULL) { + static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.non_critical_frame = (RvCoreNonCriticalSleepFrame *) rv_core_non_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame == NULL) { + void *frame = intpri_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.intpri_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cache_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.plic_frame == NULL) { + void *frame = plic_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = clint_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + sleep_cpu_retention_ptr->retent.non_critical_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame) { + sleep_cpu_retention_ptr->retent.intpri_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame) { + sleep_cpu_retention_ptr->retent.cache_config_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.plic_frame) { + sleep_cpu_retention_ptr->retent.plic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu.c index 217c8cfa2d..7ca3e2a268 100644 --- a/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,13 +17,8 @@ #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/clic_reg.h" -#include "soc/clint_reg.h" #include "soc/rtc_periph.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_cpu.h" @@ -33,6 +28,7 @@ #include "esp32c61/rom/rtc.h" #include "esp32c61/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" @@ -41,29 +37,6 @@ 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; - RvCoreNonCriticalSleepFrame *non_critical_frame; - cpu_domain_dev_sleep_frame_t *cache_config_frame; - cpu_domain_dev_sleep_frame_t *clic_frame; - cpu_domain_dev_sleep_frame_t *clint_frame; - } retent; -} sleep_cpu_retention_t; static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; @@ -77,127 +50,6 @@ static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; -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_CACHE_AUTOLOAD_CTRL_REG, .end = CACHE_L1_CACHE_AUTOLOAD_SCT1_SIZE_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(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 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, - { .start = CLIC_INT_CTRL_REG(0), .end = CLIC_INT_CTRL_REG(47) + 4 }, - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static esp_err_t esp_sleep_cpu_retention_init_impl(void) -{ - if (s_cpu_retention.retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; - rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)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 (s_cpu_retention.retent.clic_frame == NULL) { - void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clic_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - if (s_cpu_retention.retent.clint_frame == NULL) { - void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - 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) -{ - if (s_cpu_retention.retent.critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.critical_frame); - s_cpu_retention.retent.critical_frame = NULL; - rv_core_critical_regs_frame = NULL; - } - if (s_cpu_retention.retent.non_critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame); - s_cpu_retention.retent.non_critical_frame = 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; - } - if (s_cpu_retention.retent.clic_frame) { - heap_caps_free((void *)s_cpu_retention.retent.clic_frame); - s_cpu_retention.retent.clic_frame = NULL; - } - if (s_cpu_retention.retent.clint_frame) { - heap_caps_free((void *)s_cpu_retention.retent.clint_frame); - s_cpu_retention.retent.clint_frame = NULL; - } - return ESP_OK; -} - FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void) { return RV_READ_MSTATUS_AND_DISABLE_INTR(); @@ -468,12 +320,12 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin esp_err_t esp_sleep_cpu_retention_init(void) { - return esp_sleep_cpu_retention_init_impl(); + return esp_sleep_cpu_retention_init_impl(& s_cpu_retention); } esp_err_t esp_sleep_cpu_retention_deinit(void) { - return esp_sleep_cpu_retention_deinit_impl(); + return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention); } bool cpu_domain_pd_allowed(void) diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_dynamic.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_dynamic.c new file mode 100644 index 0000000000..571d38c72c --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_dynamic.c @@ -0,0 +1,141 @@ +/* + * 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/intpri_reg.h" +#include "soc/cache_reg.h" +#include "soc/clic_reg.h" +#include "soc/clint_reg.h" +#include "esp_sleep.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +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_CACHE_AUTOLOAD_CTRL_REG, .end = CACHE_L1_CACHE_AUTOLOAD_SCT1_SIZE_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(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 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, + { .start = CLIC_INT_CTRL_REG(0), .end = CLIC_INT_CTRL_REG(47) + 4 }, + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)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; + } + if (sleep_cpu_retention_ptr->retent.clic_frame == NULL) { + void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +err: + esp_sleep_cpu_retention_deinit(); + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.critical_frame); + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.non_critical_frame); + sleep_cpu_retention_ptr->retent.non_critical_frame = 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; + } + if (sleep_cpu_retention_ptr->retent.clic_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clic_frame); + sleep_cpu_retention_ptr->retent.clic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clint_frame); + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_retention.h b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_retention.h new file mode 100644 index 0000000000..a87939ba67 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_retention.h @@ -0,0 +1,41 @@ +/* + * 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 "esp_err.h" + + +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; + RvCoreNonCriticalSleepFrame *non_critical_frame; + cpu_domain_dev_sleep_frame_t *cache_config_frame; + cpu_domain_dev_sleep_frame_t *clic_frame; + cpu_domain_dev_sleep_frame_t *clint_frame; + } retent; +} sleep_cpu_retention_t; + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr); +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/esp32c61/sleep_cpu_static.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_static.c new file mode 100644 index 0000000000..8acc8c667c --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_cpu_static.c @@ -0,0 +1,176 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" + +#include "soc/intpri_reg.h" +#include "soc/cache_reg.h" +#include "soc/clic_reg.h" +#include "soc/clint_reg.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +#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_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 + +#define CPU_DOMAIN_DEV_START_ADDR0 (CACHE_L1_CACHE_AUTOLOAD_CTRL_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CACHE_L1_CACHE_AUTOLOAD_SCT1_SIZE_REG + 4) + +static void * cache_sleep_frame_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 }, + }; + static DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(1)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_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 +#undef CPU_DOMAIN_DEV_START_ADDR3 +#undef CPU_DOMAIN_DEV_END_ADDR3 + +#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_MTIMECMP_H_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR2 (CLINT_MINT_TIMECTL_REG) +#define CPU_DOMAIN_DEV_END_ADDR2 (CLINT_MINT_TIMECTL_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR3 (CLINT_MINT_MTIME_L_REG) +#define CPU_DOMAIN_DEV_END_ADDR3 (CLINT_MINT_MTIME_H_REG + 4) + +static void * clint_sleep_frame_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 }, + { .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 DRAM_ATTR 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); +} + +#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 (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(0)) +#define CPU_DOMAIN_DEV_END_ADDR1 (CLIC_INT_CTRL_REG(47) + 4) + +static void * clic_sleep_frame_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 DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == NULL) { + static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.critical_frame = (RvCoreCriticalSleepFrame *)rv_core_critical_regs; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)rv_core_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == NULL) { + static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.non_critical_frame = (RvCoreNonCriticalSleepFrame *) rv_core_non_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cache_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clic_frame == NULL) { + void *frame = clic_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.clic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = clint_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + sleep_cpu_retention_ptr->retent.non_critical_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame) { + sleep_cpu_retention_ptr->retent.cache_config_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clic_frame) { + sleep_cpu_retention_ptr->retent.clic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu.c index 24cd7b28aa..632bfd510f 100644 --- a/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,13 +18,8 @@ #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/extmem_reg.h" -#include "soc/plic_reg.h" -#include "soc/clint_reg.h" #include "soc/rtc_periph.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_cpu.h" @@ -33,6 +28,7 @@ #include "esp32h2/rom/rtc.h" #include "esp32h2/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" @@ -41,33 +37,9 @@ 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; - RvCoreNonCriticalSleepFrame *non_critical_frame; - cpu_domain_dev_sleep_frame_t *intpri_frame; - cpu_domain_dev_sleep_frame_t *cache_config_frame; - cpu_domain_dev_sleep_frame_t *plic_frame; - cpu_domain_dev_sleep_frame_t *clint_frame; - } retent; -} sleep_cpu_retention_t; - static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; + #define CUSTOM_CSR_PCER_MACHINE 0x7e0 #define CUSTOM_CSR_PCMR_MACHINE 0x7e1 #define CUSTOM_CSR_PCCR_MACHINE 0x7e2 @@ -84,146 +56,6 @@ static DRAM_ATTR sleep_cpu_retention_t s_cpu_retention; extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; -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_intpri_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = INTPRI_CORE0_CPU_INT_ENABLE_REG, .end = INTPRI_RND_ECO_LOW_REG + 4 }, - { .start = INTPRI_RND_ECO_HIGH_REG, .end = INTPRI_RND_ECO_HIGH_REG + 4 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -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_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_plic_sleep_frame_alloc_and_init(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 }, - { .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 }, - { .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 }, - { .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_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(void) -{ - const static cpu_domain_dev_regs_region_t regions[] = { - { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 }, - { .start = CLINT_UINT_SIP_REG, .end = CLINT_UINT_UTIMECMP_H_REG + 4 } - }; - return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); -} - -static esp_err_t esp_sleep_cpu_retention_init_impl(void) -{ - if (s_cpu_retention.retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; - rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)frame; - } - if (s_cpu_retention.retent.intpri_frame == NULL) { - void *frame = cpu_domain_intpri_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.intpri_frame = (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 (s_cpu_retention.retent.plic_frame == NULL) { - void *frame = cpu_domain_plic_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - if (s_cpu_retention.retent.clint_frame == NULL) { - void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); - if (frame == NULL) { - goto err; - } - s_cpu_retention.retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; - } - 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) -{ - if (s_cpu_retention.retent.critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.critical_frame); - s_cpu_retention.retent.critical_frame = NULL; - rv_core_critical_regs_frame = NULL; - } - if (s_cpu_retention.retent.non_critical_frame) { - heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame); - s_cpu_retention.retent.non_critical_frame = NULL; - } - if (s_cpu_retention.retent.intpri_frame) { - heap_caps_free((void *)s_cpu_retention.retent.intpri_frame); - s_cpu_retention.retent.intpri_frame = 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; - } - if (s_cpu_retention.retent.plic_frame) { - heap_caps_free((void *)s_cpu_retention.retent.plic_frame); - s_cpu_retention.retent.plic_frame = NULL; - } - if (s_cpu_retention.retent.clint_frame) { - heap_caps_free((void *)s_cpu_retention.retent.clint_frame); - s_cpu_retention.retent.clint_frame = NULL; - } - return ESP_OK; -} - FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void) { return RV_READ_MSTATUS_AND_DISABLE_INTR(); @@ -511,12 +343,12 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin esp_err_t esp_sleep_cpu_retention_init(void) { - return esp_sleep_cpu_retention_init_impl(); + return esp_sleep_cpu_retention_init_impl(& s_cpu_retention); } esp_err_t esp_sleep_cpu_retention_deinit(void) { - return esp_sleep_cpu_retention_deinit_impl(); + return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention); } bool cpu_domain_pd_allowed(void) diff --git a/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_dynamic.c b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_dynamic.c new file mode 100644 index 0000000000..30f8f02e55 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_dynamic.c @@ -0,0 +1,161 @@ +/* + * 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/intpri_reg.h" +#include "soc/extmem_reg.h" +#include "soc/plic_reg.h" +#include "soc/clint_reg.h" +#include "esp_sleep.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +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_intpri_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = INTPRI_CORE0_CPU_INT_ENABLE_REG, .end = INTPRI_RND_ECO_LOW_REG + 4 }, + { .start = INTPRI_RND_ECO_HIGH_REG, .end = INTPRI_RND_ECO_HIGH_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +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_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_plic_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 }, + { .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 }, + { .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 }, + { .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_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(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 }, + { .start = CLINT_UINT_SIP_REG, .end = CLINT_UINT_UTIMECMP_H_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)frame; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame == NULL) { + void *frame = cpu_domain_intpri_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.intpri_frame = (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; + } + if (sleep_cpu_retention_ptr->retent.plic_frame == NULL) { + void *frame = cpu_domain_plic_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +err: + esp_sleep_cpu_retention_deinit(); + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.critical_frame); + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.non_critical_frame); + sleep_cpu_retention_ptr->retent.non_critical_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.intpri_frame); + sleep_cpu_retention_ptr->retent.intpri_frame = 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; + } + if (sleep_cpu_retention_ptr->retent.plic_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.plic_frame); + sleep_cpu_retention_ptr->retent.plic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clint_frame); + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_retention.h b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_retention.h new file mode 100644 index 0000000000..cf5ce69bc4 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_retention.h @@ -0,0 +1,42 @@ +/* + * 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 "esp_err.h" + + +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; + RvCoreNonCriticalSleepFrame *non_critical_frame; + cpu_domain_dev_sleep_frame_t *intpri_frame; + cpu_domain_dev_sleep_frame_t *cache_config_frame; + cpu_domain_dev_sleep_frame_t *plic_frame; + cpu_domain_dev_sleep_frame_t *clint_frame; + } retent; +} sleep_cpu_retention_t; + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr); +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/esp32h2/sleep_cpu_static.c b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_static.c new file mode 100644 index 0000000000..63ee6277c0 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32h2/sleep_cpu_static.c @@ -0,0 +1,204 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" + +#include "soc/intpri_reg.h" +#include "soc/extmem_reg.h" +#include "soc/plic_reg.h" +#include "soc/clint_reg.h" + +#include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" + + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +#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_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 (INTPRI_CORE0_CPU_INT_ENABLE_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (INTPRI_RND_ECO_LOW_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (INTPRI_RND_ECO_HIGH_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (INTPRI_RND_ECO_HIGH_REG + 4) + +static void * intpri_sleep_frame_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 DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame); +} + +#undef CPU_DOMAIN_DEV_START_ADDR0 +#undef CPU_DOMAIN_DEV_END_ADDR0 + +#define CPU_DOMAIN_DEV_START_ADDR0 (CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4) + +static void * cache_sleep_frame_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 } + }; + static DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(1)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_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 +#undef CPU_DOMAIN_DEV_START_ADDR3 +#undef CPU_DOMAIN_DEV_END_ADDR3 + +#define CPU_DOMAIN_DEV_START_ADDR0 (PLIC_MXINT_ENABLE_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (PLIC_MXINT_CLAIM_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (PLIC_MXINT_CONF_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (PLIC_MXINT_CONF_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR2 (PLIC_UXINT_ENABLE_REG) +#define CPU_DOMAIN_DEV_END_ADDR2 (PLIC_UXINT_CLAIM_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR3 (PLIC_UXINT_CONF_REG) +#define CPU_DOMAIN_DEV_END_ADDR3 (PLIC_UXINT_CONF_REG + 4) + +static void * plic_sleep_frame_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 }, + { .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 DRAM_ATTR 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); +} + +#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 (CLINT_MINT_SIP_REG) +#define CPU_DOMAIN_DEV_END_ADDR0 (CLINT_MINT_MTIMECMP_H_REG + 4) +#define CPU_DOMAIN_DEV_START_ADDR1 (CLINT_UINT_SIP_REG) +#define CPU_DOMAIN_DEV_END_ADDR1 (CLINT_UINT_UTIMECMP_H_REG + 4) + +static void * clint_sleep_frame_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 DRAM_ATTR uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4))); + return cpu_domain_dev_sleep_frame_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame); +} + +esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame == NULL) { + static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.critical_frame = (RvCoreCriticalSleepFrame *) rv_core_critical_regs; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *) rv_core_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame == NULL) { + static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)] __attribute__((aligned(4))); + sleep_cpu_retention_ptr->retent.non_critical_frame = (RvCoreNonCriticalSleepFrame *) rv_core_non_critical_regs; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame == NULL) { + void *frame = intpri_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.intpri_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) { + void *frame = cache_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.plic_frame == NULL) { + void *frame = plic_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (sleep_cpu_retention_ptr->retent.clint_frame == NULL) { + void *frame = clint_sleep_frame_init(); + sleep_cpu_retention_ptr->retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +} + +esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr) +{ + if (sleep_cpu_retention_ptr->retent.critical_frame) { + sleep_cpu_retention_ptr->retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.non_critical_frame) { + sleep_cpu_retention_ptr->retent.non_critical_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.intpri_frame) { + sleep_cpu_retention_ptr->retent.intpri_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.cache_config_frame) { + sleep_cpu_retention_ptr->retent.cache_config_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.plic_frame) { + sleep_cpu_retention_ptr->retent.plic_frame = NULL; + } + if (sleep_cpu_retention_ptr->retent.clint_frame) { + sleep_cpu_retention_ptr->retent.clint_frame = NULL; + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c index 79d9da85ec..55bdbad1e7 100644 --- a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,7 +18,6 @@ #include "esp_rom_crc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_heap_caps.h" #include "riscv/csr.h" #include "soc/clic_reg.h" #include "soc/rtc_periph.h" @@ -32,6 +31,7 @@ #include "esp32p4/rom/ets_sys.h" #include "esp32p4/rom/rtc.h" #include "rvsleep-frames.h" +#include "sleep_cpu_retention.h" #if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME #include "esp_private/system_internal.h" @@ -40,142 +40,16 @@ #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; - static TCM_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 *clic_frame[portNUM_PROCESSORS]; - } retent; -} sleep_cpu_retention_t; - static TCM_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) -{ - 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_clic_sleep_frame_alloc_and_init(uint8_t core_id) -{ - const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][2] = { - [0 ... portNUM_PROCESSORS - 1] = { - { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, - { .start = CLIC_INT_CTRL_REG(0), .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; - } - } - for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { - 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 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); - } -#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; - } - } - for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { - 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; - } - } - return ESP_OK; -} - FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void) { return RV_READ_MSTATUS_AND_DISABLE_INTR(); @@ -457,12 +331,16 @@ esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, esp_err_t esp_sleep_cpu_retention_init(void) { - return 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 } esp_err_t esp_sleep_cpu_retention_deinit(void) { - return esp_sleep_cpu_retention_deinit_impl(); + return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention); } bool cpu_domain_pd_allowed(void) diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_dynamic.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_dynamic.c new file mode 100644 index 0000000000..ac62b8fb19 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_dynamic.c @@ -0,0 +1,146 @@ +/* + * 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/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_clic_sleep_frame_alloc_and_init(uint8_t core_id) +{ + const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][2] = { + [0 ... portNUM_PROCESSORS - 1] = { + { .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 }, + { .start = CLIC_INT_CTRL_REG(0), .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)); +} + +#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; + } + } + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + 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; + } + } + 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; + } + } + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + 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; + } + } + 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; + } + } + for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) { + 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; + } + } + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_retention.h b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_retention.h new file mode 100644 index 0000000000..9c0f9d9651 --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_retention.h @@ -0,0 +1,57 @@ +/* + * 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 *clic_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/esp32p4/sleep_cpu_static.c b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_static.c new file mode 100644 index 0000000000..fcd6a9953a --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32p4/sleep_cpu_static.c @@ -0,0 +1,155 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_check.h" +#include "soc/clic_reg.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 (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(0)) +#define CPU_DOMAIN_DEV_END_ADDR1 (CLIC_INT_CTRL_REG(47) + 4) + +static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id) +{ + static DRAM_ATTR cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][2] = { + [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 }, + } + }; + static DRAM_ATTR uint8_t sleep_frame[portNUM_PROCESSORS][CPU_DOMAIN_DEV_TOTAL_SZ(2)] __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.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; + } + } + 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.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; + } + } + 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.clic_frame[core_id]) { + sleep_cpu_retention_ptr->retent.clic_frame[core_id] = NULL; + } + } + return ESP_OK; +}