diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 315cd7732d..81a9e4d36f 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -30,8 +30,8 @@ if(NOT BOOTLOADER_BUILD) "port/${target}/clk_tree.c" "port/clk_tree_common.c") - if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2) - list(APPEND srcs "sleep_retention.c") + if(CONFIG_SOC_PM_SUPPORT_CPU_PD) + list(APPEND srcs "sleep_cpu.c") endif() # [refactor-todo]: requires "driver" for GPIO and RTC (by sleep_gpio and sleep_modes) diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_cpu.h similarity index 59% rename from components/esp_hw_support/include/esp_private/sleep_retention.h rename to components/esp_hw_support/include/esp_private/sleep_cpu.h index 001e559c0c..1e58100e30 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_cpu.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,9 +13,9 @@ extern "C" { #endif /** - * @file sleep_retention.h + * @file sleep_cpu.h * - * This file contains declarations of memory retention related functions in light sleeo mode. + * This file contains declarations of cpu retention related functions in light sleep mode. */ #if SOC_PM_SUPPORT_CPU_PD @@ -30,25 +30,25 @@ bool cpu_domain_pd_allowed(void); #endif -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL /** - * @brief Enable memory retention of some modules. + * @brief Enable cpu retention of some modules. * - * In light sleep mode, before the system goes to sleep, enable the memory + * In light sleep mode, before the system goes to sleep, enable the cpu * retention of modules such as CPU and I/D-cache tag memory. */ -void sleep_enable_memory_retention(void); +void sleep_enable_cpu_retention(void); /** - * @brief Disable memory retention of some modules. + * @brief Disable cpu retention of some modules. * - * In light sleep mode, after the system exits sleep, disable the memory + * In light sleep mode, after the system exits sleep, disable the cpu * retention of moudles such as CPU and I/D-cache tag memory. */ -void sleep_disable_memory_retention(void); +void sleep_disable_cpu_retention(void); -#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD +#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL #ifdef __cplusplus } diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 25d24aaeab..508e50a435 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -486,15 +486,44 @@ void esp_default_wake_deep_sleep(void); void esp_deep_sleep_disable_rom_logging(void); #ifdef SOC_PM_SUPPORT_CPU_PD + +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL /** - * @brief CPU Power down low-level initialize - * - * @param enable enable or disable CPU power down during light sleep + * @brief CPU Power down low-level initialize, enable CPU power down during light sleep * @return * - ESP_OK on success * - ESP_ERR_NO_MEM not enough retention memory */ -esp_err_t esp_sleep_cpu_pd_low_init(bool enable); +esp_err_t esp_sleep_cpu_pd_low_init(void); + +/** + * @brief CPU Power down low-level deinitialize, disable CPU power down during light sleep + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM not enough retention memory + */ +esp_err_t esp_sleep_cpu_pd_low_deinit(void); + +#endif + +/** + * @brief CPU Power down initialize + * + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM not enough retention memory + */ +esp_err_t esp_sleep_cpu_retention_init(void); + +/** + * @brief CPU Power down de-initialize + * + * @return + * - ESP_OK on success + * + * Release system retention memory. + */ +esp_err_t esp_sleep_cpu_retention_deinit(void); #endif #if SOC_GPIO_SUPPORT_SLP_SWITCH diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c new file mode 100644 index 0000000000..472601babc --- /dev/null +++ b/components/esp_hw_support/sleep_cpu.c @@ -0,0 +1,257 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_heap_caps.h" +#include "soc/soc_caps.h" +#include "hal/rtc_hal.h" +#include "esp_private/sleep_cpu.h" +#include "sdkconfig.h" + +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/cache.h" +#endif + +static __attribute__((unused)) const char *TAG = "sleep"; + +/** + * Internal structure which holds all requested light sleep cpu retention parameters + */ +typedef struct { +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + rtc_cntl_sleep_retent_t retent; +#endif +} sleep_cpu_retention_t; + +static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; + +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) +{ + int sets; /* i/d-cache total set counts */ + int index; /* virtual address mapping i/d-cache row offset */ + int waysgrp; + int icache_tagmem_blk_gs, dcache_tagmem_blk_gs; + struct cache_mode imode = { .icache = 1 }; + struct cache_mode dmode = { .icache = 0 }; + + /* calculate/prepare i-cache tag memory retention parameters */ + Cache_Get_Mode(&imode); + sets = imode.cache_size / imode.cache_ways / imode.cache_line_size; + index = (code_seg_vaddr / imode.cache_line_size) % sets; + waysgrp = imode.cache_ways >> 2; + + code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size); + + s_cpu_retention.retent.tagmem.icache.start_point = index; + s_cpu_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff; + s_cpu_retention.retent.tagmem.icache.vld_size = s_cpu_retention.retent.tagmem.icache.size; + if (code_seg_size < imode.cache_size / imode.cache_ways) { + s_cpu_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp; + } + s_cpu_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0; + icache_tagmem_blk_gs = s_cpu_retention.retent.tagmem.icache.vld_size ? s_cpu_retention.retent.tagmem.icache.vld_size : sets * waysgrp; + icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs); + ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10), + imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs); + + /* calculate/prepare d-cache tag memory retention parameters */ + Cache_Get_Mode(&dmode); + sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size; + index = (data_seg_vaddr / dmode.cache_line_size) % sets; + waysgrp = dmode.cache_ways >> 2; + + data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size); + + s_cpu_retention.retent.tagmem.dcache.start_point = index; + s_cpu_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff; + s_cpu_retention.retent.tagmem.dcache.vld_size = s_cpu_retention.retent.tagmem.dcache.size; +#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB + if (data_seg_size < dmode.cache_size / dmode.cache_ways) { + s_cpu_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp; + } + s_cpu_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0; +#else + s_cpu_retention.retent.tagmem.dcache.enable = 1; +#endif + dcache_tagmem_blk_gs = s_cpu_retention.retent.tagmem.dcache.vld_size ? s_cpu_retention.retent.tagmem.dcache.vld_size : sets * waysgrp; + dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs); + ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10), + dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs); + + /* For I or D cache tagmem retention, backup and restore are performed through + * RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache + * tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically + * aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4 + * i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */ + return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3); +} +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + +static esp_err_t esp_sleep_tagmem_pd_low_init(void) +{ +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + if (s_cpu_retention.retent.tagmem.link_addr == NULL) { + extern char _stext[], _etext[]; + uint32_t code_start = (uint32_t)_stext; + uint32_t code_size = (uint32_t)(_etext - _stext); +#if !(CONFIG_SPIRAM && CONFIG_SOC_PM_SUPPORT_TAGMEM_PD) + extern char _rodata_start[], _rodata_reserved_end[]; + uint32_t data_start = (uint32_t)_rodata_start; + uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start); +#else + uint32_t data_start = SOC_DROM_LOW; + uint32_t data_size = SOC_EXTRAM_DATA_SIZE; +#endif + ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB", + code_start, (float)code_size/1024, data_start, (float)data_size/1024); + int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, + tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE, + MALLOC_CAP_RETENTION); + if (buf) { + memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE); + s_cpu_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL); + } else { + s_cpu_retention.retent.tagmem.icache.enable = 0; + s_cpu_retention.retent.tagmem.dcache.enable = 0; + s_cpu_retention.retent.tagmem.link_addr = NULL; + return ESP_ERR_NO_MEM; + } + } +#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + s_cpu_retention.retent.tagmem.icache.enable = 0; + s_cpu_retention.retent.tagmem.dcache.enable = 0; + s_cpu_retention.retent.tagmem.link_addr = NULL; +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + return ESP_OK; +} + +static esp_err_t esp_sleep_tagmem_pd_low_deinit(void) +{ +#if SOC_PM_SUPPORT_TAGMEM_PD + if (s_cpu_retention.retent.tagmem.link_addr) { + heap_caps_free(s_cpu_retention.retent.tagmem.link_addr); + s_cpu_retention.retent.tagmem.icache.enable = 0; + s_cpu_retention.retent.tagmem.dcache.enable = 0; + s_cpu_retention.retent.tagmem.link_addr = NULL; + } +#endif + return ESP_OK; +} +#endif // SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + +esp_err_t esp_sleep_cpu_pd_low_init(void) +{ + if (s_cpu_retention.retent.cpu_pd_mem == NULL) { + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, + SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, + MALLOC_CAP_RETENTION); + if (buf) { + memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); + s_cpu_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); + } else { + return ESP_ERR_NO_MEM; + } + } + +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + if (esp_sleep_tagmem_pd_low_init() != ESP_OK) { +#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB + esp_sleep_cpu_pd_low_deinit(); + return ESP_ERR_NO_MEM; +#endif + } +#endif + return ESP_OK; +} + +esp_err_t esp_sleep_cpu_pd_low_deinit(void) +{ + if (s_cpu_retention.retent.cpu_pd_mem) { + heap_caps_free(s_cpu_retention.retent.cpu_pd_mem); + s_cpu_retention.retent.cpu_pd_mem = NULL; + } + +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + if (esp_sleep_tagmem_pd_low_deinit() != ESP_OK) { +#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB + esp_sleep_cpu_pd_low_deinit(); + return ESP_ERR_NO_MEM; +#endif + } +#endif + return ESP_OK; +} + +void sleep_enable_cpu_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_enable_cpu_retention(&s_cpu_retention.retent); +#endif +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_enable_tagmem_retention(&s_cpu_retention.retent); +#endif +} + +void IRAM_ATTR sleep_disable_cpu_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_disable_cpu_retention(&s_cpu_retention.retent); +#endif +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_disable_tagmem_retention(&s_cpu_retention.retent); +#endif +} + +#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + + +#if SOC_PM_SUPPORT_CPU_PD + +esp_err_t esp_sleep_cpu_retention_init(void) +{ + esp_err_t err = ESP_OK; +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL + err = esp_sleep_cpu_pd_low_init(); +#endif + return err; +} + +esp_err_t esp_sleep_cpu_retention_deinit(void) +{ + esp_err_t err = ESP_OK; +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL + err = esp_sleep_cpu_pd_low_deinit(); +#endif + return err; +} + +bool cpu_domain_pd_allowed(void) +{ +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL + return (s_cpu_retention.retent.cpu_pd_mem != NULL); +#else + return false; +#endif +} + +#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index f61b7bac96..51b79a8480 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -49,7 +49,7 @@ #include "esp_rom_uart.h" #include "esp_rom_sys.h" #include "esp_private/brownout.h" -#include "esp_private/sleep_retention.h" +#include "esp_private/sleep_cpu.h" #include "esp_private/esp_clk.h" #include "esp_private/startup_internal.h" #include "esp_private/esp_task_wdt.h" @@ -366,8 +366,8 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(void) #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL gpio_sleep_mode_config_apply(); #endif -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD - sleep_enable_memory_retention(); +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + sleep_enable_cpu_retention(); #endif #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_read(); @@ -379,8 +379,8 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(void) */ inline static void IRAM_ATTR misc_modules_wake_prepare(void) { -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD - sleep_disable_memory_retention(); +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + sleep_disable_cpu_retention(); #endif #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL gpio_sleep_mode_config_unapply(); diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c deleted file mode 100644 index dd19180abf..0000000000 --- a/components/esp_hw_support/sleep_retention.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -#include "esp_attr.h" -#include "esp_sleep.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_heap_caps.h" -#include "soc/soc_caps.h" -#include "hal/rtc_hal.h" -#include "esp_private/sleep_retention.h" -#include "sdkconfig.h" - -#ifdef CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/cache.h" -#endif - -static __attribute__((unused)) const char *TAG = "sleep"; - -/** - * Internal structure which holds all requested light sleep memory retention parameters - */ -typedef struct { - rtc_cntl_sleep_retent_t retent; -} sleep_retention_t; - -static DRAM_ATTR __attribute__((unused)) sleep_retention_t s_retention; - -#if SOC_PM_SUPPORT_TAGMEM_PD - -#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP -static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) -{ - int sets; /* i/d-cache total set counts */ - int index; /* virtual address mapping i/d-cache row offset */ - int waysgrp; - int icache_tagmem_blk_gs, dcache_tagmem_blk_gs; - struct cache_mode imode = { .icache = 1 }; - struct cache_mode dmode = { .icache = 0 }; - - /* calculate/prepare i-cache tag memory retention parameters */ - Cache_Get_Mode(&imode); - sets = imode.cache_size / imode.cache_ways / imode.cache_line_size; - index = (code_seg_vaddr / imode.cache_line_size) % sets; - waysgrp = imode.cache_ways >> 2; - - code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size); - - s_retention.retent.tagmem.icache.start_point = index; - s_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff; - s_retention.retent.tagmem.icache.vld_size = s_retention.retent.tagmem.icache.size; - if (code_seg_size < imode.cache_size / imode.cache_ways) { - s_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp; - } - s_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0; - icache_tagmem_blk_gs = s_retention.retent.tagmem.icache.vld_size ? s_retention.retent.tagmem.icache.vld_size : sets * waysgrp; - icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs); - ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10), - imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs); - - /* calculate/prepare d-cache tag memory retention parameters */ - Cache_Get_Mode(&dmode); - sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size; - index = (data_seg_vaddr / dmode.cache_line_size) % sets; - waysgrp = dmode.cache_ways >> 2; - - data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size); - - s_retention.retent.tagmem.dcache.start_point = index; - s_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff; - s_retention.retent.tagmem.dcache.vld_size = s_retention.retent.tagmem.dcache.size; -#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB - if (data_seg_size < dmode.cache_size / dmode.cache_ways) { - s_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp; - } - s_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0; -#else - s_retention.retent.tagmem.dcache.enable = 1; -#endif - dcache_tagmem_blk_gs = s_retention.retent.tagmem.dcache.vld_size ? s_retention.retent.tagmem.dcache.vld_size : sets * waysgrp; - dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs); - ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10), - dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs); - - /* For I or D cache tagmem retention, backup and restore are performed through - * RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache - * tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically - * aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4 - * i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */ - return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3); -} -#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - -static esp_err_t esp_sleep_tagmem_pd_low_init(bool enable) -{ - if (enable) { -#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - if (s_retention.retent.tagmem.link_addr == NULL) { - extern char _stext[], _etext[]; - uint32_t code_start = (uint32_t)_stext; - uint32_t code_size = (uint32_t)(_etext - _stext); -#if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32S3) - extern char _rodata_start[], _rodata_reserved_end[]; - uint32_t data_start = (uint32_t)_rodata_start; - uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start); -#else - uint32_t data_start = SOC_DROM_LOW; - uint32_t data_size = SOC_EXTRAM_DATA_SIZE; -#endif - ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB", - code_start, (float)code_size/1024, data_start, (float)data_size/1024); - int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, - tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE, - MALLOC_CAP_RETENTION); - if (buf) { - memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE); - s_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf, - buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL); - } else { - s_retention.retent.tagmem.icache.enable = 0; - s_retention.retent.tagmem.dcache.enable = 0; - s_retention.retent.tagmem.link_addr = NULL; - return ESP_ERR_NO_MEM; - } - } -#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - s_retention.retent.tagmem.icache.enable = 0; - s_retention.retent.tagmem.dcache.enable = 0; - s_retention.retent.tagmem.link_addr = NULL; -#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - } else { -#if SOC_PM_SUPPORT_TAGMEM_PD - if (s_retention.retent.tagmem.link_addr) { - heap_caps_free(s_retention.retent.tagmem.link_addr); - s_retention.retent.tagmem.icache.enable = 0; - s_retention.retent.tagmem.dcache.enable = 0; - s_retention.retent.tagmem.link_addr = NULL; - } -#endif - } - return ESP_OK; -} - -#endif // SOC_PM_SUPPORT_TAGMEM_PD - -#if SOC_PM_SUPPORT_CPU_PD - -esp_err_t esp_sleep_cpu_pd_low_init(bool enable) -{ - if (enable) { - if (s_retention.retent.cpu_pd_mem == NULL) { - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, - SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, - MALLOC_CAP_RETENTION); - if (buf) { - memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); - s_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, - buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); - } else { - return ESP_ERR_NO_MEM; - } - } - } else { - if (s_retention.retent.cpu_pd_mem) { - heap_caps_free(s_retention.retent.cpu_pd_mem); - s_retention.retent.cpu_pd_mem = NULL; - } - } -#if SOC_PM_SUPPORT_TAGMEM_PD - if (esp_sleep_tagmem_pd_low_init(enable) != ESP_OK) { -#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB - esp_sleep_cpu_pd_low_init(false); - return ESP_ERR_NO_MEM; -#endif - } -#endif - return ESP_OK; -} - -bool cpu_domain_pd_allowed(void) -{ - return (s_retention.retent.cpu_pd_mem != NULL); -} - -#endif // SOC_PM_SUPPORT_CPU_PD - -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD - -void sleep_enable_memory_retention(void) -{ -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_enable_cpu_retention(&s_retention.retent); -#endif -#if SOC_PM_SUPPORT_TAGMEM_PD - rtc_cntl_hal_enable_tagmem_retention(&s_retention.retent); -#endif -} - -void IRAM_ATTR sleep_disable_memory_retention(void) -{ -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_disable_cpu_retention(&s_retention.retent); -#endif -#if SOC_PM_SUPPORT_TAGMEM_PD - rtc_cntl_hal_disable_tagmem_retention(&s_retention.retent); -#endif -} - -#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index 6ef1e90e06..eacfc0cc2b 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -21,10 +21,10 @@ entries: esp_clk:esp_rtc_get_time_us (noflash) if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y: sleep_gpio:gpio_sleep_mode_config_apply (noflash) - if SOC_PM_SUPPORT_CPU_PD = y || SOC_PM_SUPPORT_TAGMEM_PD = y: - sleep_retention:sleep_enable_memory_retention (noflash) + if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y && (SOC_PM_SUPPORT_CPU_PD = y || SOC_PM_SUPPORT_TAGMEM_PD = y): + sleep_cpu:sleep_enable_cpu_retention (noflash) if SOC_PM_SUPPORT_CPU_PD = y: - sleep_retention:cpu_domain_pd_allowed (noflash) + sleep_cpu:cpu_domain_pd_allowed (noflash) [mapping:esp_system_pm] archive: libesp_system.a @@ -86,7 +86,8 @@ entries: gpio_hal_workaround:gpio_hal_sleep_pupd_config_unapply (noflash) gpio_hal_workaround:gpio_hal_sleep_mode_setup_wrapper (noflash) gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash) - if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: - rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) - if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y: - rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash) + if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y: + if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: + rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) + if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y: + rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 3d5b435597..20b0113c67 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -327,9 +327,12 @@ esp_err_t esp_pm_configure(const void* vconfig) #endif #if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_SUPPORT_CPU_PD - esp_err_t ret = esp_sleep_cpu_pd_low_init(config->light_sleep_enable); - if (config->light_sleep_enable && ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep."); + if (config->light_sleep_enable) { + if (esp_sleep_cpu_retention_init() != ESP_OK) { + ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep."); + } + } else { + esp_sleep_cpu_retention_deinit(); } #endif diff --git a/components/esp_wifi/esp32c6/esp_adapter.c b/components/esp_wifi/esp32c6/esp_adapter.c index ea4a676797..76eb31bd0b 100644 --- a/components/esp_wifi/esp32c6/esp_adapter.c +++ b/components/esp_wifi/esp32c6/esp_adapter.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,7 +33,6 @@ #include "esp_phy_init.h" #include "soc/rtc_cntl_periph.h" #include "soc/rtc.h" -#include "esp_private/sleep_retention.h" #include "phy_init_data.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h"