diff --git a/components/esp_driver_gptimer/include/driver/gptimer.h b/components/esp_driver_gptimer/include/driver/gptimer.h index b9c0b8b14b..825f93db79 100644 --- a/components/esp_driver_gptimer/include/driver/gptimer.h +++ b/components/esp_driver_gptimer/include/driver/gptimer.h @@ -28,6 +28,9 @@ typedef struct { if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */ struct { uint32_t intr_shared: 1; /*!< Set true, the timer interrupt number can be shared with other peripherals */ + uint32_t backup_before_sleep: 1; /*!< If set, the driver will backup/restore the GPTimer registers before/after entering/exist sleep mode. + By this approach, the system can power off GPTimer's power domain. + This can save power, but at the expense of more RAM being consumed */ } flags; /*!< GPTimer config flags*/ } gptimer_config_t; diff --git a/components/esp_driver_gptimer/src/gptimer.c b/components/esp_driver_gptimer/src/gptimer.c index f1d4af4664..6fd66b9b95 100644 --- a/components/esp_driver_gptimer/src/gptimer.c +++ b/components/esp_driver_gptimer/src/gptimer.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,10 @@ #include "esp_clk_tree.h" #include "gptimer_priv.h" +#if GPTIMER_USE_RETENTION_LINK +#include "esp_private/sleep_retention.h" +#endif + static const char *TAG = "gptimer"; #if SOC_PERIPH_CLK_CTRL_SHARED @@ -52,6 +56,37 @@ static void gptimer_release_group_handle(gptimer_group_t *group); static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t src_clk, uint32_t resolution_hz); static void gptimer_default_isr(void *args); +#if GPTIMER_USE_RETENTION_LINK +static esp_err_t sleep_tg_timer_retention_link_cb(void *arg) +{ + uint32_t group_id = *(uint32_t *)arg; + esp_err_t err = sleep_retention_entries_create(tg_timer_regs_retention[group_id].link_list, + tg_timer_regs_retention[group_id].link_num, + REGDMA_LINK_PRI_6, + (group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + if (err == ESP_OK) { + ESP_LOGD(TAG, "Timer group %ld retention initialization", group_id); + } + ESP_RETURN_ON_ERROR(err, TAG, "Failed to create sleep retention linked list for timer group %ld", group_id); + return err; +} + +static void gptimer_create_retention_module(gptimer_group_t *group) +{ + _lock_acquire(&s_platform.mutex); + int group_id = group->group_id; + if ((group->sleep_retention_initialized == true) && (group->retention_link_created == false)) { + esp_err_t err = sleep_retention_module_allocate((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for timer group %d retention, power domain can't turn off", group_id); + } else { + group->retention_link_created = true; + } + } + _lock_release(&s_platform.mutex); +} +#endif + static esp_err_t gptimer_register_to_group(gptimer_t *timer) { gptimer_group_t *group = NULL; @@ -129,6 +164,12 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re int group_id = group->group_id; int timer_id = timer->timer_id; +#if GPTIMER_USE_RETENTION_LINK + if (config->flags.backup_before_sleep != 0) { + gptimer_create_retention_module(group); + } +#endif // GPTIMER_USE_RETENTION_LINK + // initialize HAL layer timer_hal_init(&timer->hal, group_id, timer_id); // select clock source, set clock resolution @@ -404,7 +445,6 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id) // someone acquired the group handle means we have a new object that refer to this group s_platform.group_ref_counts[group_id]++; } - _lock_release(&s_platform.mutex); if (new_group) { // !!! HARDWARE SHARED RESOURCE !!! @@ -417,7 +457,28 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id) } } ESP_LOGD(TAG, "new group (%d) @%p", group_id, group); +#if GPTIMER_USE_RETENTION_LINK + if (group->sleep_retention_initialized != true) { + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = sleep_tg_timer_retention_link_cb, + .arg = &group_id + }, + }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + esp_err_t err = sleep_retention_module_init((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER, &init_param); + + if (err == ESP_OK) { + group->sleep_retention_initialized = true; + } else { + ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for timer group %d retention", group_id); + } + } +#endif // GPTIMER_USE_RETENTION_LINK } + _lock_release(&s_platform.mutex); return group; } @@ -434,7 +495,6 @@ static void gptimer_release_group_handle(gptimer_group_t *group) do_deinitialize = true; s_platform.groups[group_id] = NULL; } - _lock_release(&s_platform.mutex); if (do_deinitialize) { // disable bus clock for the timer group @@ -443,9 +503,18 @@ static void gptimer_release_group_handle(gptimer_group_t *group) timer_ll_enable_bus_clock(group_id, false); } } +#if GPTIMER_USE_RETENTION_LINK + if (group->retention_link_created) { + sleep_retention_module_free((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + } + if (group->sleep_retention_initialized) { + sleep_retention_module_deinit((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER : SLEEP_RETENTION_MODULE_TG1_TIMER); + } +#endif free(group); ESP_LOGD(TAG, "del group (%d)", group_id); } + _lock_release(&s_platform.mutex); } static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t src_clk, uint32_t resolution_hz) diff --git a/components/esp_driver_gptimer/src/gptimer_priv.h b/components/esp_driver_gptimer/src/gptimer_priv.h index 78428ce09c..fe072c85d4 100644 --- a/components/esp_driver_gptimer/src/gptimer_priv.h +++ b/components/esp_driver_gptimer/src/gptimer_priv.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,12 +39,18 @@ extern "C" { #define GPTIMER_PM_LOCK_NAME_LEN_MAX 16 +#define GPTIMER_USE_RETENTION_LINK (SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + typedef struct gptimer_t gptimer_t; typedef struct gptimer_group_t { int group_id; portMUX_TYPE spinlock; // to protect per-group register level concurrent access gptimer_t *timers[SOC_TIMER_GROUP_TIMERS_PER_GROUP]; +#if GPTIMER_USE_RETENTION_LINK + bool sleep_retention_initialized; // mark if the retention link is initialized + bool retention_link_created; // mark if the retention link is created +#endif } gptimer_group_t; typedef enum { diff --git a/components/soc/esp32c5/beta3/timer_periph.c b/components/soc/esp32c5/beta3/timer_periph.c index 4ab27c7fdf..7036e7ca81 100644 --- a/components/soc/esp32c5/beta3/timer_periph.c +++ b/components/soc/esp32c5/beta3/timer_periph.c @@ -46,8 +46,47 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_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)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; #endif diff --git a/components/soc/esp32c5/mp/timer_periph.c b/components/soc/esp32c5/mp/timer_periph.c index 4ab27c7fdf..7036e7ca81 100644 --- a/components/soc/esp32c5/mp/timer_periph.c +++ b/components/soc/esp32c5/mp/timer_periph.c @@ -46,8 +46,47 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_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)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; #endif diff --git a/components/soc/esp32c6/timer_periph.c b/components/soc/esp32c6/timer_periph.c index 7d338258de..422b536f37 100644 --- a/components/soc/esp32c6/timer_periph.c +++ b/components/soc/esp32c6/timer_periph.c @@ -45,7 +45,46 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_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)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; diff --git a/components/soc/esp32h2/timer_periph.c b/components/soc/esp32h2/timer_periph.c index 7d338258de..422b536f37 100644 --- a/components/soc/esp32h2/timer_periph.c +++ b/components/soc/esp32h2/timer_periph.c @@ -45,7 +45,46 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG + * TIMG_T0ALARMLO_REG + * TIMG_T0ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 5 +static const uint32_t tg_timer_regs_map[4] = {0x10000031, 0x80000000, 0, 0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_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)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; diff --git a/components/soc/esp32p4/timer_periph.c b/components/soc/esp32p4/timer_periph.c index 043ab9764f..b94dacaefb 100644 --- a/components/soc/esp32p4/timer_periph.c +++ b/components/soc/esp32p4/timer_periph.c @@ -47,7 +47,56 @@ static const regdma_entries_config_t tg1_wdt_regs_retention[] = { [5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x04), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, }; +/* Registers in retention context: + * TIMG_T0CONFIG_REG / TIMG_T1CONFIG_REG + * TIMG_T0ALARMLO_REG / TIMG_T1ALARMLO_REG + * TIMG_T0ALARMHI_REG / TIMG_T1ALARMHI_REG + * TIMG_INT_ENA_TIMERS_REG + * TIMG_REGCLK_REG + */ +#define N_REGS_TG_TIMER_CFG 8 +static const uint32_t tg_timer_regs_map[4] = {0x10006231, 0x80000000, 0x0, 0x0}; + +const regdma_entries_config_t tg0_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x02), TIMG_T1UPDATE_REG(0), TIMG_T1_UPDATE, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x03), TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x04), TIMG_T1UPDATE_REG(0), 0x0, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x05), TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x06), TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x07), TIMG_T1LO_REG(0), TIMG_T1LOADLO_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x08), TIMG_T1HI_REG(0), TIMG_T1LOADHI_REG(0), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [9] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x09), TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [10] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x0a), TIMG_T1LOAD_REG(0), 0x1, TIMG_T1_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, +}; + +const regdma_entries_config_t tg1_timer_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x00), TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1), N_REGS_TG_TIMER_CFG, 0, 0, \ + tg_timer_regs_map[0], tg_timer_regs_map[1], tg_timer_regs_map[2], tg_timer_regs_map[3]), .owner = ENTRY(0) | ENTRY(2) + }, + [1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01), TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x02), TIMG_T1UPDATE_REG(1), TIMG_T1_UPDATE, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [3] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x03), TIMG_T0UPDATE_REG(1), 0x0, TIMG_T0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [4] = { .config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x04), TIMG_T1UPDATE_REG(1), 0x0, TIMG_T1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, + [5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x05), TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x06), TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x07), TIMG_T1LO_REG(1), TIMG_T1LOADLO_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x08), TIMG_T1HI_REG(1), TIMG_T1LOADHI_REG(1), 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, + [9] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x09), TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, + [10] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x0a), TIMG_T1LOAD_REG(1), 0x1, TIMG_T1_LOAD_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)}, }; + +const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS] = { + [0] = {tg0_timer_regs_retention, ARRAY_SIZE(tg0_timer_regs_retention)}, + [1] = {tg1_timer_regs_retention, ARRAY_SIZE(tg1_timer_regs_retention)}, +}; diff --git a/components/soc/include/soc/timer_periph.h b/components/soc/include/soc/timer_periph.h index 1da11986e7..1d7cd219b3 100644 --- a/components/soc/include/soc/timer_periph.h +++ b/components/soc/include/soc/timer_periph.h @@ -36,6 +36,7 @@ typedef struct { } tg_reg_ctx_link_t; extern const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS]; +extern const tg_reg_ctx_link_t tg_timer_regs_retention[SOC_TIMER_GROUPS]; #endif #ifdef __cplusplus