Merge branch 'fix/fix_regdma_wait_node_issue_v5.3' into 'release/v5.3'

fix(esp_driver_gptimer): do gptimer retention by timer unit rather than timer group (v5.3)

See merge request espressif/esp-idf!35358
This commit is contained in:
Jiang Jiang Jian
2024-12-09 15:27:24 +08:00
26 changed files with 395 additions and 258 deletions

View File

@ -25,6 +25,31 @@ static const char *TAG = "gptimer";
static void gptimer_default_isr(void *args);
#if GPTIMER_USE_RETENTION_LINK
static esp_err_t gptimer_create_sleep_retention_link_cb(void *timer)
{
int group_id = ((gptimer_t *)timer)->group->group_id;
int timer_id = ((gptimer_t *)timer)->timer_id;
esp_err_t err = sleep_retention_entries_create(tg_timer_reg_retention_info[group_id][timer_id].regdma_entry_array,
tg_timer_reg_retention_info[group_id][timer_id].array_size,
REGDMA_LINK_PRI_GPTIMER, tg_timer_reg_retention_info[group_id][timer_id].module);
return err;
}
static void gptimer_create_retention_module(gptimer_t *timer)
{
int group_id = timer->group->group_id;
int timer_id = timer->timer_id;
sleep_retention_module_t module = tg_timer_reg_retention_info[group_id][timer_id].module;
if ((sleep_retention_get_inited_modules() & BIT(module)) && !(sleep_retention_get_created_modules() & BIT(module))) {
if (sleep_retention_module_allocate(module) != ESP_OK) {
// even though the sleep retention module create failed, GPTimer driver should still work, so just warning here
ESP_LOGW(TAG, "create retention link failed on TimerGroup%d Timer%d, power domain won't be turned off during sleep", group_id, timer_id);
}
}
}
#endif // GPTIMER_USE_RETENTION_LINK
static esp_err_t gptimer_register_to_group(gptimer_t *timer)
{
gptimer_group_t *group = NULL;
@ -51,6 +76,24 @@ static esp_err_t gptimer_register_to_group(gptimer_t *timer)
}
}
ESP_RETURN_ON_FALSE(timer_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free timer");
#if GPTIMER_USE_RETENTION_LINK
sleep_retention_module_t module = tg_timer_reg_retention_info[group->group_id][timer_id].module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = gptimer_create_sleep_retention_link_cb,
.arg = (void *)timer
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, RMT driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed on TimerGroup%d Timer%d, power domain may be turned off during sleep", group->group_id, timer_id);
}
#endif // GPTIMER_USE_RETENTION_LINK
return ESP_OK;
}
@ -61,6 +104,15 @@ static void gptimer_unregister_from_group(gptimer_t *timer)
portENTER_CRITICAL(&group->spinlock);
group->timers[timer_id] = NULL;
portEXIT_CRITICAL(&group->spinlock);
#if GPTIMER_USE_RETENTION_LINK
sleep_retention_module_t module = tg_timer_reg_retention_info[group->group_id][timer_id].module;
if (sleep_retention_get_created_modules() & BIT(module)) {
sleep_retention_module_free(module);
}
sleep_retention_module_deinit(module);
#endif
// timer has a reference on group, release it now
gptimer_release_group_handle(group);
}
@ -108,7 +160,7 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re
#if GPTIMER_USE_RETENTION_LINK
if (config->flags.backup_before_sleep != 0) {
gptimer_create_retention_module(group);
gptimer_create_retention_module(timer);
}
#endif // GPTIMER_USE_RETENTION_LINK

View File

