From f1beed90ff63d28b73c3e72c580be67153591a16 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 15 Jan 2024 11:49:10 +0800 Subject: [PATCH] feat(esp_hw_support): support esp32p4 sleep clock retention --- .../port/esp32p4/clock_retention_init.c | 33 +++ .../system_peripheral_retention_init.c | 214 ++++++++++++++++++ components/esp_hw_support/sleep_modes.c | 29 ++- .../esp_hw_support/sleep_system_peripheral.c | 4 + components/esp_pm/Kconfig | 4 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32p4/include/soc/soc_caps.h | 4 +- 7 files changed, 278 insertions(+), 14 deletions(-) create mode 100644 components/esp_hw_support/port/esp32p4/clock_retention_init.c create mode 100644 components/esp_hw_support/port/esp32p4/system_peripheral_retention_init.c diff --git a/components/esp_hw_support/port/esp32p4/clock_retention_init.c b/components/esp_hw_support/port/esp32p4/clock_retention_init.c new file mode 100644 index 0000000000..b9fc4d7667 --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/clock_retention_init.c @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_private/sleep_clock.h" +#include "soc/hp_sys_clkrst_reg.h" + +static __attribute__((unused)) const char *TAG = "sleep_clock"; + +esp_err_t sleep_clock_system_retention_init(void) +{ + #define N_REGS_PCR() (((HP_SYS_CLKRST_HPCORE_WDT_RESET_SOURCE0_REG - DR_REG_HP_SYS_CLKRST_BASE) / 4) + 1) + + const static sleep_retention_entries_config_t pcr_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0x0), DR_REG_HP_SYS_CLKRST_BASE, DR_REG_HP_SYS_CLKRST_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) }, /* pcr */ + [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0x01), HP_SYS_CLKRST_ROOT_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE_M, 1, 0), .owner = ENTRY(0) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(0x02), HP_SYS_CLKRST_ROOT_CLK_CTRL0_REG, 0x0, HP_SYS_CLKRST_REG_SOC_CLK_DIV_UPDATE_M, 1, 0), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0x03), HP_SYS_CLKRST_PERI_CLK_CTRL02_REG, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE_M, 1, 0), .owner = ENTRY(0) }, + [4] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(0x04), HP_SYS_CLKRST_PERI_CLK_CTRL02_REG, 0x0, HP_SYS_CLKRST_REG_SDIO_LS_CLK_EDGE_CFG_UPDATE_M, 1, 0), .owner = ENTRY(0) }, + }; + + esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention"); + ESP_LOGI(TAG, "System Power, Clock and Reset sleep retention initialization"); + return ESP_OK; +} + +void sleep_clock_system_retention_deinit(void) +{ + sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM); +} diff --git a/components/esp_hw_support/port/esp32p4/system_peripheral_retention_init.c b/components/esp_hw_support/port/esp32p4/system_peripheral_retention_init.c new file mode 100644 index 0000000000..83ff04175c --- /dev/null +++ b/components/esp_hw_support/port/esp32p4/system_peripheral_retention_init.c @@ -0,0 +1,214 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_check.h" + +#include "esp_private/startup_internal.h" +#include "esp_private/sleep_retention.h" +#include "esp_private/sleep_clock.h" + +#include "soc/cache_reg.h" +#include "soc/gpio_reg.h" +#include "soc/hp_system_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/interrupt_core0_reg.h" +#include "soc/interrupt_core1_reg.h" +#include "hal/mwdt_ll.h" +#include "soc/pau_reg.h" +#include "soc/spi_mem_reg.h" +#include "soc/systimer_reg.h" +#include "soc/timer_group_reg.h" +#include "soc/uart_reg.h" + +static __attribute__((unused)) const char *TAG = "sleep_sys_periph"; + +#define SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT (REGDMA_LINK_PRI_6) + + +esp_err_t sleep_sys_periph_intr_matrix_retention_init(void) +{ + #define N_REGS_INTR_CORE0() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1) + #define N_REGS_INTR_CORE1() (((INTERRUPT_CORE1_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE1_BASE) / 4) + 1) + + const static sleep_retention_entries_config_t intr_matrix_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0x00), DR_REG_INTERRUPT_CORE0_BASE, DR_REG_INTERRUPT_CORE0_BASE, N_REGS_INTR_CORE0(), 0, 0), .owner = ENTRY(0) }, /* intr matrix */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0x01), DR_REG_INTERRUPT_CORE1_BASE, DR_REG_INTERRUPT_CORE1_BASE, N_REGS_INTR_CORE1(), 0, 0), .owner = ENTRY(0) } /* intr matrix */ + }; + + esp_err_t err = sleep_retention_entries_create(intr_matrix_regs_retention, ARRAY_SIZE(intr_matrix_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_INTR_MATRIX); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (Interrupt matrix) retention"); + ESP_LOGI(TAG, "Interrupt Matrix sleep retention initialization"); + return ESP_OK; +} + + +esp_err_t sleep_sys_periph_l2_cache_retention_init(void) +{ + #define N_REGS_L2_CACHE() (((CACHE_L2_CACHE_DATA_MEM_POWER_CTRL_REG - CACHE_L2_CACHE_CTRL_REG) / 4) + 1) + + const static sleep_retention_entries_config_t l2_cache_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_HPSYS_LINK(0), CACHE_L2_CACHE_CTRL_REG, CACHE_L2_CACHE_CTRL_REG, N_REGS_L2_CACHE(), 0, 0), .owner = ENTRY(0) } /* hp system */ + }; + + esp_err_t err = sleep_retention_entries_create(l2_cache_regs_retention, ARRAY_SIZE(l2_cache_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_L2_CACHE); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (L2 Cache) retention"); + ESP_LOGI(TAG, "L2 Cache sleep retention initialization"); + return ESP_OK; +} + +esp_err_t sleep_sys_periph_hp_system_retention_init(void) +{ + #define N_REGS_HP_SYSTEM() (((HP_SYSTEM_AHB2AXI_BRESP_ERR_INT_ENA_REG - DR_REG_HP_SYS_BASE) / 4) + 1) + + const static sleep_retention_entries_config_t hp_system_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_HPSYS_LINK(0), DR_REG_HP_SYS_BASE, DR_REG_HP_SYS_BASE, N_REGS_HP_SYSTEM(), 0, 0), .owner = ENTRY(0) } /* hp system */ + }; + + esp_err_t err = sleep_retention_entries_create(hp_system_regs_retention, ARRAY_SIZE(hp_system_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_HP_SYSTEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (HP system) retention"); + ESP_LOGI(TAG, "HP System sleep retention initialization"); + return ESP_OK; +} + +esp_err_t sleep_sys_periph_uart0_retention_init(void) +{ + #define N_REGS_UART() (((UART_CLK_CONF_REG(0) - REG_UART_BASE(0)) / 4) + 1) + + const static sleep_retention_entries_config_t uart_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), REG_UART_BASE(0), REG_UART_BASE(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) }, /* uart */ + /* Note: uart register should set update reg to make the configuration take effect */ + [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_UART_LINK(0x01), UART_REG_UPDATE_REG(0), UART_REG_UPDATE, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_UART_LINK(0x02), UART_REG_UPDATE_REG(0), 0x0, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) } + }; + + esp_err_t err = sleep_retention_entries_create(uart_regs_retention, ARRAY_SIZE(uart_regs_retention), REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_UART0); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (UART) retention"); + ESP_LOGI(TAG, "UART sleep retention initialization"); + return ESP_OK; +} + +esp_err_t sleep_sys_periph_tg0_retention_init(void) +{ + #define N_REGS_TG0() (((TIMG_REGCLK_REG(0) - REG_TIMG_BASE(0)) / 4) + 1) + + const static sleep_retention_entries_config_t tg_regs_retention[] = { + /*Timer group0 backup. T0_wdt should get of write project firstly. wdt used by RTOS.*/ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) }, /* TG0 */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x01), REG_TIMG_BASE(0), REG_TIMG_BASE(0), N_REGS_TG0(), 0, 0), .owner = ENTRY(0) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x02), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x03), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x04), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) }, + [5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_TIMG_LINK(0x05), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TIMG_LINK(0x06), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) }, + [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TIMG_LINK(0x07), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) }, + }; + + esp_err_t err = sleep_retention_entries_create(tg_regs_retention, ARRAY_SIZE(tg_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_TG0); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (Timer Group0) retention"); + ESP_LOGI(TAG, "Timer Group0 sleep retention initialization"); + return ESP_OK; +} + +esp_err_t sleep_sys_periph_iomux_retention_init(void) +{ + #define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_U_PAD_GPIO56 - REG_IO_MUX_BASE) / 4) + 1) + #define N_REGS_IOMUX_1() (((GPIO_ZERO_DET1_FILTER_CNT_REG - DR_REG_GPIO_BASE) / 4) + 1) + + const static sleep_retention_entries_config_t iomux_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) }, /* io_mux */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) }, + }; + + esp_err_t err = sleep_retention_entries_create(iomux_regs_retention, ARRAY_SIZE(iomux_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_IOMUX); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (IO Matrix) retention"); + ESP_LOGI(TAG, "IO Matrix sleep retention initialization"); + return ESP_OK; +} + +esp_err_t sleep_sys_periph_spimem_retention_init(void) +{ + #define N_REGS_SPI1_MEM_0() (((SPI1_MEM_C_SUS_STATUS_REG - DR_REG_FLASH_SPI1_BASE) / 4) + 1) + #define N_REGS_SPI1_MEM_1() (((SPI1_MEM_C_DDR_REG - SPI1_MEM_C_INT_ENA_REG) / 4) + 1) + #define N_REGS_SPI1_MEM_2() (1) + #define N_REGS_SPI1_MEM_3() (1) + + #define N_REGS_SPI0_MEM_0() ((SPI_MEM_C_SMEM_DDR_REG - DR_REG_FLASH_SPI0_BASE) / 4 + 1) + #define N_REGS_SPI0_MEM_1() (((SPI_MEM_C_SMEM_AC_REG - SPI_MEM_C_FMEM__PMS0_ATTR_REG) / 4) + 1) + #define N_REGS_SPI0_MEM_2() (1) + #define N_REGS_SPI0_MEM_3() (((SPI_MEM_C_DATE_REG - SPI_MEM_C_MMU_POWER_CTRL_REG) / 4) + 1) + + const static sleep_retention_entries_config_t spimem_regs_retention[] = { + /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), DR_REG_FLASH_SPI1_BASE, DR_REG_FLASH_SPI1_BASE, N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi1_mem */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI1_MEM_C_INT_ENA_REG, SPI1_MEM_C_INT_ENA_REG, N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI_REG, N_REGS_SPI1_MEM_2(), 0, 0), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x03), SPI1_MEM_C_CLOCK_GATE_REG, SPI1_MEM_C_CLOCK_GATE_REG, N_REGS_SPI1_MEM_3(), 0, 0), .owner = ENTRY(0) }, + + /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */ + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_C_FMEM__PMS0_ATTR_REG, SPI_MEM_C_FMEM__PMS0_ATTR_REG, N_REGS_SPI0_MEM_1(), 0, 0), .owner = ENTRY(0) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) }, + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_C_MMU_POWER_CTRL_REG, SPI_MEM_C_MMU_POWER_CTRL_REG, N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) } + }; + + esp_err_t err = sleep_retention_entries_create(spimem_regs_retention, ARRAY_SIZE(spimem_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SPIMEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (SPI mem) retention"); + ESP_LOGI(TAG, "SPI Mem sleep retention initialization"); + return ESP_OK; +} + +esp_err_t sleep_sys_periph_systimer_retention_init(void) +{ + #define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1) + + const static sleep_retention_entries_config_t systimer_regs_retention[] = { + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x00), SYSTIMER_UNIT0_OP_REG, SYSTIMER_TIMER_UNIT0_UPDATE_M, SYSTIMER_TIMER_UNIT0_UPDATE_M, 0, 1), .owner = ENTRY(0) }, /* Systimer */ + [1] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_SYSTIMER_LINK(0x01), SYSTIMER_UNIT0_OP_REG, SYSTIMER_TIMER_UNIT0_VALUE_VALID, SYSTIMER_TIMER_UNIT0_VALUE_VALID, 0, 1), .owner = ENTRY(0) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x02), SYSTIMER_UNIT0_VALUE_HI_REG, SYSTIMER_UNIT0_LOAD_HI_REG, 2, 0, 0), .owner = ENTRY(0) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x03), SYSTIMER_UNIT0_LOAD_REG, SYSTIMER_TIMER_UNIT0_LOAD_M, SYSTIMER_TIMER_UNIT0_LOAD_M, 1, 0), .owner = ENTRY(0) }, + + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x04), SYSTIMER_UNIT1_OP_REG, SYSTIMER_TIMER_UNIT1_UPDATE_M, SYSTIMER_TIMER_UNIT1_UPDATE_M, 0, 1), .owner = ENTRY(0) }, + [5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_SYSTIMER_LINK(0x05), SYSTIMER_UNIT1_OP_REG, SYSTIMER_TIMER_UNIT1_VALUE_VALID, SYSTIMER_TIMER_UNIT1_VALUE_VALID, 0, 1), .owner = ENTRY(0) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x06), SYSTIMER_UNIT1_VALUE_HI_REG, SYSTIMER_UNIT1_LOAD_HI_REG, 2, 0, 0), .owner = ENTRY(0) }, + [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x07), SYSTIMER_UNIT1_LOAD_REG, SYSTIMER_TIMER_UNIT1_LOAD_M, SYSTIMER_TIMER_UNIT1_LOAD_M, 1, 0), .owner = ENTRY(0) }, + + [8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x08), SYSTIMER_TARGET0_HI_REG, SYSTIMER_TARGET0_HI_REG, N_REGS_SYSTIMER_0(), 0, 0), .owner = ENTRY(0) }, /* Systimer target value & period */ + + [9] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x09), SYSTIMER_COMP0_LOAD_REG, SYSTIMER_TIMER_COMP0_LOAD, SYSTIMER_TIMER_COMP0_LOAD, 1, 0), .owner = ENTRY(0) }, + [10] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0a), SYSTIMER_COMP1_LOAD_REG, SYSTIMER_TIMER_COMP1_LOAD, SYSTIMER_TIMER_COMP1_LOAD, 1, 0), .owner = ENTRY(0) }, + [11] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0b), SYSTIMER_COMP2_LOAD_REG, SYSTIMER_TIMER_COMP2_LOAD, SYSTIMER_TIMER_COMP2_LOAD, 1, 0), .owner = ENTRY(0) }, + + [12] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0c), SYSTIMER_TARGET0_CONF_REG, 0, SYSTIMER_TARGET0_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) }, + [13] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0d), SYSTIMER_TARGET0_CONF_REG, SYSTIMER_TARGET0_PERIOD_MODE_M, SYSTIMER_TARGET0_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) }, + + [14] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0e), SYSTIMER_TARGET1_CONF_REG, 0, SYSTIMER_TARGET1_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) }, + [15] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0f), SYSTIMER_TARGET1_CONF_REG, SYSTIMER_TARGET1_PERIOD_MODE_M, SYSTIMER_TARGET1_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) }, + + [16] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x10), SYSTIMER_TARGET2_CONF_REG, 0, SYSTIMER_TARGET2_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) }, + + [17] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x11), SYSTIMER_CONF_REG, SYSTIMER_CONF_REG, 1, 0, 0), .owner = ENTRY(0) }, /* Systimer work enable */ + [18] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x12), SYSTIMER_INT_ENA_REG, SYSTIMER_INT_ENA_REG, 1, 0, 0), .owner = ENTRY(0) } /* Systimer intr enable */ + }; + + esp_err_t err = sleep_retention_entries_create(systimer_regs_retention, ARRAY_SIZE(systimer_regs_retention), SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT, SLEEP_RETENTION_MODULE_SYSTIMER); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (SysTimer) retention"); + ESP_LOGI(TAG, "SysTimer sleep retention initialization"); + return ESP_OK; +} + +esp_err_t sleep_pau_retention_init(void) +{ + #define N_REGS_PAU() (((PAU_INT_ENA_REG - DR_REG_PAU_BASE) / 4) + 1) + + const static sleep_retention_entries_config_t pau_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PAU_LINK(0x0), DR_REG_PAU_BASE, DR_REG_PAU_BASE, N_REGS_PAU(), 0, 0), .owner = ENTRY(0) }, /* pau */ + }; + + esp_err_t err = sleep_retention_entries_create(pau_regs_retention, ARRAY_SIZE(pau_regs_retention), REGDMA_LINK_PRI_7, SLEEP_RETENTION_MODULE_REGDMA_SYSTEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PAU) retention"); + ESP_LOGI(TAG, "PAU sleep retention initialization"); + return ESP_OK; +} diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index e20f2f7d3e..b4dc4592b8 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -301,8 +301,8 @@ static void RTC_IRAM_ATTR __attribute__((used, noinline)) esp_wake_stub_start(vo /* We must have a default deep sleep wake stub entry function, which must be * located at the start address of the RTC fast memory, and its implementation - * must be simple enough to ensure that there is no litteral data before the - * wake stub entry, otherwise, the litteral data before the wake stub entry + * must be simple enough to ensure that there is no literal data before the + * wake stub entry, otherwise, the literal data before the wake stub entry * will not be CRC checked. */ static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void) { @@ -769,7 +769,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m if (!deep_sleep) { /* Enable sleep reject for faster return from this function, - * in case the wakeup is already triggerred. + * in case the wakeup is already triggered. */ reject_triggers |= sleep_modem_reject_triggers(); } @@ -1216,8 +1216,8 @@ esp_err_t esp_light_sleep_start(void) /* * Adjustment time consists of parts below: - * 1. Hardware time waiting for internal 8M oscilate clock and XTAL; - * 2. Hardware state swithing time of the rtc main state machine; + * 1. Hardware time waiting for internal 8M oscillate clock and XTAL; + * 2. Hardware state switching time of the rtc main state machine; * 3. Code execution time when clock is not stable; * 4. Code execution time which can be measured; */ @@ -1990,11 +1990,20 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_ */ #if SOC_PM_SUPPORT_TOP_PD FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) { - return (cpu_domain_pd_allowed() && \ - clock_domain_pd_allowed() && \ - peripheral_domain_pd_allowed() && \ - modem_domain_pd_allowed() && \ - s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option != ESP_PD_OPTION_ON); + bool top_pd_allowed = true; +#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP + top_pd_allowed &= cpu_domain_pd_allowed(); +#else + top_pd_allowed = false; +#endif + top_pd_allowed &= clock_domain_pd_allowed(); + top_pd_allowed &= peripheral_domain_pd_allowed(); +#if SOC_PM_SUPPORT_MODEM_PD + top_pd_allowed &= modem_domain_pd_allowed(); +#endif + top_pd_allowed &= (s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option != ESP_PD_OPTION_ON); + + return top_pd_allowed; } #endif diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 6feddc3fd8..71344a4383 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -105,6 +105,10 @@ esp_err_t sleep_sys_periph_retention_init(void) err = sleep_sys_periph_spimem_retention_init(); if(err) goto error; err = sleep_sys_periph_systimer_retention_init(); +#if SOC_PAU_IN_TOP_DOMAIN + if(err) goto error; + err = sleep_pau_retention_init(); +#endif error: return err; diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 5134b7d988..3058381fbd 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -2,7 +2,7 @@ menu "Power Management" config PM_ENABLE bool "Support for power management" # SMP FreeRTOS currently does not support power management IDF-4997 - depends on (!FREERTOS_SMP && !IDF_TARGET_ESP32P4) || __DOXYGEN__ # TODO: IDF-7527 + depends on !FREERTOS_SMP || __DOXYGEN__ default n help If enabled, application is compiled with support for power management. @@ -75,7 +75,7 @@ menu "Power Management" you can call 'gpio_sleep_sel_dis' to disable this feature on those pins. You can also keep this feature on and call 'gpio_sleep_set_direction' and 'gpio_sleep_set_pull_mode' to have a different GPIO configuration at sleep. - Waring: If you want to enable this option on ESP32, you should enable `GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL` + Warning: If you want to enable this option on ESP32, you should enable `GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL` at first, otherwise you will not be able to switch pullup/pulldown mode. config PM_SLP_DEFAULT_PARAMS_OPT diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index c71dc8331d..0318025f10 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1431,6 +1431,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_PM_SUPPORT_TOP_PD + bool + default y + config SOC_PM_SUPPORT_CNNT_PD bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 05124b04f0..2698fd2910 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -574,14 +574,14 @@ // TODO: IDF-5351 (Copy from esp32c3, need check) /*-------------------------- Power Management CAPS ----------------------------*/ #define SOC_PM_SUPPORT_EXT1_WAKEUP (1) -#define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (1) /*!