diff --git a/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py b/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py index 6fe3bcc0de..e9d9633e33 100644 --- a/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py +++ b/components/app_update/test_apps/test_app_update/pytest_app_update_ut.py @@ -24,7 +24,7 @@ def test_app_update(dut: Dut) -> None: @pytest.mark.supported_targets -# TODO: [ESP32C61] IDF-9245, IDF-9247, IDF-10983 +# TODO: [ESP32C61] IDF-9245, IDF-10983 @pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C61 has not supported deep sleep') @pytest.mark.generic @pytest.mark.parametrize( diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index c3cdf5062f..167d828de2 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -273,4 +273,13 @@ menu "Hardware Settings" config ESP_SPI_BUS_LOCK_FUNCS_IN_IRAM bool default n + + config ESP_CLK_RC32K_NOT_TO_USE + bool + default y if IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C61 + default n + help + Due to the poor low-temperature characteristics of + RC32K (it cannot operate below -40 degrees Celsius), + please avoid using it whenever possible endmenu diff --git a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c index 19c936fda5..d4a682ea3e 100644 --- a/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c @@ -19,7 +19,7 @@ esp_err_t sleep_clock_system_retention_init(void *arg) [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */ [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP - [2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 74, 0, 0, 0xffffffff, 0xffffffff, 0x7f7, 0x0), .owner = ENTRY(0) | ENTRY(1) }, + [2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 75, 0, 0, 0xffffffff, 0xffffffff, 0x200007f7, 0x0), .owner = ENTRY(0) | ENTRY(1) }, #endif }; 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); diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c new file mode 100644 index 0000000000..0dbe9445ee --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_private/sleep_clock.h" +#include "soc/pcr_reg.h" +#include "modem/modem_syscon_reg.h" + +static const char *TAG = "sleep_clock"; + +esp_err_t sleep_clock_system_retention_init(void *arg) +{ + const static sleep_retention_entries_config_t pcr_regs_retention[] = { + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 63, 0, 0, 0xfd73ffff, 0xfdffffff, 0xe001, 0x0), .owner = ENTRY(0) | ENTRY(1) }, + }; + + 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; +} + +#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE +esp_err_t sleep_clock_modem_retention_init(void *arg) +{ + #define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1) + + const static sleep_retention_entries_config_t modem_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM SYSCON */ + }; + + esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_MODEM_CLK, SLEEP_RETENTION_MODULE_CLOCK_MODEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (SYSCON) retention, 1 level priority"); + ESP_LOGI(TAG, "Modem Power, Clock and Reset sleep retention initialization"); + return ESP_OK; +} +#endif + +bool clock_domain_pd_allowed(void) +{ + const uint32_t inited_modules = sleep_retention_get_inited_modules(); + const uint32_t created_modules = sleep_retention_get_created_modules(); + const uint32_t sys_clk_dep_modules = (const uint32_t) (BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH)); + + /* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed + * through MODEM_SYSCON, when one or more MODEMs are initialized, it is + * necessary to check the state of CLOCK_MODEM to determine MODEM domain on + * or off. The clock and reset of digital peripherals are managed through + * PCR, with TOP domain similar to MODEM domain. */ + uint32_t modem_clk_dep_modules = 0; +#if SOC_WIFI_SUPPORTED + modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_WIFI_MAC) | BIT(SLEEP_RETENTION_MODULE_WIFI_BB); +#endif +#if SOC_BT_SUPPORTED + modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_BLE_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB); +#endif +#if SOC_IEEE802154_SUPPORTED + modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_802154_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB); +#endif + + uint32_t mask = 0; + if (inited_modules & sys_clk_dep_modules) { + mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM); + } + if (inited_modules & modem_clk_dep_modules) { +#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM); +#endif + } + return ((inited_modules & mask) == (created_modules & mask)); +} + +ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) +{ + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + }; + sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param); + +#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE + init_param = (sleep_retention_module_init_param_t) { + .cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } }, + .attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE + }; + sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param); +#endif + return ESP_OK; +} diff --git a/components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c b/components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c new file mode 100644 index 0000000000..ac2f45da7b --- /dev/null +++ b/components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "esp_attr.h" +#include "esp_check.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#include "soc/spi_mem_reg.h" +#include "esp_private/startup_internal.h" + +static const char *TAG = "sleep_mmu"; + +typedef struct { + uint32_t start; + uint32_t end; +} mmu_domain_dev_regs_region_t; + +typedef struct { + mmu_domain_dev_regs_region_t *region; + int region_num; + uint32_t *regs_frame; +} mmu_domain_dev_sleep_frame_t; + +/** + * Internal structure which holds all requested light sleep mmu retention parameters + */ +typedef struct { + struct { + mmu_domain_dev_sleep_frame_t *mmu_table_frame; + } retent; +} sleep_mmu_retention_t; + +static DRAM_ATTR __attribute__((unused)) sleep_mmu_retention_t s_mmu_retention; + +static void * mmu_domain_dev_sleep_frame_alloc_and_init(const mmu_domain_dev_regs_region_t *regions, const int region_num) +{ + const int region_sz = sizeof(mmu_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(mmu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame) { + mmu_domain_dev_regs_region_t *region = (mmu_domain_dev_regs_region_t *)(frame + sizeof(mmu_domain_dev_sleep_frame_t)); + memcpy(region, regions, region_num * sizeof(mmu_domain_dev_regs_region_t)); + void *regs_frame = frame + sizeof(mmu_domain_dev_sleep_frame_t) + region_sz; + memset(regs_frame, 0, regs_frame_sz); + *(mmu_domain_dev_sleep_frame_t *)frame = (mmu_domain_dev_sleep_frame_t) { + .region = region, + .region_num = region_num, + .regs_frame = (uint32_t *)regs_frame + }; + } + return frame; +} + +static inline void * mmu_domain_mmu_table_sleep_frame_alloc_and_init(void) +{ + #define MMU_TABLE_SIZE (512 * 4) + const static mmu_domain_dev_regs_region_t regions[] = { + { .start = SPI_MEM_MMU_ITEM_CONTENT_REG(0), .end = SPI_MEM_MMU_ITEM_CONTENT_REG(0) + MMU_TABLE_SIZE} + }; + return mmu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static IRAM_ATTR void mmu_domain_dev_regs_save(mmu_domain_dev_sleep_frame_t *frame) +{ + assert(frame); + mmu_domain_dev_regs_region_t *region = frame->region; + uint32_t *regs_frame = frame->regs_frame; + + int offset = 0; + for (int i = 0; i < frame->region_num; i++) { + for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) { + REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset); + regs_frame[offset++] = REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0)); + } + } +} + +static IRAM_ATTR void mmu_domain_dev_regs_restore(mmu_domain_dev_sleep_frame_t *frame) +{ + assert(frame); + mmu_domain_dev_regs_region_t *region = frame->region; + uint32_t *regs_frame = frame->regs_frame; + + int offset = 0; + for (int i = 0; i < frame->region_num; i++) { + for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) { + REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset); + REG_WRITE(SPI_MEM_MMU_ITEM_CONTENT_REG(0),regs_frame[offset++]); + } + } +} + +IRAM_ATTR void esp_sleep_mmu_retention(bool backup_or_restore) +{ + if (backup_or_restore) { + mmu_domain_dev_regs_save(s_mmu_retention.retent.mmu_table_frame); + } else { + mmu_domain_dev_regs_restore(s_mmu_retention.retent.mmu_table_frame); + } +} + +static esp_err_t esp_sleep_mmu_retention_deinit_impl(void) +{ + if (s_mmu_retention.retent.mmu_table_frame) { + heap_caps_free((void *)s_mmu_retention.retent.mmu_table_frame); + s_mmu_retention.retent.mmu_table_frame = NULL; + } + return ESP_OK; +} + +static esp_err_t esp_sleep_mmu_retention_init_impl(void) +{ + if (s_mmu_retention.retent.mmu_table_frame == NULL) { + void *frame = mmu_domain_mmu_table_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + s_mmu_retention.retent.mmu_table_frame = (mmu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +err: + esp_sleep_mmu_retention_deinit(); + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_sleep_mmu_retention_init(void) +{ + return esp_sleep_mmu_retention_init_impl(); +} + +esp_err_t esp_sleep_mmu_retention_deinit(void) +{ + return esp_sleep_mmu_retention_deinit_impl(); +} + +bool mmu_domain_pd_allowed(void) +{ + return (s_mmu_retention.retent.mmu_table_frame != NULL); +} + +ESP_SYSTEM_INIT_FN(sleep_mmu_startup_init, SECONDARY, BIT(0), 108) +{ + esp_err_t ret; + ret = esp_sleep_mmu_retention_init(); + if (ret != ESP_OK) { + ESP_EARLY_LOGW(TAG, "Failed to enable TOP power down during light sleep."); + } + return ESP_OK; +} diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index a4ae39be5c..63066d6302 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -423,7 +423,7 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) ( (last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST : (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL : -#if !SOC_CLK_RC32K_NOT_TO_USE +#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE (last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K : #endif (last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K : @@ -431,7 +431,7 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl esp_sleep_pd_domain_t pu_domain = (esp_sleep_pd_domain_t) ( (src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST : (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL : -#if !SOC_CLK_RC32K_NOT_TO_USE +#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE (src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K : #endif (src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K : @@ -486,7 +486,7 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module) esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) ( (last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST : (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL : -#if !SOC_CLK_RC32K_NOT_TO_USE +#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE (last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K : #endif (last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K : diff --git a/components/esp_hw_support/port/esp32c61/CMakeLists.txt b/components/esp_hw_support/port/esp32c61/CMakeLists.txt index 45cdcebb73..0e720dc029 100644 --- a/components/esp_hw_support/port/esp32c61/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c61/CMakeLists.txt @@ -17,7 +17,7 @@ if(NOT BOOTLOADER_BUILD) endif() -# TODO: [ESP32C61] IDF-9250 +# TODO: [ESP32C61] IDF-9304 if(CONFIG_IDF_TARGET_ESP32C61) list(REMOVE_ITEM srcs "sar_periph_ctrl.c" diff --git a/components/esp_hw_support/port/esp32c61/private_include/pmu_bit_defs.h b/components/esp_hw_support/port/esp32c61/private_include/pmu_bit_defs.h index 686855458a..842b61fbe1 100644 --- a/components/esp_hw_support/port/esp32c61/private_include/pmu_bit_defs.h +++ b/components/esp_hw_support/port/esp32c61/private_include/pmu_bit_defs.h @@ -10,8 +10,6 @@ extern "C" { #endif -// TODO: IDF-9247 - #define PMU_EXT0_WAKEUP_EN BIT(0) #define PMU_EXT1_WAKEUP_EN BIT(1) #define PMU_GPIO_WAKEUP_EN BIT(2) diff --git a/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h index 237684c2ed..8b9b6468dd 100644 --- a/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c61/private_include/pmu_param.h @@ -476,12 +476,12 @@ typedef struct pmu_sleep_machine_constant { .reset_wait_time_us = 1, \ .power_supply_wait_time_us = 20, \ .power_up_wait_time_us = 2, \ - .regdma_s2m_work_time_us = 172, \ - .regdma_s2a_work_time_us = 480, \ - .regdma_m2a_work_time_us = 278, \ - .regdma_a2s_work_time_us = 382, \ - .regdma_rf_on_work_time_us = 70, \ - .regdma_rf_off_work_time_us = 23, \ + .regdma_s2m_work_time_us = 270, \ + .regdma_s2a_work_time_us = 666, \ + .regdma_m2a_work_time_us = 296, \ + .regdma_a2s_work_time_us = 586, \ + .regdma_rf_on_work_time_us = 138, \ + .regdma_rf_off_work_time_us = 28, \ .xtal_wait_stable_time_us = 250, \ .pll_wait_stable_time_us = 1 \ } \ diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 484af78847..44edbe8cfd 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -157,8 +157,8 @@ #define DEFAULT_SLEEP_OUT_OVERHEAD_US (318) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56) #elif CONFIG_IDF_TARGET_ESP32C61 -#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318) -#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56) +#define DEFAULT_SLEEP_OUT_OVERHEAD_US (1148) //TODO: PM-231 +#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (107) #elif CONFIG_IDF_TARGET_ESP32H2 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (118) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9) @@ -189,8 +189,12 @@ #endif #if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD +#if CONFIG_IDF_TARGET_ESP32C61 +#define SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US (1232) +#elif CONFIG_IDF_TARGET_ESP32C5 #define SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US (1220) #endif +#endif // Minimal amount of time we can sleep for #define LIGHT_SLEEP_MIN_TIME_US 200 @@ -705,7 +709,7 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags) #if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP sleep_console_usj_pad_restore(); #endif -#if !CONFIG_IDF_TARGET_ESP32C61 +#if !CONFIG_IDF_TARGET_ESP32C61 // TODO: IDF-9304 sar_periph_ctrl_power_enable(); #endif #if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL @@ -2359,7 +2363,7 @@ static uint32_t get_power_down_flags(void) } #endif #if SOC_PM_SUPPORT_RC32K_PD -#if !SOC_CLK_RC32K_NOT_TO_USE +#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE if (s_config.domain[ESP_PD_DOMAIN_RC32K].pd_option != ESP_PD_OPTION_ON) { pd_flags |= PMU_SLEEP_PD_RC32K; } diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 561baa29d6..ba656cb3f1 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -82,10 +82,12 @@ SECONDARY: 103: esp_security_init in components/esp_security/src/init.c on BIT(0 SECONDARY: 105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0) SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c on BIT(0) SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c6/sleep_clock.c on BIT(0) +SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c on BIT(0) SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32h2/sleep_clock.c on BIT(0) SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c on BIT(0) SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c on BIT(0) +SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c on BIT(0) # app_trace has to be initialized before systemview SECONDARY: 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES diff --git a/components/hal/esp32c61/include/hal/pau_ll.h b/components/hal/esp32c61/include/hal/pau_ll.h new file mode 100644 index 0000000000..6a19d22a7b --- /dev/null +++ b/components/hal/esp32c61/include/hal/pau_ll.h @@ -0,0 +1,172 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-C61 PAU(Power Assist Unit) register operations + +#pragma once + +#include +#include +#include "soc/soc.h" +#include "soc/pau_reg.h" +#include "soc/pau_struct.h" +#include "soc/pcr_struct.h" +#include "hal/pau_types.h" +#include "hal/assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void pau_ll_enable_bus_clock(bool enable) +{ + if (enable) { + PCR.regdma_conf.regdma_clk_en = 1; + PCR.regdma_conf.regdma_rst_en = 0; + } else { + PCR.regdma_conf.regdma_clk_en = 0; + PCR.regdma_conf.regdma_rst_en = 1; + } +} + +static inline uint32_t pau_ll_get_regdma_backup_flow_error(pau_dev_t *dev) +{ + return dev->regdma_conf.flow_err; +} + +static inline void pau_ll_select_regdma_entry_link(pau_dev_t *dev, int link) +{ + dev->regdma_conf.link_sel = link; +} + +static inline void pau_ll_set_regdma_entry_link_backup_direction(pau_dev_t *dev, bool to_mem) +{ + dev->regdma_conf.to_mem = to_mem ? 1 : 0; +} + +static inline void pau_ll_set_regdma_entry_link_backup_start_enable(pau_dev_t *dev) +{ + dev->regdma_conf.start = 1; +} + +static inline void pau_ll_set_regdma_entry_link_backup_start_disable(pau_dev_t *dev) +{ + dev->regdma_conf.start = 0; +} + +static inline void pau_ll_set_regdma_select_wifimac_link(pau_dev_t *dev) +{ + dev->regdma_conf.sel_mac = 1; +} + +static inline void pau_ll_set_regdma_deselect_wifimac_link(pau_dev_t *dev) +{ + dev->regdma_conf.sel_mac = 0; +} + +static inline void pau_ll_set_regdma_wifimac_link_backup_direction(pau_dev_t *dev, bool to_mem) +{ + dev->regdma_conf.to_mem_mac = to_mem ? 1 : 0; +} + +static inline void pau_ll_set_regdma_wifimac_link_backup_start_enable(pau_dev_t *dev) +{ + dev->regdma_conf.start_mac = 1; +} + +static inline void pau_ll_set_regdma_wifimac_link_backup_start_disable(pau_dev_t *dev) +{ + dev->regdma_conf.start_mac = 0; +} + +static inline void pau_ll_set_regdma_link0_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_0_addr.val = (uint32_t)link_addr; +} + +static inline void pau_ll_set_regdma_link1_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_1_addr.val = (uint32_t)link_addr; +} + +static inline void pau_ll_set_regdma_link2_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_2_addr.val = (uint32_t)link_addr; +} + +static inline void pau_ll_set_regdma_link3_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_3_addr.val = (uint32_t)link_addr; +} + +static inline void pau_ll_set_regdma_wifimac_link_addr(pau_dev_t *dev, void *link_addr) +{ + dev->regdma_link_mac_addr.val = (uint32_t)link_addr; +} + +static inline uint32_t pau_ll_get_regdma_current_link_addr(pau_dev_t *dev) +{ + return dev->regdma_current_link_addr.val; +} + +static inline uint32_t pau_ll_get_regdma_backup_addr(pau_dev_t *dev) +{ + return dev->regdma_backup_addr.val; +} + +static inline uint32_t pau_ll_get_regdma_memory_addr(pau_dev_t *dev) +{ + return dev->regdma_mem_addr.val; +} + +static inline uint32_t pau_ll_get_regdma_intr_raw_signal(pau_dev_t *dev) +{ + return dev->int_raw.val; +} + +static inline uint32_t pau_ll_get_regdma_intr_status(pau_dev_t *dev) +{ + return dev->int_st.val; +} + +static inline void pau_ll_set_regdma_backup_done_intr_enable(pau_dev_t *dev) +{ + dev->int_ena.done_int_ena = 1; +} + +static inline void pau_ll_set_regdma_backup_done_intr_disable(pau_dev_t *dev) +{ + dev->int_ena.done_int_ena = 0; +} + +static inline void pau_ll_set_regdma_backup_error_intr_enable(pau_dev_t *dev, bool enable) +{ + dev->int_ena.error_int_ena = enable; +} + +static inline void pau_ll_clear_regdma_backup_done_intr_state(pau_dev_t *dev) +{ + dev->int_clr.done_int_clr = 1; +} + +static inline void pau_ll_clear_regdma_backup_error_intr_state(pau_dev_t *dev) +{ + dev->int_clr.error_int_clr = 1; +} + +static inline void pau_ll_set_regdma_link_wait_retry_count(pau_dev_t *dev, int count) +{ + dev->regdma_bkp_conf.link_tout_thres = count; +} + +static inline void pau_ll_set_regdma_link_wait_read_interval(pau_dev_t *dev, int interval) +{ + dev->regdma_bkp_conf.read_interval = interval; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c61/include/hal/timer_ll.h b/components/hal/esp32c61/include/hal/timer_ll.h index b8b56465dc..85d9335f2b 100644 --- a/components/hal/esp32c61/include/hal/timer_ll.h +++ b/components/hal/esp32c61/include/hal/timer_ll.h @@ -24,6 +24,7 @@ extern "C" { // Get timer group register base address with giving group number #define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1)) #define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id)) +#define TIMER_LL_SLEEP_RETENTION_MODULE_ID(group_id) ((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER: SLEEP_RETENTION_MODULE_TG1_TIMER) #define TIMER_LL_ETM_TASK_TABLE(group, timer, task) \ (uint32_t [2][1][GPTIMER_ETM_TASK_MAX]){{{ \ diff --git a/components/hal/esp32c61/include/hal/uart_ll.h b/components/hal/esp32c61/include/hal/uart_ll.h index f6599d94bd..2a6a014108 100644 --- a/components/hal/esp32c61/include/hal/uart_ll.h +++ b/components/hal/esp32c61/include/hal/uart_ll.h @@ -64,6 +64,10 @@ extern "C" { ((hw) == &UART1) ? PCR.uart1_##reg_suffix.uart1_##field_suffix : \ PCR.uart2_##reg_suffix.uart2_##field_suffix) +// UART sleep retention module +#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \ + (uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1) + // Define UART interrupts typedef enum { UART_INTR_RXFIFO_FULL = (0x1 << 0), diff --git a/components/hal/esp32c61/pau_hal.c b/components/hal/esp32c61/pau_hal.c index 21a393a634..335188cc5a 100644 --- a/components/hal/esp32c61/pau_hal.c +++ b/components/hal/esp32c61/pau_hal.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -// The HAL layer for PAU (ESP32-C61 specific part) - #include "soc/soc.h" #include "esp_attr.h" #include "hal/pau_hal.h" @@ -59,3 +57,14 @@ void IRAM_ATTR pau_hal_stop_regdma_extra_link(pau_hal_context_t *hal) pau_ll_select_regdma_entry_link(hal->dev, 0); /* restore link select to default */ pau_ll_clear_regdma_backup_done_intr_state(hal->dev); } + +void pau_hal_set_regdma_work_timeout(pau_hal_context_t *hal, uint32_t loop_num, uint32_t time) +{ +} + +void pau_hal_set_regdma_wait_timeout(pau_hal_context_t *hal, int count, int interval) +{ + HAL_ASSERT(count > 0 && interval > 0); + pau_ll_set_regdma_link_wait_retry_count(hal->dev, count); + pau_ll_set_regdma_link_wait_read_interval(hal->dev, interval); +} diff --git a/components/hal/esp32p4/include/hal/pau_ll.h b/components/hal/esp32p4/include/hal/pau_ll.h index 8ecde59e79..40ef69d180 100644 --- a/components/hal/esp32p4/include/hal/pau_ll.h +++ b/components/hal/esp32p4/include/hal/pau_ll.h @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -// The LL layer for ESP32-C6 PAU(Power Assist Unit) register operations +// The LL layer for ESP32-P4 PAU(Power Assist Unit) register operations #pragma once diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 0ac05a0ce3..7435729305 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1359,10 +1359,6 @@ config SOC_CLK_LP_FAST_SUPPORT_XTAL bool default y -config SOC_CLK_RC32K_NOT_TO_USE - bool - default y - config SOC_RCC_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 2cad5a7f94..9f3de8cea2 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -579,7 +579,6 @@ #define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ #define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */ #define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */ -#define SOC_CLK_RC32K_NOT_TO_USE (1) /*!< Due to the poor low-temperature characteristics of RC32K (it cannot operate below -40 degrees Celsius), please avoid using it whenever possible. */ #define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */ /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 4a904e190f..82abba0a68 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -131,6 +131,10 @@ config SOC_REG_I2C_SUPPORTED bool default y +config SOC_PAU_SUPPORTED + bool + default y + config SOC_LIGHT_SLEEP_SUPPORTED bool default y @@ -671,6 +675,14 @@ config SOC_TIMER_GROUP_SUPPORT_RC_FAST bool default y +config SOC_TIMER_SUPPORT_SLEEP_RETENTION + bool + default y + +config SOC_MWDT_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_EFUSE_DIS_DOWNLOAD_ICACHE bool default n @@ -771,6 +783,10 @@ config SOC_UART_SUPPORT_WAKEUP_INT bool default y +config SOC_UART_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y @@ -827,6 +843,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_PM_SUPPORT_TOP_PD + bool + default y + config SOC_PM_SUPPORT_HP_AON_PD bool default y @@ -849,16 +869,32 @@ config SOC_PM_CPU_RETENTION_BY_SW config SOC_PM_MODEM_RETENTION_BY_REGDMA bool - default n + default y config SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN bool default y +config SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD + bool + default y + config SOC_PM_PAU_LINK_NUM int default 4 +config SOC_PM_PAU_REGDMA_LINK_MULTI_ADDR + bool + default y + +config SOC_PM_PAU_REGDMA_LINK_WIFIMAC + bool + default y + +config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE + bool + default y + config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y @@ -879,10 +915,6 @@ config SOC_CLK_LP_FAST_SUPPORT_XTAL bool default y -config SOC_CLK_RC32K_NOT_TO_USE - bool - default y - config SOC_RCC_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32c61/include/soc/reg_base.h b/components/soc/esp32c61/include/soc/reg_base.h index c3c302b592..5fe48114a2 100644 --- a/components/soc/esp32c61/include/soc/reg_base.h +++ b/components/soc/esp32c61/include/soc/reg_base.h @@ -35,7 +35,7 @@ #define DR_REG_PAU_BASE 0x60093000 #define DR_REG_HP_SYSTEM_BASE 0x60095000 #define DR_REG_PCR_BASE 0x60096000 -#define DR_REG_TEE_REG_BASE 0x60098000 +#define DR_REG_TEE_BASE 0x60098000 #define DR_REG_HP_APM_BASE 0x60099000 #define DR_REG_MISC_BASE 0x6009F000 #define DR_REG_MODEM0_BASE 0x600A0000 @@ -61,4 +61,3 @@ #define DR_REG_INTPRI_BASE 0x600C5000 #define DR_REG_CACHE_BASE 0x600C8000 #define DR_REG_CLINT_M_BASE 0x20000000 -#define DR_REG_TEE_BASE DR_REG_TEE_REG_BASE diff --git a/components/soc/esp32c61/include/soc/retention_periph_defs.h b/components/soc/esp32c61/include/soc/retention_periph_defs.h index d5d03d00e7..0904c5a2a2 100644 --- a/components/soc/esp32c61/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c61/include/soc/retention_periph_defs.h @@ -18,23 +18,29 @@ typedef enum periph_retention_module { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1, SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2, - - /* modem module, which includes WiFi, BLE and 802.15.4 */ - SLEEP_RETENTION_MODULE_WIFI_MAC = 10, - SLEEP_RETENTION_MODULE_WIFI_BB = 11, - SLEEP_RETENTION_MODULE_BLE_MAC = 12, - SLEEP_RETENTION_MODULE_BT_BB = 13, - SLEEP_RETENTION_MODULE_802154_MAC = 14, - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_SYS_PERIPH = 16, - - SLEEP_RETENTION_MODULE_GDMA_CH0 = 24, - SLEEP_RETENTION_MODULE_GDMA_CH1 = 25, - SLEEP_RETENTION_MODULE_GDMA_CH2 = 26, - SLEEP_RETENTION_MODULE_I2C0 = 27, + * TEE, APM, IOMUX, SPIMEM, SysTimer, etc.. */ + SLEEP_RETENTION_MODULE_SYS_PERIPH = 3, + /* Timer Group by target */ + SLEEP_RETENTION_MODULE_TG0_WDT = 4, + SLEEP_RETENTION_MODULE_TG1_WDT = 5, + SLEEP_RETENTION_MODULE_TG0_TIMER = 6, + SLEEP_RETENTION_MODULE_TG1_TIMER = 7, + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_GDMA_CH0 = 8, + SLEEP_RETENTION_MODULE_GDMA_CH1 = 9, + SLEEP_RETENTION_MODULE_GDMA_CH2 = 10, + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_I2C0 = 12, + SLEEP_RETENTION_MODULE_UART0 = 14, + SLEEP_RETENTION_MODULE_UART1 = 15, + /* Modem module, which includes WiFi, BLE and 802.15.4 */ + SLEEP_RETENTION_MODULE_WIFI_MAC = 26, + SLEEP_RETENTION_MODULE_WIFI_BB = 27, + SLEEP_RETENTION_MODULE_BLE_MAC = 28, + SLEEP_RETENTION_MODULE_BT_BB = 29, + SLEEP_RETENTION_MODULE_802154_MAC = 30, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -42,26 +48,44 @@ typedef enum periph_retention_module_bitmap { /* clock module, which includes system and modem */ SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM), SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM), - + /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, + * TEE, APM, IOMUX, SPIMEM, SysTimer, etc.. */ + SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), + /* Timer Group by target*/ + SLEEP_RETENTION_MODULE_BM_TASK_WDT = BIT(SLEEP_RETENTION_MODULE_TG0_WDT), + SLEEP_RETENTION_MODULE_BM_INT_WDT = BIT(SLEEP_RETENTION_MODULE_TG1_WDT), + SLEEP_RETENTION_MODULE_BM_TG0_TIMER = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER), + SLEEP_RETENTION_MODULE_BM_TG1_TIMER = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER), + /* GDMA by channel */ + SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), + SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), + SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), + /* MISC Peripherals */ + SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), + SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0), + SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1), /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC), SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB), SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC), SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB), SLEEP_RETENTION_MODULE_BM_802154_MAC = BIT(SLEEP_RETENTION_MODULE_802154_MAC), - - /* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM, - * TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */ - SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH), - - SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0), - SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1), - SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2), - SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), - SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; +#define TOP_DOMAIN_PERIPHERALS_BM ( SLEEP_RETENTION_MODULE_BM_SYS_PERIPH \ + | SLEEP_RETENTION_MODULE_BM_TASK_WDT \ + | SLEEP_RETENTION_MODULE_BM_INT_WDT \ + | SLEEP_RETENTION_MODULE_BM_TG0_TIMER \ + | SLEEP_RETENTION_MODULE_BM_TG1_TIMER \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \ + | SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \ + | SLEEP_RETENTION_MODULE_BM_I2C0 \ + | SLEEP_RETENTION_MODULE_BM_UART0 \ + | SLEEP_RETENTION_MODULE_BM_UART1 \ + ) + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 62086ac264..b962eb25bf 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -59,7 +59,7 @@ #define SOC_REG_I2C_SUPPORTED 1 // \#define SOC_ETM_SUPPORTED 0 // \#define SOC_SDIO_SLAVE_SUPPORTED 0 -// \#define SOC_PAU_SUPPORTED 0 +#define SOC_PAU_SUPPORTED 1 #define SOC_LIGHT_SLEEP_SUPPORTED 1 #define SOC_DEEP_SLEEP_SUPPORTED 1 #define SOC_PM_SUPPORTED 1 @@ -349,10 +349,12 @@ #define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54) #define SOC_TIMER_GROUP_SUPPORT_XTAL (1) #define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1) +#define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1) // #define SOC_TIMER_SUPPORT_ETM (1) /*--------------------------- WATCHDOG CAPS ---------------------------------------*/ // #define SOC_MWDT_SUPPORT_XTAL (1) +#define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- eFuse CAPS----------------------------*/ #define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 0 @@ -391,7 +393,7 @@ #define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ #define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ - +#define SOC_UART_SUPPORT_SLEEP_RETENTION (1) // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) @@ -423,7 +425,7 @@ #define SOC_PM_SUPPORT_RC32K_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) -// \#define SOC_PM_SUPPORT_TOP_PD (1) +#define SOC_PM_SUPPORT_TOP_PD (1) #define SOC_PM_SUPPORT_HP_AON_PD (1) #define SOC_PM_SUPPORT_MAC_BB_PD (1) #define SOC_PM_SUPPORT_RTC_PERIPH_PD (1) @@ -433,9 +435,15 @@ #define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE #define SOC_PM_CPU_RETENTION_BY_SW (1) -#define SOC_PM_MODEM_RETENTION_BY_REGDMA (0) +#define SOC_PM_MODEM_RETENTION_BY_REGDMA (1) #define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1) -#define SOC_PM_PAU_LINK_NUM (4) +#define SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD (1) + +#define SOC_PM_PAU_LINK_NUM (4) +#define SOC_PM_PAU_REGDMA_LINK_MULTI_ADDR (1) +#define SOC_PM_PAU_REGDMA_LINK_WIFIMAC (1) + +#define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) @@ -444,7 +452,6 @@ #define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ #define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */ #define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */ -#define SOC_CLK_RC32K_NOT_TO_USE (1) /*!< Due to the poor low-temperature characteristics of RC32K (it cannot operate below -40 degrees Celsius), please avoid using it whenever possible. */ #define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */ /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ diff --git a/components/soc/esp32c61/include/soc/system_periph_retention.h b/components/soc/esp32c61/include/soc/system_periph_retention.h new file mode 100644 index 0000000000..83304975fb --- /dev/null +++ b/components/soc/esp32c61/include/soc/system_periph_retention.h @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc_caps.h" +#include "soc/regdma.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Provide access to interrupt matrix configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define INT_MTX_RETENTION_LINK_LEN 1 +extern const regdma_entries_config_t intr_matrix_regs_retention[INT_MTX_RETENTION_LINK_LEN]; + +/** + * @brief Provide access to hp_system configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define HP_SYSTEM_RETENTION_LINK_LEN 1 +extern const regdma_entries_config_t hp_system_regs_retention[HP_SYSTEM_RETENTION_LINK_LEN]; + +/** + * @brief Provide access to TEE_APM configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define TEE_APM_RETENTION_LINK_LEN 2 +extern const regdma_entries_config_t tee_apm_regs_retention[TEE_APM_RETENTION_LINK_LEN]; +#define TEE_APM_HIGH_PRI_RETENTION_LINK_LEN 1 +extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH_PRI_RETENTION_LINK_LEN]; + +/** + * @brief Provide access to IOMUX configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define IOMUX_RETENTION_LINK_LEN 7 +extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN]; + +/** + * @brief Provide access to spimem configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define SPIMEM_RETENTION_LINK_LEN 8 +extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN]; + +/** + * @brief Provide access to systimer configuration registers retention + * context definition. + * + * This is an internal function of the sleep retention driver, and is not + * useful for external use. + */ +#define SYSTIMER_RETENTION_LINK_LEN 19 +extern const regdma_entries_config_t systimer_regs_retention[SYSTIMER_RETENTION_LINK_LEN]; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32c61/include/soc/tee_reg.h b/components/soc/esp32c61/include/soc/tee_reg.h index 2a9cca5270..52d683f8a6 100644 --- a/components/soc/esp32c61/include/soc/tee_reg.h +++ b/components/soc/esp32c61/include/soc/tee_reg.h @@ -769,9 +769,9 @@ extern "C" { * Version control register */ #define TEE_DATE 0x0FFFFFFFU -#define TEE_DATE_REG_M (TEE_DATE_REG_V << TEE_DATE_REG_S) -#define TEE_DATE_REG_V 0x0FFFFFFFU -#define TEE_DATE_REG_S 0 +#define TEE_DATE_M (TEE_DATE_REG_V << TEE_DATE_REG_S) +#define TEE_DATE_V 0x0FFFFFFFU +#define TEE_DATE_S 0 #ifdef __cplusplus } diff --git a/components/soc/esp32c61/system_retention_periph.c b/components/soc/esp32c61/system_retention_periph.c new file mode 100644 index 0000000000..b9ae7fb1a7 --- /dev/null +++ b/components/soc/esp32c61/system_retention_periph.c @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/regdma.h" +#include "soc/system_periph_retention.h" +#include "soc/timer_periph.h" +#include "soc/uart_reg.h" +#include "soc/systimer_reg.h" +#include "soc/timer_group_reg.h" +#include "soc/spi_mem_reg.h" +#include "soc/hp_system_reg.h" +#include "soc/tee_reg.h" +#include "soc/hp_apm_reg.h" +#include "soc/gpio_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/interrupt_matrix_reg.h" + +/* Interrupt Matrix Registers Context */ +#define N_REGS_INTR_MATRIX() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1) +const regdma_entries_config_t intr_matrix_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0), DR_REG_INTERRUPT_CORE0_BASE, DR_REG_INTERRUPT_CORE0_BASE, N_REGS_INTR_MATRIX(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* intr matrix */ +}; +_Static_assert(ARRAY_SIZE(intr_matrix_regs_retention) == INT_MTX_RETENTION_LINK_LEN, "Inconsistent INT_MTX retention link length definitions"); + +/* HP System Registers Context */ +#define N_REGS_HP_SYSTEM() (((HP_SYSTEM_CLOCK_GATE_REG - DR_REG_HP_SYSTEM_BASE) / 4) + 1) +const regdma_entries_config_t hp_system_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_HPSYS_LINK(0), DR_REG_HP_SYSTEM_BASE, DR_REG_HP_SYSTEM_BASE, N_REGS_HP_SYSTEM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* hp system */ +}; +_Static_assert(ARRAY_SIZE(hp_system_regs_retention) == HP_SYSTEM_RETENTION_LINK_LEN, "Inconsistent HP_SYSTEM retention link length definitions"); + +/* TEE/APM Registers Context */ +#define N_REGS_TEE() (((TEE_CLOCK_GATE_REG - DR_REG_TEE_BASE) / 4) + 1) +#define N_REGS_APM() (((HP_APM_CLOCK_GATE_REG - DR_REG_HP_APM_BASE) / 4) + 1) +const regdma_entries_config_t tee_apm_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(0), DR_REG_HP_APM_BASE, DR_REG_HP_APM_BASE, N_REGS_APM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* apm */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(1), DR_REG_TEE_BASE, DR_REG_TEE_BASE, N_REGS_TEE(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* tee */ +}; +const regdma_entries_config_t tee_apm_highpri_regs_retention[] = { + [0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TEEAPM_LINK(2), TEE_M4_MODE_CTRL_REG, 0x0, 0xffffffff, 1, 0), .owner = ENTRY(2) } +}; +_Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN) && (ARRAY_SIZE(tee_apm_highpri_regs_retention) == TEE_APM_HIGH_PRI_RETENTION_LINK_LEN), "Inconsistent TEE_APM retention link length definitions"); + +/* IO MUX Registers Context */ +#define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_U_PAD_SPID - REG_IO_MUX_BASE) / 4) + 1) +#define N_REGS_IOMUX_1() (((GPIO_FUNC21_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) +#define N_REGS_IOMUX_2() (((GPIO_FUNC121_IN_SEL_CFG_REG - GPIO_FUNC0_IN_SEL_CFG_REG) / 4) + 1) +#define N_REGS_IOMUX_3() (((GPIO_PIN21_REG - GPIO_PIN0_REG) / 4) + 1) +#define N_REGS_IOMUX_4() (1) +#define N_REGS_IOMUX_5() (1) +#define N_REGS_IOMUX_6() (1) + +const regdma_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) | ENTRY(2) }, /* io_mux */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_FUNC0_IN_SEL_CFG_REG, GPIO_FUNC0_IN_SEL_CFG_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_STATUS_REG, GPIO_STATUS_REG, N_REGS_IOMUX_4(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_REG, N_REGS_IOMUX_5(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_OUT_REG, GPIO_OUT_REG, N_REGS_IOMUX_6(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } +}; +_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions"); + +/* Memory SPI Registers Context */ +#define N_REGS_SPI1_MEM_0() (((SPI_SMEM_DDR_REG(1) - REG_SPI_MEM_BASE(1)) / 4) + 1) +#define N_REGS_SPI1_MEM_1() (1) +#define N_REGS_SPI1_MEM_2() (1) +#define N_REGS_SPI0_MEM_0() (((SPI_SMEM_DDR_REG(0) - REG_SPI_MEM_BASE(0)) / 4) + 1) +#define N_REGS_SPI0_MEM_1() (((SPI_SMEM_AC_REG(0) - SPI_FMEM_PMS0_ATTR_REG(0)) / 4) + 1) +#define N_REGS_SPI0_MEM_2() (1) +#define N_REGS_SPI0_MEM_3() (((SPI_MEM_XTS_PSEUDO_ROUND_CONF_REG(0) - SPI_MEM_MMU_POWER_CTRL_REG(0)) / 4) + 1) +const regdma_entries_config_t flash_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), REG_SPI_MEM_BASE(1), REG_SPI_MEM_BASE(1), N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi1_mem */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI_MEM_TIMING_CALI_REG(1), SPI_MEM_TIMING_CALI_REG(1), N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI_MEM_CLOCK_GATE_REG(1), SPI_MEM_CLOCK_GATE_REG(1), N_REGS_SPI1_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + + /* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */ + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x03), REG_SPI_MEM_BASE(0), REG_SPI_MEM_BASE(0), N_REGS_SPI0_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi0_mem */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), SPI_FMEM_PMS0_ATTR_REG(0), SPI_FMEM_PMS0_ATTR_REG(0), N_REGS_SPI0_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLOCK_GATE_REG(0), N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + /* Note: spimem register should set update reg to make the configuration take effect */ + [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SPIMEM_LINK(0x07), SPI_MEM_TIMING_CALI_REG(0), SPI_MEM_TIMING_CALI_UPDATE, SPI_MEM_TIMING_CALI_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } +}; +_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions"); + +/* Systimer Registers Context */ +#define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1) +const regdma_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) | ENTRY(2) }, /* 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) | ENTRY(2) }, + [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) | ENTRY(2) }, + [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) | ENTRY(2) }, + + [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) | ENTRY(2) }, + [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) | ENTRY(2) }, + [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) | ENTRY(2) }, + [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) | ENTRY(2) }, + + [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) | ENTRY(2) }, /* 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) | ENTRY(2) }, + [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) | ENTRY(2) }, + [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) | ENTRY(2) }, + + [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) | ENTRY(2) }, + [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) | ENTRY(2) }, + + [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) | ENTRY(2) }, + [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) | ENTRY(2) }, + + [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) | ENTRY(2) }, + + [17] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x11), SYSTIMER_CONF_REG, SYSTIMER_CONF_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* 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) | ENTRY(2) } /* Systimer intr enable */ +}; +_Static_assert(ARRAY_SIZE(systimer_regs_retention) == SYSTIMER_RETENTION_LINK_LEN, "Inconsistent Systimer retention link length definitions"); diff --git a/components/soc/esp32c61/timer_periph.c b/components/soc/esp32c61/timer_periph.c index 529d5a6454..82744d00d6 100644 --- a/components/soc/esp32c61/timer_periph.c +++ b/components/soc/esp32c61/timer_periph.c @@ -22,3 +22,112 @@ const timer_group_signal_conn_t timer_group_periph_signals = { } } }; + +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_T0LOADLO_REG + * TIMG_T0LOADHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define TG_TIMER_RETENTION_REGS_CNT 7 +static const uint32_t tg_timer_regs_map[4] = {0x100000f1, 0x80000000, 0x0, 0x0}; + +const regdma_entries_config_t tg0_timer_regdma_entries[] = { + // backup stage: trigger a soft capture + [0] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x00), + TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), + .owner = TIMG_RETENTION_ENTRY + }, + // backup stage: wait for the capture done + [1] = { + .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x01), + TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), + .owner = TIMG_RETENTION_ENTRY + }, + // backup stage: save the captured counter value + // restore stage: store the captured counter value to the loader register + [2] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x02), + TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), + .owner = TIMG_RETENTION_ENTRY + }, + [3] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), + TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), + .owner = TIMG_RETENTION_ENTRY + }, + // restore stage: trigger a soft reload, so the timer can continue from where it was backed up + [4] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x04), + TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), + .owner = TIMG_RETENTION_ENTRY + }, + // backup stage: save other configuration and status registers + // restore stage: restore the configuration and status registers + [5] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x05), + TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), + TG_TIMER_RETENTION_REGS_CNT, 0, 0, + tg_timer_regs_map[0], tg_timer_regs_map[1], + tg_timer_regs_map[2], tg_timer_regs_map[3]), + .owner = TIMG_RETENTION_ENTRY + }, +}; + +const regdma_entries_config_t tg1_timer_regdma_entries[] = { + // backup stage: trigger a soft capture + [0] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x00), + TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), + .owner = TIMG_RETENTION_ENTRY + }, + // backup stage: wait for the capture done + [1] = { + .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x01), + TIMG_T0UPDATE_REG(1), 0x0, TIMG_T0_UPDATE_M, 0, 1), + .owner = TIMG_RETENTION_ENTRY + }, + // backup stage: save the captured counter value + // restore stage: store the captured counter value to the loader register + [2] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x02), + TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), + .owner = TIMG_RETENTION_ENTRY + }, + [3] = { + .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), + TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), + .owner = TIMG_RETENTION_ENTRY + }, + // restore stage: trigger a soft reload, so the timer can continue from where it was backed up + [4] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x04), + TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0), + .owner = TIMG_RETENTION_ENTRY + }, + // backup stage: save other configuration and status registers + // restore stage: restore the configuration and status registers + [5] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x05), + TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), + TG_TIMER_RETENTION_REGS_CNT, 0, 0, + tg_timer_regs_map[0], tg_timer_regs_map[1], + tg_timer_regs_map[2], tg_timer_regs_map[3]), + .owner = TIMG_RETENTION_ENTRY + }, +}; + +const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS] = { + [0] = { + .regdma_entry_array = tg0_timer_regdma_entries, + .array_size = ARRAY_SIZE(tg0_timer_regdma_entries) + }, + [1] = { + .regdma_entry_array = tg1_timer_regdma_entries, + .array_size = ARRAY_SIZE(tg1_timer_regdma_entries) + }, +}; diff --git a/components/soc/esp32c61/uart_periph.c b/components/soc/esp32c61/uart_periph.c index 4f18940705..be396c4321 100644 --- a/components/soc/esp32c61/uart_periph.c +++ b/components/soc/esp32c61/uart_periph.c @@ -5,6 +5,7 @@ */ #include "soc/uart_periph.h" +#include "soc/uart_reg.h" /* Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc @@ -108,3 +109,52 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { .irq = ETS_UART2_INTR_SOURCE, }, }; + +/** + * UART registers to be saved during sleep retention + * + * Reset TXFIFO and RXFIFO + * UART registers require set the reg_update bit to make the configuration take effect + * + * UART_INT_ENA_REG, UART_CLKDIV_SYNC_REG, UART_RX_FILT_REG, UART_CONF0_SYNC_REG, UART_CONF1_REG, + * UART_HWFC_CONF_SYNC_REG, UART_SLEEP_CONF0_REG, UART_SLEEP_CONF1_REG, UART_SLEEP_CONF2_REG, + * UART_SWFC_CONF0_SYNC_REG, UART_SWFC_CONF1_REG, UART_TXBRK_CONF_SYNC_REG, UART_IDLE_CONF_SYNC_REG, + * UART_RS485_CONF_SYNC_REG, UART_AT_CMD_PRECNT_SYNC_REG, UART_AT_CMD_POSTCNT_SYNC_REG, UART_AT_CMD_GAPTOUT_SYNC_REG, + * UART_AT_CMD_CHAR_SYNC_REG, UART_MEM_CONF_REG, UART_TOUT_CONF_SYNC_REG, UART_ID_REG + */ +#define UART_RETENTION_ADDR_MAP_REGS_CNT 21 +#define UART_RETENTION_REGS_BASE(i) UART_INT_ENA_REG(i) +static const uint32_t uart_regs_map[4] = {0x7fff6d, 0x10, 0x0, 0x0}; +#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \ + [0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_UART_LINK(0x00), \ + UART_RETENTION_REGS_BASE(uart_num), UART_RETENTION_REGS_BASE(uart_num), \ + UART_RETENTION_ADDR_MAP_REGS_CNT, 0, 0, \ + uart_regs_map[0], uart_regs_map[1], \ + uart_regs_map[2], uart_regs_map[3] \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \ + UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ + [2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \ + UART_REG_UPDATE_REG(uart_num), 0x0, \ + UART_REG_UPDATE_M, 1, 0 \ + ), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1); + +const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = { + [0] = { + .regdma_entry_array = uart0_regdma_entries, + .array_size = ARRAY_SIZE(uart0_regdma_entries), + }, + [1] = { + .regdma_entry_array = uart1_regdma_entries, + .array_size = ARRAY_SIZE(uart1_regdma_entries), + }, +}; diff --git a/components/soc/esp32c61/wdt_periph.c b/components/soc/esp32c61/wdt_periph.c index 58f1349d3d..f615401cfa 100644 --- a/components/soc/esp32c61/wdt_periph.c +++ b/components/soc/esp32c61/wdt_periph.c @@ -5,3 +5,28 @@ */ #include "soc/wdt_periph.h" + +#define N_REGS_TGWDT 6 // TIMG_WDTCONFIG0_REG ... TIMG_WDTCONFIG5_REG & TIMG_INT_ENA_TIMERS_REG + +static const regdma_entries_config_t tg0_wdt_regs_retention[] = { + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(0), TIMG_WDTCONFIG0_REG(0), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x02), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(0), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x04), TIMG_INT_ENA_TIMERS_REG(0),TIMG_INT_ENA_TIMERS_REG(0), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x05), TIMG_WDTWPROTECT_REG(0), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +static const regdma_entries_config_t tg1_wdt_regs_retention[] = { + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(1), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x01), TIMG_INT_ENA_TIMERS_REG(1),TIMG_INT_ENA_TIMERS_REG(1), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x02), TIMG_WDTCONFIG0_REG(1), TIMG_WDTCONFIG0_REG(1), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(1), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x04), TIMG_WDTFEED_REG(1), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x05), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)}, + [1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)}, +}; diff --git a/examples/system/esp_timer/main/esp_timer_example_main.c b/examples/system/esp_timer/main/esp_timer_example_main.c index e2c2d26a89..54183cb8a3 100644 --- a/examples/system/esp_timer/main/esp_timer_example_main.c +++ b/examples/system/esp_timer/main/esp_timer_example_main.c @@ -71,7 +71,8 @@ void app_main(void) int64_t t2 = esp_timer_get_time(); ESP_LOGI(TAG, "Woke up from light sleep, time since boot: %lld us", t2); - assert(llabs((t2 - t1) - 500000) < 1200); + // TODO: PM-232 + assert(((t2 - t1 - 500000) < 1000) && ((t2 - t1 - 500000) > -2000)); #endif /* Let the timer run for a little bit more */ diff --git a/examples/system/esp_timer/pytest_esp_timer.py b/examples/system/esp_timer/pytest_esp_timer.py index 595cecb7c9..98bdd1232c 100644 --- a/examples/system/esp_timer/pytest_esp_timer.py +++ b/examples/system/esp_timer/pytest_esp_timer.py @@ -81,7 +81,7 @@ def test_esp_timer(dut: Dut) -> None: logging.info('Enter sleep: {}, exit sleep: {}, slept: {}'.format( sleep_enter_time, sleep_exit_time, sleep_time)) - assert abs(sleep_time - LIGHT_SLEEP_TIME) < 1200 + assert -2000 < sleep_time - LIGHT_SLEEP_TIME < 1000 for i in range(5, 7): match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2) diff --git a/examples/system/light_sleep/pytest_light_sleep.py b/examples/system/light_sleep/pytest_light_sleep.py index 3aade876e8..698138469e 100644 --- a/examples/system/light_sleep/pytest_light_sleep.py +++ b/examples/system/light_sleep/pytest_light_sleep.py @@ -62,5 +62,6 @@ def test_light_sleep(dut: Dut) -> None: logging.info('Went to sleep again') match = dut.expect(EXIT_SLEEP_REGEX) - assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 1 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1 + # TODO: Need to support dynamically change retention overhead for chips which support pmu (PM-232) + assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 2 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1 logging.info('Woke up from timer again') diff --git a/examples/wifi/.build-test-rules.yml b/examples/wifi/.build-test-rules.yml index 16229bb7ba..17f466aaee 100644 --- a/examples/wifi/.build-test-rules.yml +++ b/examples/wifi/.build-test-rules.yml @@ -57,12 +57,22 @@ examples/wifi/itwt: examples/wifi/power_save: <<: *wifi_depends_default disable: - - if: (SOC_WIFI_SUPPORTED != 1) + - if: SOC_WIFI_SUPPORTED != 1 + - if: IDF_TARGET in ["esp32c61"] + temporary: true + reason: PM-234 disable_test: - if: IDF_TARGET == "esp32c61" temporary: true reason: lack of runners depends_components: + - esp_wifi + - esp_phy + - esp_netif + - lwip + - esp_event + - esp_coex + - wpa_supplicant - esp_driver_uart examples/wifi/wifi_aware: diff --git a/examples/wifi/power_save/README.md b/examples/wifi/power_save/README.md index 473379d265..50df4b8e6e 100644 --- a/examples/wifi/power_save/README.md +++ b/examples/wifi/power_save/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | # Wifi Power Save Example