@ -20,35 +20,6 @@ typedef struct gptimer_platform_t {
// gptimer driver platform, it's always a singleton
static gptimer_platform_t s_platform;
#if GPTIMER_USE_RETENTION_LINK
static esp_err_t gptimer_create_sleep_retention_link_cb(void *arg)
{
gptimer_group_t *group = (gptimer_group_t *)arg;
int group_id = group->group_id;
sleep_retention_module_t module = group->sleep_retention_module;
esp_err_t err = sleep_retention_entries_create(tg_timer_reg_retention_info[group_id].regdma_entry_array,
tg_timer_reg_retention_info[group_id].array_size,
REGDMA_LINK_PRI_GPTIMER, module);
ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed");
return ESP_OK;
}
void gptimer_create_retention_module(gptimer_group_t *group)
{
sleep_retention_module_t module = group->sleep_retention_module;
_lock_acquire(&s_platform.mutex);
if (group->retention_link_created == false) {
if (sleep_retention_module_allocate(module) != ESP_OK) {
// even though the sleep retention module create failed, GPTimer driver should still work, so just warning here
ESP_LOGW(TAG, "create retention module for group %d retention, power domain can't turn off", group->group_id);
} else {
group->retention_link_created = true;
}
}
_lock_release(&s_platform.mutex);
}
#endif // GPTIMER_USE_RETENTION_LINK
gptimer_group_t *gptimer_acquire_group_handle(int group_id)
{
bool new_group = false;
@ -84,24 +55,6 @@ gptimer_group_t *gptimer_acquire_group_handle(int group_id)
timer_ll_reset_register(group_id);
}
}
#if GPTIMER_USE_RETENTION_LINK
sleep_retention_module_t module = TIMER_LL_SLEEP_RETENTION_MODULE_ID(group_id);
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = gptimer_create_sleep_retention_link_cb,
.arg = group
},
},
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) == ESP_OK) {
group->sleep_retention_module = module;
} else {
// even though the sleep retention module init failed, RMT driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
}
#endif // GPTIMER_USE_RETENTION_LINK
ESP_LOGD(TAG, "new group (%d) @%p", group_id, group);
}
@ -129,14 +82,6 @@ void gptimer_release_group_handle(gptimer_group_t *group)
timer_ll_enable_bus_clock(group_id, false);
}
}
#if GPTIMER_USE_RETENTION_LINK
if (group->sleep_retention_module) {
if (group->retention_link_created) {
sleep_retention_module_free(group->sleep_retention_module);
}
sleep_retention_module_deinit(group->sleep_retention_module);
}
#endif
free(group);
ESP_LOGD(TAG, "del group (%d)", group_id);
}

View File

@ -59,10 +59,6 @@ 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
sleep_retention_module_t sleep_retention_module; // sleep retention module
bool retention_link_created; // mark if the retention link is created
#endif
} gptimer_group_t;
typedef enum {
@ -102,7 +98,6 @@ struct gptimer_t {
gptimer_group_t *gptimer_acquire_group_handle(int group_id);
void gptimer_release_group_handle(gptimer_group_t *group);
esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t src_clk, uint32_t resolution_hz);
void gptimer_create_retention_module(gptimer_group_t *group);
#ifdef __cplusplus
}

View File

