diff --git a/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c b/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c index 7f8932a736e..c1971a97284 100644 --- a/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c +++ b/components/esp_hw_support/lowpower/port/esp32h21/sleep_clock.c @@ -30,9 +30,8 @@ esp_err_t sleep_clock_system_retention_init(void *arg) [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), I2C_ANA_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH, I2C_MST_BBPLL_STOP_FORCE_HIGH, 1, 0), .owner = ENTRY(0) }, /* Clock configuration retention */ [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(6), DR_REG_PCR_BASE, DR_REG_PCR_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(7), PCR_RESET_EVENT_BYPASS_REG, PCR_RESET_EVENT_BYPASS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, - [8] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(8), PCR_BUS_CLK_UPDATE_REG, PCR_BUS_CLOCK_UPDATE, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, - [9] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(9), PCR_BUS_CLK_UPDATE_REG, 0x0, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(7), PCR_BUS_CLK_UPDATE_REG, PCR_BUS_CLOCK_UPDATE, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [8] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(8), PCR_BUS_CLK_UPDATE_REG, 0x0, PCR_BUS_CLOCK_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; 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); @@ -77,7 +76,7 @@ bool clock_domain_pd_allowed(void) * 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. */ - sleep_retention_module_bitmap_t modem_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; + __attribute__((unused)) sleep_retention_module_bitmap_t modem_clk_dep_modules = (sleep_retention_module_bitmap_t){ .bitmap = { 0 } }; #if SOC_BT_SUPPORTED modem_clk_dep_modules.bitmap[SLEEP_RETENTION_MODULE_BLE_MAC >> 5] |= BIT(SLEEP_RETENTION_MODULE_BLE_MAC % 32); modem_clk_dep_modules.bitmap[SLEEP_RETENTION_MODULE_BT_BB >> 5] |= BIT(SLEEP_RETENTION_MODULE_BT_BB % 32); diff --git a/components/esp_hw_support/lowpower/port/esp32h21/sleep_cpu.c b/components/esp_hw_support/lowpower/port/esp32h21/sleep_cpu.c index 356ccaa310f..31bdb58bc36 100644 --- a/components/esp_hw_support/lowpower/port/esp32h21/sleep_cpu.c +++ b/components/esp_hw_support/lowpower/port/esp32h21/sleep_cpu.c @@ -23,6 +23,7 @@ #include "soc/soc_caps.h" #include "soc/cache_reg.h" #include "soc/intpri_reg.h" +#include "soc/plic_reg.h" #include "soc/rtc_periph.h" #include "esp_private/esp_pmu.h" #include "esp_private/sleep_cpu.h" @@ -57,6 +58,7 @@ typedef struct { RvCoreCriticalSleepFrame *critical_frame; RvCoreNonCriticalSleepFrame *non_critical_frame; cpu_domain_dev_sleep_frame_t *intpri_frame; + cpu_domain_dev_sleep_frame_t *plic_frame; cpu_domain_dev_sleep_frame_t *cache_config_frame; } retent; } sleep_cpu_retention_t; @@ -119,6 +121,17 @@ static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); } +static inline void * cpu_domain_plic_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 }, + { .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 }, + { .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 }, + { .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + static esp_err_t esp_sleep_cpu_retention_init_impl(void) { if (s_cpu_retention.retent.critical_frame == NULL) { @@ -150,6 +163,13 @@ static esp_err_t esp_sleep_cpu_retention_init_impl(void) } s_cpu_retention.retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; } + if (s_cpu_retention.retent.plic_frame == NULL) { + void *frame = cpu_domain_plic_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + s_cpu_retention.retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } return ESP_OK; err: esp_sleep_cpu_retention_deinit(); @@ -175,6 +195,10 @@ static esp_err_t esp_sleep_cpu_retention_deinit_impl(void) heap_caps_free((void *)s_cpu_retention.retent.cache_config_frame); s_cpu_retention.retent.cache_config_frame = NULL; } + if (s_cpu_retention.retent.plic_frame) { + heap_caps_free((void *)s_cpu_retention.retent.plic_frame); + s_cpu_retention.retent.plic_frame = NULL; + } return ESP_OK; } @@ -437,6 +461,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0); uint32_t mstatus = save_mstatus_and_disable_global_int(); + cpu_domain_dev_regs_save(s_cpu_retention.retent.plic_frame); cpu_domain_dev_regs_save(s_cpu_retention.retent.intpri_frame); cpu_domain_dev_regs_save(s_cpu_retention.retent.cache_config_frame); RvCoreNonCriticalSleepFrame *frame = rv_core_noncritical_regs_save(); @@ -455,6 +480,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin rv_core_noncritical_regs_restore(frame); cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame); cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame); + cpu_domain_dev_regs_restore(s_cpu_retention.retent.plic_frame); restore_mstatus(mstatus); return err; } @@ -472,9 +498,10 @@ esp_err_t esp_sleep_cpu_retention_deinit(void) bool cpu_domain_pd_allowed(void) { return (s_cpu_retention.retent.critical_frame != NULL) && \ - (s_cpu_retention.retent.non_critical_frame != NULL) && \ - (s_cpu_retention.retent.intpri_frame != NULL) && \ - (s_cpu_retention.retent.cache_config_frame != NULL); + (s_cpu_retention.retent.non_critical_frame != NULL) && \ + (s_cpu_retention.retent.intpri_frame != NULL) && \ + (s_cpu_retention.retent.cache_config_frame != NULL) && \ + (s_cpu_retention.retent.plic_frame != NULL); } esp_err_t sleep_cpu_configure(bool light_sleep_enable) diff --git a/components/esp_hw_support/port/esp32h21/pmu_sleep.c b/components/esp_hw_support/port/esp32h21/pmu_sleep.c index ef3a39c7b80..7ff14ab998e 100644 --- a/components/esp_hw_support/port/esp32h21/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32h21/pmu_sleep.c @@ -25,6 +25,8 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_sleep"); +static bool s_pmu_sleep_regdma_backup_enabled; + #define HP(state) (PMU_MODE_HP_ ## state) #define LP(state) (PMU_MODE_LP_ ## state) @@ -51,17 +53,23 @@ uint32_t get_slp_lp_dbias(void) void pmu_sleep_enable_regdma_backup(void) { - assert(PMU_instance()->hal); - /* entry 0, 1, 2 is used by pmu HP_SLEEP and HP_ACTIVE, HP_SLEEP - * and HP_MODEM or HP_MODEM and HP_ACTIVE states switching, - * respectively. entry 3 is reserved, not used yet! */ - pmu_hal_hp_set_sleep_active_backup_enable(PMU_instance()->hal); + if (!s_pmu_sleep_regdma_backup_enabled){ + assert(PMU_instance()->hal); + /* entry 0, 1, 2 is used by pmu HP_SLEEP and HP_ACTIVE, HP_SLEEP + * and HP_MODEM or HP_MODEM and HP_ACTIVE states switching, + * respectively. entry 3 is reserved, not used yet! */ + pmu_hal_hp_set_sleep_active_backup_enable(PMU_instance()->hal); + s_pmu_sleep_regdma_backup_enabled = true; + } } void pmu_sleep_disable_regdma_backup(void) { - assert(PMU_instance()->hal); - pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal); + if (s_pmu_sleep_regdma_backup_enabled) { + assert(PMU_instance()->hal); + pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal); + s_pmu_sleep_regdma_backup_enabled = false; + } } uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk_src_t slowclk_src, uint32_t slowclk_period, uint32_t fastclk_period) diff --git a/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h b/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h index b3c44c0a8de..288c7682a14 100644 --- a/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32h21/private_include/pmu_param.h @@ -41,7 +41,8 @@ extern "C" { #define PMU_HP_DBIAS_LIGHTSLEEP_0V6_DEFAULT 1 #define PMU_LP_DBIAS_SLEEP_0V7_DEFAULT 6 -#define PMU_REGDMA_S2A_WORK_TIME_US 390 +#define PMU_REGDMA_S2A_WORK_TIME_US 520 +#define PMU_REGDMA_A2S_WORK_TIME_US 180 // FOR DEEPSLEEP #define PMU_HP_XPD_DEEPSLEEP 0 @@ -558,7 +559,7 @@ typedef struct pmu_sleep_machine_constant { .power_supply_wait_time_us = 2, \ .power_up_wait_time_us = 2, \ .regdma_s2a_work_time_us = PMU_REGDMA_S2A_WORK_TIME_US, \ - .regdma_a2s_work_time_us = 190, \ + .regdma_a2s_work_time_us = PMU_REGDMA_A2S_WORK_TIME_US, \ .xtal_wait_stable_time_us = 250, \ .pll_wait_stable_time_us = 1 \ } \ diff --git a/components/soc/esp32h21/include/soc/system_periph_retention.h b/components/soc/esp32h21/include/soc/system_periph_retention.h new file mode 100644 index 00000000000..ff57203d2fa --- /dev/null +++ b/components/soc/esp32h21/include/soc/system_periph_retention.h @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2025 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 4 +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/esp32h21/system_retention_periph.c b/components/soc/esp32h21/system_retention_periph.c new file mode 100644 index 00000000000..e32b2b2d98a --- /dev/null +++ b/components/soc/esp32h21/system_retention_periph.c @@ -0,0 +1,128 @@ +/* + * SPDX-FileCopyrightText: 2025 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() (((INTMTX_CORE0_CLOCK_GATE_REG - DR_REG_INTMTX_BASE) / 4) + 1) +const regdma_entries_config_t intr_matrix_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0), DR_REG_INTMTX_BASE, DR_REG_INTMTX_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_EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL_REG / HP_SYSTEM_SRAM_USAGE_CONF_REG + * HP_SYSTEM_SEC_DPA_CONF_REG / HP_SYSTEM_CPU_PERI_TIMEOUT_CONF_REG + * HP_SYSTEM_HP_PERI_TIMEOUT_CONF_REG /HP_SYSTEM_ROM_TABLE_LOCK_REG /HP_SYSTEM_ROM_TABLE_REG + */ +#define HP_SYSTEM_RETENTION_REGS_CNT 7 +#define HP_SYSTEM_RETENTION_REGS_BASE (HP_SYSTEM_EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL_REG) +static const uint32_t hp_system_regs_map[4] = {0x64f, 0x0, 0x0, 0x0}; +const regdma_entries_config_t hp_system_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_HPSYS_LINK(0x00), \ + HP_SYSTEM_RETENTION_REGS_BASE, HP_SYSTEM_RETENTION_REGS_BASE, \ + HP_SYSTEM_RETENTION_REGS_CNT, 0, 0, \ + hp_system_regs_map[0], hp_system_regs_map[1], \ + hp_system_regs_map[2], hp_system_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ +}; +_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() (SOC_GPIO_PIN_COUNT) +#define N_REGS_IOMUX_1() (SOC_GPIO_PIN_COUNT) +#define N_REGS_IOMUX_2() (((GPIO_FUNC124_IN_SEL_CFG_REG - GPIO_FUNC0_IN_SEL_CFG_REG) / 4) + 1) +#define N_REGS_IOMUX_3() (SOC_GPIO_PIN_COUNT) +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), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, 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_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_3(), 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) - DR_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) - DR_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), DR_REG_SPI_MEM_BASE(1), DR_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), DR_REG_SPI_MEM_BASE(0), DR_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");