From 03746de96f65923983d2a3c52457c0667960853f Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 18 Jun 2021 17:25:04 +0800 Subject: [PATCH] light sleep: add cpu power down support for esp32s3 --- components/esp_hw_support/sleep_retention.c | 4 + components/esp_pm/Kconfig | 8 +- components/hal/CMakeLists.txt | 1 + .../hal/esp32c3/include/hal/rtc_cntl_ll.h | 12 ++- components/hal/esp32c3/rtc_cntl_hal.c | 41 ++++++++-- .../hal/esp32s3/include/hal/rtc_cntl_ll.h | 30 +++++++ components/hal/esp32s3/rtc_cntl_hal.c | 82 +++++++++++++++++++ components/hal/include/hal/rtc_hal.h | 9 +- components/soc/esp32s3/include/soc/soc_caps.h | 10 +++ 9 files changed, 181 insertions(+), 16 deletions(-) create mode 100644 components/hal/esp32s3/rtc_cntl_hal.c diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c index f915f3f107..564b983a77 100644 --- a/components/esp_hw_support/sleep_retention.c +++ b/components/esp_hw_support/sleep_retention.c @@ -29,7 +29,11 @@ static DRAM_ATTR sleep_retention_t s_retention; #if SOC_PM_SUPPORT_CPU_PD +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 #define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT) +#else +#define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_DMA | MALLOC_CAP_DEFAULT) +#endif esp_err_t esp_sleep_cpu_pd_low_init(bool enable) { diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index dc0e14422f..d7f42245a3 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -96,10 +96,12 @@ menu "Power Management" config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP bool "Power down CPU in light sleep" - depends on IDF_TARGET_ESP32C3 + depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 default y help - If enabled, the CPU will be powered down in light sleep. Enabling this option will consume - 1.68 KB of internal RAM and will reduce sleep current consumption by about 100 uA. + If enabled, the CPU will be powered down in light sleep. On esp32c3 soc, enabling this + option will consume 1.68 KB of internal RAM and will reduce sleep current consumption + by about 100 uA. On esp32s3 soc, enabling this option will consume 8.58 KB of internal + RAM and will reduce sleep current consumption by about 650 uA. endmenu # "Power Management" diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index ba6e51db8b..2959ecbb50 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -85,6 +85,7 @@ if(NOT BOOTLOADER_BUILD) "esp32s3/hmac_hal.c" "esp32s3/interrupt_descriptor_table.c" "esp32s3/touch_sensor_hal.c" + "esp32s3/rtc_cntl_hal.c" "usbh_hal.c") endif() diff --git a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h index 72385568a4..1ff802fde7 100644 --- a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h @@ -47,12 +47,18 @@ static inline void rtc_cntl_ll_gpio_clear_wakeup_pins(void) REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR); } -static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr) +static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr) { - /* write memory address to register */ REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_LINK_ADDR, (uint32_t)addr); - /* Enable clock */ +} + +static inline void rtc_cntl_ll_enable_cpu_retention_clock(void) +{ REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); +} + +static inline void rtc_cntl_ll_enable_cpu_retention(void) +{ /* Enable retention when cpu sleep enable */ REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); } diff --git a/components/hal/esp32c3/rtc_cntl_hal.c b/components/hal/esp32c3/rtc_cntl_hal.c index 2fb14a5b2f..90b2e9d083 100644 --- a/components/hal/esp32c3/rtc_cntl_hal.c +++ b/components/hal/esp32c3/rtc_cntl_hal.c @@ -16,8 +16,10 @@ #include "soc/soc_caps.h" #include "soc/lldesc.h" +#include "hal/dma_types.h" #include "hal/rtc_hal.h" #include "hal/assert.h" +#include "esp_attr.h" #define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ @@ -34,7 +36,7 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) lldesc_t *plink = (lldesc_t *)elem; plink->eof = next ? 0 : 1; - plink->owner = 1; + plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; plink->size = size >> 4; /* in unit of 16 bytes */ plink->length = size >> 4; plink->buf = buff; @@ -44,18 +46,39 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) return (void *)plink; } +#if SOC_PM_SUPPORT_CPU_PD + void rtc_cntl_hal_enable_cpu_retention(void *addr) { + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + if (addr) { - lldesc_t *plink = (lldesc_t *)addr; + if (retent->cpu_pd_mem) { + lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem; - /* dma link buffer configure */ - rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; - pbuf->cfg[0] = 0; - pbuf->cfg[1] = 0; - pbuf->cfg[2] = 0; - pbuf->cfg[3] = (uint32_t)-1; + /* dma link buffer configure */ + rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; + pbuf->cfg[0] = 0; + pbuf->cfg[1] = 0; + pbuf->cfg[2] = 0; + pbuf->cfg[3] = (uint32_t)-1; - rtc_cntl_ll_enable_cpu_retention((uint32_t)addr); + rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink); + rtc_cntl_ll_enable_cpu_retention_clock(); + rtc_cntl_ll_enable_cpu_retention(); + } } } + +void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + rtc_cntl_ll_disable_cpu_retention(); + } + } +} + +#endif // SOC_PM_SUPPORT_CPU_PD diff --git a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h index e1ad1d52cd..518c95a014 100644 --- a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h @@ -17,6 +17,7 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "soc/apb_ctrl_reg.h" #ifdef __cplusplus extern "C" { @@ -53,6 +54,35 @@ static inline void rtc_cntl_ll_ulp_wakeup_enable(void) SET_PERI_REG_BITS(RTC_CNTL_STATE0_REG, RTC_CNTL_WAKEUP_ENA_V, 0x800, RTC_CNTL_WAKEUP_ENA_S); } +static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t link_addr) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_CPU_LINK_ADDR, link_addr); +} + +static inline void rtc_cntl_ll_enable_cpu_retention_clock(void) +{ + REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); /* Enable internal 20 MHz clock */ +} + +static inline void rtc_cntl_ll_enable_cpu_retention(void) +{ + uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); + + /* TODO: I/d-Cache tagmem retention has not been implementted yet, + * so i/d-cache tagmem retention is explicitly disabled */ + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE); + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE); + + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | 0x1)); + /* Enable retention when cpu sleep enable */ + REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + +static inline void rtc_cntl_ll_disable_cpu_retention(void) +{ + REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/rtc_cntl_hal.c b/components/hal/esp32s3/rtc_cntl_hal.c new file mode 100644 index 0000000000..10edc61cab --- /dev/null +++ b/components/hal/esp32s3/rtc_cntl_hal.c @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for RTC CNTL (common part) + +#include "hal/rtc_hal.h" +#include "soc/soc_caps.h" +#include "esp32s3/rom/lldesc.h" +#include "esp32s3/rom/cache.h" +#include "hal/dma_types.h" +#include "hal/assert.h" +#include "esp_attr.h" + +#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ + +typedef struct rtc_cntl_link_buf_conf { + uint32_t cfg[4]; /* 4 word for dma link buffer configuration */ +} rtc_cntl_link_buf_conf_t; + +void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) +{ + HAL_ASSERT(elem != NULL); + HAL_ASSERT(buff != NULL); + HAL_ASSERT(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN); + + lldesc_t *plink = (lldesc_t *)elem; + + plink->eof = next ? 0 : 1; + plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + plink->size = size >> 4; /* in unit of 16 bytes */ + plink->length = size >> 4; + plink->buf = buff; + plink->offset = 0; + plink->sosf = 0; + STAILQ_NEXT(plink, qe) = next; + return (void *)plink; +} + +#if SOC_PM_SUPPORT_CPU_PD + +void rtc_cntl_hal_enable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem; + + /* dma link buffer configure */ + rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; + pbuf->cfg[0] = 0; + pbuf->cfg[1] = 0; + pbuf->cfg[2] = 0; + pbuf->cfg[3] = 0xfffe0000; + + rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink); + rtc_cntl_ll_enable_cpu_retention_clock(); + rtc_cntl_ll_enable_cpu_retention(); + } + } +} + +void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + /* TODO: I/d-cache tagmem retention has not been implemented yet, + * so after the system wakes up, all the contents of i/d-cache need + * to be invalidated. */ + Cache_Invalidate_ICache_All(); + Cache_Invalidate_DCache_All(); + rtc_cntl_ll_disable_cpu_retention(); + } + } +} + +#endif // SOC_PM_SUPPORT_CPU_PD diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index 8d74f4c4cd..2f032c460d 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -14,12 +14,19 @@ #pragma once +#include "soc/soc_caps.h" #include "hal/gpio_types.h" #include "hal/rtc_cntl_ll.h" #if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 #include "hal/rtc_io_ll.h" #endif +typedef struct rtc_cntl_sleep_retent { +#if SOC_PM_SUPPORT_CPU_PD + void *cpu_pd_mem; /* Internal ram address for cpu retention */ +#endif // SOC_PM_SUPPORT_CPU_PD +} rtc_cntl_sleep_retent_t; + #define RTC_HAL_DMA_LINK_NODE_SIZE (16) #if SOC_PM_SUPPORT_EXT_WAKEUP @@ -48,7 +55,7 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next); void rtc_cntl_hal_enable_cpu_retention(void *addr); -#define rtc_cntl_hal_disable_cpu_retention() rtc_cntl_ll_disable_cpu_retention() +void rtc_cntl_hal_disable_cpu_retention(void *addr); /* * Enable wakeup from ULP coprocessor. diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 848c0b1e01..e20111243f 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -118,6 +118,14 @@ #define SOC_LCD_I80_BUS_WIDTH (16) /*!< Intel 8080 bus width */ #define SOC_LCD_RGB_DATA_WIDTH (16) /*!< Number of LCD data lines */ +/*-------------------------- RTC CAPS --------------------------------------*/ +#define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) +#define SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM (549) +#define SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) +#define SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) + +#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) + /*-------------------------- RTCIO CAPS --------------------------------------*/ #include "rtc_io_caps.h" @@ -210,6 +218,8 @@ #define SOC_PM_SUPPORT_BT_WAKEUP (1) +#define SOC_PM_SUPPORT_CPU_PD (1) + /*-------------------------- Flash Encryption CAPS----------------------------*/ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64)