@ -269,6 +269,13 @@ void *regdma_link_new_branch_wait_default(void *backup, uint32_t value, uint32_t
*/
void *regdma_link_init(const regdma_link_config_t *config, bool branch, uint32_t module, int nentry, ...);
/**
* @brief Get REGDMA linked list node mode through configuration parameters
* @param config REGDMA linked node configuration parameters
* @return REGDMA linked list node mode
*/
regdma_link_mode_t regdma_link_get_config_mode(const regdma_link_config_t *config);
/**
* @brief Recurse the REGDMA linked list and call the hook subroutine for each node
* @param link The REGDMA linkded list head pointer

View File

@ -774,10 +774,10 @@ static void print_info_branch_continuous_wrapper(FILE *out, void *link)
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
regdma_link_branch_continuous_t *cons = __containerof(link, regdma_link_branch_continuous_t, head);
assert((cons->stat.module & (cons->stat.module - 1)) == 0);
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR,
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, restore start:%p, buff_ptr:%p\n" LOG_RESET_COLOR,
__builtin_ffs(cons->stat.module) - 1, cons->stat.id, link,
s_link_mode_str[cons->head.mode], cons->head.length, s_boolean_str[cons->head.branch], s_boolean_str[cons->head.skip_r], s_boolean_str[cons->head.skip_b], s_boolean_str[cons->head.eof],
cons->body.next,
cons->body.next[0], cons->body.next[1], cons->body.next[2], cons->body.next[3],
cons->body.backup, cons->body.restore,
cons->body.mem);
print_info_link_data(out, (const uint32_t *)cons->body.mem, head.length);
@ -788,10 +788,10 @@ static void print_info_branch_addr_map_wrapper(FILE *out, void *link)
regdma_link_head_t head = REGDMA_LINK_HEAD(link);
regdma_link_branch_addr_map_t *map = __containerof(link, regdma_link_branch_addr_map_t, head);
assert((map->stat.module & (map->stat.module - 1)) == 0);
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR,
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, restore start:%p, buff_ptr:%p, map:{%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"}\n" LOG_RESET_COLOR,
__builtin_ffs(map->stat.module) - 1, map->stat.id, link,
s_link_mode_str[map->head.mode], map->head.length, s_boolean_str[map->head.branch], s_boolean_str[map->head.skip_r], s_boolean_str[map->head.skip_b], s_boolean_str[map->head.eof],
map->body.next,
map->body.next[0], map->body.next[1], map->body.next[2], map->body.next[3],
map->body.backup, map->body.restore,
map->body.mem, map->body.map[0], map->body.map[1], map->body.map[2], map->body.map[3]);
print_info_link_data(out, (const uint32_t *)map->body.mem, head.length);
@ -800,10 +800,10 @@ static void print_info_branch_addr_map_wrapper(FILE *out, void *link)
static void print_info_branch_write_wait_wrapper(FILE *out, void *link)
{
regdma_link_branch_write_wait_t *ww = __containerof(link, regdma_link_branch_write_wait_t, head);
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:%p, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR,
fprintf(out, LOG_COLOR_I " [%02d/%04x] link_ptr:%p, head: {mode:%s len:%d branch:%s skip_r:%s skip_b:%s eof:%s}, next:{%p, %p, %p, %p}, backup start:%p, value:%"PRIx32", mask:%"PRIx32"\n" LOG_RESET_COLOR,
__builtin_ffs(ww->stat.module) - 1, ww->stat.id, link,
s_link_mode_str[ww->head.mode], ww->head.length, s_boolean_str[ww->head.branch], s_boolean_str[ww->head.skip_r], s_boolean_str[ww->head.skip_b], s_boolean_str[ww->head.eof],
ww->body.next,
ww->body.next[0], ww->body.next[1], ww->body.next[2], ww->body.next[3],
ww->body.backup, ww->body.value, ww->body.mask);
}
@ -842,3 +842,9 @@ void regdma_link_dump(FILE *out, void *link, int entry)
fprintf(out, "This REGDMA linked list is empty!\n");
}
}
regdma_link_mode_t regdma_link_get_config_mode(const regdma_link_config_t *config)
{
assert(config != NULL);
return (regdma_link_mode_t)config->head.mode;
}

View File

@ -21,6 +21,10 @@
#include "sdkconfig.h"
#include "esp_pmu.h"
#if SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
#include "soc/pmu_reg.h" // for PMU_DATE_REG, it can provide full 32 bit read and write access
#endif
static __attribute__((unused)) const char *TAG = "sleep";
struct sleep_retention_module_object {
@ -472,8 +476,9 @@ static void sleep_retention_entries_destroy(sleep_retention_module_t module)
static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entries_config_t retent[], int num, regdma_link_priority_t priority, sleep_retention_module_t module)
{
esp_err_t err = ESP_OK;
_lock_acquire_recursive(&s_retention.lock);
for (int i = num - 1; i >= 0; i--) {
for (int i = num - 1; (i >= 0) && (err == ESP_OK); i--) {
#if SOC_PM_RETENTION_HAS_CLOCK_BUG
if ((retent[i].owner > BIT(EXTRA_LINK_NUM)) && (retent[i].config.id != 0xffff)) {
_lock_release_recursive(&s_retention.lock);
@ -481,6 +486,27 @@ static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entri
return ESP_ERR_NOT_SUPPORTED;
}
#endif
#if SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
/* There is a bug in REGDMA wait mode, when two wait nodes need to wait for the
* same value (_val & _mask), the second wait node will immediately return to
* wait done, The reason is that the wait mode comparison output logic immediate
* compares the value of the previous wait register cached inside the
* digital logic before reading out he register contents specified by _backup.
*/
#define config_is_wait_mode(_config) (regdma_link_get_config_mode(_config) == REGDMA_LINK_MODE_WAIT)
if ((retent[i].config.id != 0xffff) && config_is_wait_mode(&(retent[i].config)) && (retent[i].config.id != 0xfffe)) {
uint32_t value = retent[i].config.write_wait.value;
uint32_t mask = retent[i].config.write_wait.mask;
bool skip_b = retent[i].config.head.skip_b;
bool skip_r = retent[i].config.head.skip_r;
sleep_retention_entries_config_t wait_bug_workaround[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT(0xfffe, PMU_DATE_REG, ~value, mask, skip_b, skip_r), .owner = retent[i].owner },
[1] = { .config = REGDMA_LINK_WAIT_INIT (0xfffe, PMU_DATE_REG, ~value, mask, skip_b, skip_r), .owner = retent[i].owner }
};
err = sleep_retention_entries_create_impl(wait_bug_workaround, ARRAY_SIZE(wait_bug_workaround), priority, module);
}
#endif
if (err == ESP_OK) {
void *link = sleep_retention_entries_try_create(&retent[i].config, retent[i].owner, priority, module);
if (link == NULL) {
_lock_release_recursive(&s_retention.lock);
@ -488,9 +514,12 @@ static esp_err_t sleep_retention_entries_create_impl(const sleep_retention_entri
return ESP_ERR_NO_MEM;
}
sleep_retention_entries_update(retent[i].owner, link, priority);
} else {
break;
}
}
_lock_release_recursive(&s_retention.lock);
return ESP_OK;
return err;
}
static esp_err_t sleep_retention_entries_create_bonding(regdma_link_priority_t priority, sleep_retention_module_t module)

View File

@ -24,7 +24,6 @@ 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]){{{ \

View File

@ -24,7 +24,6 @@ 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]){{{ \

View File

@ -24,7 +24,6 @@ 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][2][GPTIMER_ETM_TASK_MAX]){ \
@ -177,7 +176,7 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num,
* @param timer_num Timer index in the group
* @param en true to enable, false to disable
*/
static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en)
static inline void _timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en)
{
if (hw == &TIMERG0) {
if (timer_num == 0) {
@ -196,7 +195,7 @@ static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, boo
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define timer_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; timer_ll_enable_clock(__VA_ARGS__)
#define timer_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _timer_ll_enable_clock(__VA_ARGS__)
/**
* @brief Enable alarm event

View File

@ -24,8 +24,8 @@ typedef enum periph_retention_module {
/* 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,
SLEEP_RETENTION_MODULE_TG0_TIMER0 = 6,
SLEEP_RETENTION_MODULE_TG1_TIMER0 = 7,
/* GDMA by channel */
SLEEP_RETENTION_MODULE_GDMA_CH0 = 8,
SLEEP_RETENTION_MODULE_GDMA_CH1 = 9,
@ -54,8 +54,8 @@ typedef enum periph_retention_module_bitmap {
/* 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),
SLEEP_RETENTION_MODULE_BM_TG0_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER0),
SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER0),
/* 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),
@ -76,8 +76,8 @@ typedef enum periph_retention_module_bitmap {
#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_TG0_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \

View File

@ -80,13 +80,20 @@ const regdma_entries_config_t tg1_timer_regs_retention[] = {
[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)},
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS][SOC_TIMER_GROUP_TIMERS_PER_GROUP] = {
[0] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG0_TIMER0,
.regdma_entry_array = tg0_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer_regdma_entries)
}
},
[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG1_TIMER0,
.regdma_entry_array = tg1_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer_regdma_entries)
}
},
};
#endif

View File

@ -80,13 +80,20 @@ const regdma_entries_config_t tg1_timer_regs_retention[] = {
[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)},
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS][SOC_TIMER_GROUP_TIMERS_PER_GROUP] = {
[0] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG0_TIMER0,
.regdma_entry_array = tg0_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer_regdma_entries)
}
},
[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG1_TIMER0,
.regdma_entry_array = tg1_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer_regdma_entries)
}
},
};
#endif

View File

@ -1379,6 +1379,10 @@ config SOC_PM_PAU_LINK_NUM
int
default 4
config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
bool
default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y

View File

@ -24,8 +24,8 @@ typedef enum periph_retention_module {
/* 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,
SLEEP_RETENTION_MODULE_TG0_TIMER0 = 6,
SLEEP_RETENTION_MODULE_TG1_TIMER0 = 7,
/* GDMA by channel */
SLEEP_RETENTION_MODULE_GDMA_CH0 = 8,
SLEEP_RETENTION_MODULE_GDMA_CH1 = 9,
@ -56,8 +56,8 @@ typedef enum periph_retention_module_bitmap {
/* 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),
SLEEP_RETENTION_MODULE_BM_TG0_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER0),
SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER0),
/* 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),
@ -80,8 +80,8 @@ typedef enum periph_retention_module_bitmap {
#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_TG0_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \

View File

@ -546,6 +546,8 @@
#define SOC_PM_PAU_LINK_NUM (4)
#define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1)
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (1)

View File

@ -121,13 +121,19 @@ const regdma_entries_config_t tg1_timer_regdma_entries[] = {
},
};
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS] = {
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS][SOC_TIMER_GROUP_TIMERS_PER_GROUP] = {
[0] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG0_TIMER0,
.regdma_entry_array = tg0_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer_regdma_entries)
}
},
[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG1_TIMER0,
.regdma_entry_array = tg1_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer_regdma_entries)
}
},
};

View File

@ -1331,6 +1331,10 @@ config SOC_PM_CPU_RETENTION_BY_SW
bool
default y
config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
bool
default y
config SOC_PM_MODEM_RETENTION_BY_REGDMA
bool
default y

View File

@ -24,8 +24,8 @@ typedef enum periph_retention_module {
/* 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,
SLEEP_RETENTION_MODULE_TG0_TIMER0 = 6,
SLEEP_RETENTION_MODULE_TG1_TIMER0 = 7,
/* GDMA by channel */
SLEEP_RETENTION_MODULE_GDMA_CH0 = 8,
SLEEP_RETENTION_MODULE_GDMA_CH1 = 9,
@ -55,8 +55,8 @@ typedef enum periph_retention_module_bitmap {
/* 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),
SLEEP_RETENTION_MODULE_BM_TG0_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER0),
SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER0),
/* 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),
@ -78,8 +78,8 @@ typedef enum periph_retention_module_bitmap {
#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_TG0_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \

View File

@ -524,6 +524,9 @@
#define SOC_PM_SUPPORT_TOP_PD (1)
#define SOC_PM_PAU_LINK_NUM (4)
#define SOC_PM_CPU_RETENTION_BY_SW (1)
#define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1)
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (1)
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
#define SOC_PM_RETENTION_SW_TRIGGER_REGDMA (1) /*!< In esp32H2, regdma will power off when entering sleep */

View File

@ -121,13 +121,19 @@ const regdma_entries_config_t tg1_timer_regdma_entries[] = {
},
};
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS] = {
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS][SOC_TIMER_GROUP_TIMERS_PER_GROUP] = {
[0] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG0_TIMER0,
.regdma_entry_array = tg0_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer_regdma_entries)
}
},
[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG1_TIMER0,
.regdma_entry_array = tg1_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer_regdma_entries)
}
},
};

View File

@ -1707,6 +1707,10 @@ config SOC_CPU_IN_TOP_DOMAIN
bool
default y
config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
bool
default y
config SOC_PSRAM_VDD_POWER_MPLL
bool
default y

View File

@ -23,14 +23,16 @@ typedef enum periph_retention_module {
/* Timer Group by target*/
SLEEP_RETENTION_MODULE_TG0_WDT = 3,
SLEEP_RETENTION_MODULE_TG1_WDT = 4,
SLEEP_RETENTION_MODULE_TG0_TIMER = 5,
SLEEP_RETENTION_MODULE_TG1_TIMER = 6,
SLEEP_RETENTION_MODULE_TG0_TIMER0 = 5,
SLEEP_RETENTION_MODULE_TG0_TIMER1 = 6,
SLEEP_RETENTION_MODULE_TG1_TIMER0 = 7,
SLEEP_RETENTION_MODULE_TG1_TIMER1 = 8,
/* MISC Peripherals */
SLEEP_RETENTION_MODULE_UART0 = 7,
SLEEP_RETENTION_MODULE_UART1 = 8,
SLEEP_RETENTION_MODULE_UART2 = 9,
SLEEP_RETENTION_MODULE_UART3 = 10,
SLEEP_RETENTION_MODULE_UART4 = 11,
SLEEP_RETENTION_MODULE_UART0 = 9,
SLEEP_RETENTION_MODULE_UART1 = 10,
SLEEP_RETENTION_MODULE_UART2 = 11,
SLEEP_RETENTION_MODULE_UART3 = 12,
SLEEP_RETENTION_MODULE_UART4 = 13,
SLEEP_RETENTION_MODULE_MAX = 31
} periph_retention_module_t;
@ -44,8 +46,10 @@ typedef enum periph_retention_module_bitmap {
/* Timer Group by target*/
SLEEP_RETENTION_MODULE_BM_TG0_WDT = BIT(SLEEP_RETENTION_MODULE_TG0_WDT),
SLEEP_RETENTION_MODULE_BM_TG1_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),
SLEEP_RETENTION_MODULE_BM_TG0_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER0),
SLEEP_RETENTION_MODULE_BM_TG0_TIMER1 = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER1),
SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER0),
SLEEP_RETENTION_MODULE_BM_TG1_TIMER1 = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER1),
/* MISC Peripherals */
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
@ -59,8 +63,10 @@ typedef enum periph_retention_module_bitmap {
#define TOP_DOMAIN_PERIPHERALS_BM (SLEEP_RETENTION_MODULE_BM_SYS_PERIPH \
| SLEEP_RETENTION_MODULE_BM_TG0_WDT \
| SLEEP_RETENTION_MODULE_BM_TG1_WDT \
| SLEEP_RETENTION_MODULE_BM_TG0_TIMER \
| SLEEP_RETENTION_MODULE_BM_TG1_TIMER \
| SLEEP_RETENTION_MODULE_BM_TG0_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_TG0_TIMER1 \
| SLEEP_RETENTION_MODULE_BM_TG1_TIMER0 \
| SLEEP_RETENTION_MODULE_BM_TG1_TIMER1 \
| SLEEP_RETENTION_MODULE_BM_UART0 \
| SLEEP_RETENTION_MODULE_BM_UART1 \
| SLEEP_RETENTION_MODULE_BM_UART2 \

View File

@ -667,6 +667,8 @@
#define SOC_PAU_IN_TOP_DOMAIN (1)
#define SOC_CPU_IN_TOP_DOMAIN (1)
#define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1)
/*-------------------------- PSRAM CAPS ----------------------------*/
#define SOC_PSRAM_VDD_POWER_MPLL (1)

View File

@ -25,160 +25,210 @@ const timer_group_signal_conn_t timer_group_periph_signals = {
}
};
/* Registers in retention context:
* TIMG_T0CONFIG_REG / TIMG_T1CONFIG_REG
* TIMG_T0ALARMLO_REG / TIMG_T1ALARMLO_REG
* TIMG_T0ALARMHI_REG / TIMG_T1ALARMHI_REG
* TIMG_T0LOADLO_REG / TIMG_T1LOADLO_REG
* TIMG_T0LOADHI_REG / TIMG_T1LOADHI_REG
* 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 12
static const uint32_t tg_timer_regs_map[4] = {0x1001e2f1, 0x80000000, 0x0, 0x0};
#define TG0_TIMER0_RETENTION_REGS_BASE (REG_TIMG_BASE(0))
#define TG1_TIMER0_RETENTION_REGS_BASE (REG_TIMG_BASE(1))
#define TG_TIMER0_RETENTION_REGS_CNT 7
static const uint32_t tg_timer0_regs_map[4] = {0x100000f1, 0x80000000, 0x0, 0x0};
const regdma_entries_config_t tg0_timer_regdma_entries[] = {
/* Registers in retention context:
* TIMG_T1CONFIG_REG
* TIMG_T1ALARMLO_REG
* TIMG_T1ALARMHI_REG
* TIMG_T1LOADLO_REG
* TIMG_T1LOADHI_REG
* TIMG_INT_ENA_TIMERS_REG
* TIMG_REGCLK_REG
*/
#define TG0_TIMER1_RETENTION_REGS_BASE (REG_TIMG_BASE(0) + 0x24)
#define TG1_TIMER1_RETENTION_REGS_BASE (REG_TIMG_BASE(1) + 0x24)
#define TG_TIMER1_RETENTION_REGS_CNT 7
static const uint32_t tg_timer1_regs_map[4] = {0x800f1, 0x400000, 0x0, 0x0};
const regdma_entries_config_t tg0_timer0_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 = ENTRY(0)
},
// backup stage: wait for the capture done
[1] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x01),
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x01),
TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1),
.owner = ENTRY(0)
},
// 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 = ENTRY(0)
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[3] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x03),
TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = ENTRY(0)
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[4] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x04),
TG0_TIMER0_RETENTION_REGS_BASE, TG0_TIMER0_RETENTION_REGS_BASE,
TG_TIMER0_RETENTION_REGS_CNT, 0, 0,
tg_timer0_regs_map[0], tg_timer0_regs_map[1],
tg_timer0_regs_map[2], tg_timer0_regs_map[3]),
.owner = ENTRY(0)
},
};
const regdma_entries_config_t tg0_timer1_regdma_entries[] = {
// backup stage: trigger a soft capture
[0] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x05),
TIMG_T1UPDATE_REG(0), TIMG_T1_UPDATE, TIMG_T1_UPDATE_M, 0, 1),
.owner = ENTRY(0)
},
// backup stage: wait for the capture done
[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)
},
[3] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x03),
[1] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x06),
TIMG_T1UPDATE_REG(0), 0x0, TIMG_T1_UPDATE_M, 0, 1),
.owner = ENTRY(0)
},
// backup stage: save the captured counter value
// restore stage: store the captured counter value to the loader register
[4] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x04),
TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0),
.owner = ENTRY(0)
},
[5] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x05),
TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0),
.owner = ENTRY(0)
},
[6] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x06),
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x07),
TIMG_T1LO_REG(0), TIMG_T1LOADLO_REG(0), 2, 0, 0),
.owner = ENTRY(0)
},
[7] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x07),
TIMG_T1HI_REG(0), TIMG_T1LOADHI_REG(0), 2, 0, 0),
.owner = ENTRY(0)
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[8] = {
[3] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x08),
TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = ENTRY(0)
},
[9] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x09),
TIMG_T1LOAD_REG(0), 0x1, TIMG_T1_LOAD_M, 1, 0),
.owner = ENTRY(0)
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[10] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x0a),
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]),
[4] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x09),
TG0_TIMER1_RETENTION_REGS_BASE, TG0_TIMER1_RETENTION_REGS_BASE,
TG_TIMER1_RETENTION_REGS_CNT, 0, 0,
tg_timer1_regs_map[0], tg_timer1_regs_map[1],
tg_timer1_regs_map[2], tg_timer1_regs_map[3]),
.owner = ENTRY(0)
},
};
const regdma_entries_config_t tg1_timer_regdma_entries[] = {
const regdma_entries_config_t tg1_timer0_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 = ENTRY(0)
},
// backup stage: wait for the capture done
[1] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x01),
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x01),
TIMG_T0UPDATE_REG(1), 0x0, TIMG_T0_UPDATE_M, 0, 1),
.owner = ENTRY(0)
},
// 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 = ENTRY(0)
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[3] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x03),
TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = ENTRY(0)
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[4] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x04),
TG1_TIMER0_RETENTION_REGS_BASE, TG1_TIMER0_RETENTION_REGS_BASE,
TG_TIMER0_RETENTION_REGS_CNT, 0, 0,
tg_timer0_regs_map[0], tg_timer0_regs_map[1],
tg_timer0_regs_map[2], tg_timer0_regs_map[3]),
.owner = ENTRY(0)
},
};
const regdma_entries_config_t tg1_timer1_regdma_entries[] = {
// backup stage: trigger a soft capture
[0] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x05),
TIMG_T1UPDATE_REG(1), TIMG_T1_UPDATE, TIMG_T1_UPDATE_M, 0, 1),
.owner = ENTRY(0)
},
// backup stage: wait for the capture done
[2] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x02),
TIMG_T0UPDATE_REG(1), 0x0, TIMG_T0_UPDATE_M, 0, 1),
.owner = ENTRY(0)
},
[3] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x03),
[1] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x06),
TIMG_T1UPDATE_REG(1), 0x0, TIMG_T1_UPDATE_M, 0, 1),
.owner = ENTRY(0)
},
// backup stage: save the captured counter value
// restore stage: store the captured counter value to the loader register
[4] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x04),
TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0),
.owner = ENTRY(0)
},
[5] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x05),
TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0),
.owner = ENTRY(0)
},
[6] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x06),
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x07),
TIMG_T1LO_REG(1), TIMG_T1LOADLO_REG(1), 2, 0, 0),
.owner = ENTRY(0)
},
[7] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x07),
TIMG_T1HI_REG(1), TIMG_T1LOADHI_REG(1), 2, 0, 0),
.owner = ENTRY(0)
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[8] = {
[3] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x08),
TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = ENTRY(0)
},
[9] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x09),
TIMG_T1LOAD_REG(1), 0x1, TIMG_T1_LOAD_M, 1, 0),
.owner = ENTRY(0)
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[10] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x0a),
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]),
[4] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x09),
TG1_TIMER1_RETENTION_REGS_BASE, TG1_TIMER1_RETENTION_REGS_BASE,
TG_TIMER1_RETENTION_REGS_CNT, 0, 0,
tg_timer1_regs_map[0], tg_timer1_regs_map[1],
tg_timer1_regs_map[2], tg_timer1_regs_map[3]),
.owner = ENTRY(0)
},
};
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS] = {
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS][SOC_TIMER_GROUP_TIMERS_PER_GROUP] = {
[0] = {
.regdma_entry_array = tg0_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer_regdma_entries)
[0] = {
.module = SLEEP_RETENTION_MODULE_TG0_TIMER0,
.regdma_entry_array = tg0_timer0_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer0_regdma_entries)
},
[1] = {
.regdma_entry_array = tg1_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer_regdma_entries)
.module = SLEEP_RETENTION_MODULE_TG0_TIMER1,
.regdma_entry_array = tg0_timer1_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer1_regdma_entries)
},
},
[1] = {
[0] = {
.module = SLEEP_RETENTION_MODULE_TG1_TIMER0,
.regdma_entry_array = tg1_timer0_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer0_regdma_entries)
},
[1] = {
.module = SLEEP_RETENTION_MODULE_TG1_TIMER1,
.regdma_entry_array = tg1_timer1_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer1_regdma_entries)
},
},
};

View File

@ -10,21 +10,21 @@
#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) },
[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)},
[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)},
[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)},
[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)},
[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)},
[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)},
};
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) },
[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)},
[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)},
[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)},
[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)},
[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)},
[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)},
};
const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = {

View File

@ -13,6 +13,10 @@
#include "soc/periph_defs.h"
#include "soc/regdma.h"
#if SOC_TIMER_SUPPORT_SLEEP_RETENTION
#include "soc/retention_periph_defs.h"
#endif // SOC_TIMER_SUPPORT_SLEEP_RETENTION
#ifdef __cplusplus
extern "C" {
#endif
@ -26,13 +30,14 @@ typedef struct {
extern const timer_group_signal_conn_t timer_group_periph_signals;
#if SOC_TIMER_SUPPORT_SLEEP_RETENTION && SOC_PAU_SUPPORTED
#if SOC_TIMER_SUPPORT_SLEEP_RETENTION
typedef struct {
const periph_retention_module_t module;
const regdma_entries_config_t *regdma_entry_array;
uint32_t array_size;
} tg_timer_reg_retention_info_t;
extern const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS];
extern const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS][SOC_TIMER_GROUP_TIMERS_PER_GROUP];
#endif // SOC_TIMER_SUPPORT_SLEEP_RETENTION
#ifdef __cplusplus