feat(ppa): add sleep retention support for DMA2D and PPA

This commit is contained in:
Song Ruo Jing
2026-07-03 21:37:45 +08:00
parent c8d74d975a
commit de7b3abfe0
20 changed files with 609 additions and 157 deletions
+45
View File
@@ -24,6 +24,7 @@
#include "soc/dma2d_channel.h"
#include "soc/dma2d_periph.h"
#include "esp_bit_defs.h"
#include "esp_private/sleep_retention.h"
/**
* The 2D-DMA driver is designed with a pool & client model + queue design pattern.
@@ -349,6 +350,17 @@ static void dma2d_default_isr(void *args)
}
}
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
static esp_err_t dma2d_create_sleep_retention_link_cb(void *arg)
{
sleep_retention_module_t module = dma2d_reg_retention_info.module;
esp_err_t err = sleep_retention_entries_create(dma2d_reg_retention_info.regdma_entry_array,
dma2d_reg_retention_info.array_size,
REGDMA_LINK_PRI_DMA2D, module);
return err;
}
#endif
esp_err_t dma2d_acquire_pool(const dma2d_pool_config_t *config, dma2d_pool_handle_t *ret_pool)
{
esp_err_t ret = ESP_OK;
@@ -403,6 +415,29 @@ esp_err_t dma2d_acquire_pool(const dma2d_pool_config_t *config, dma2d_pool_handl
dma2d_hal_init(&pre_alloc_group->hal, group_id); // initialize HAL context
// Enable 2D-DMA module clock
dma2d_ll_hw_enable(s_platform.groups[group_id]->hal.dev, true);
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
// acquire sleep retention
sleep_retention_module_t module = dma2d_reg_retention_info.module;
sleep_retention_module_init_param_t init_param = {
.cbs = {
.create = {
.handle = dma2d_create_sleep_retention_link_cb,
.arg = NULL,
},
},
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
};
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
// even though the sleep retention module init failed, DMA2D driver should still work, so just warning here
ESP_LOGW(TAG, "init sleep retention failed, power domain may be turned off during sleep");
} else {
if (sleep_retention_module_allocate(module) != ESP_OK) {
ESP_LOGW(TAG, "fail to allocate retention link list");
// don't call sleep_retention_module_deinit here, otherwise DMA2D peripheral may be powered off during sleep
}
}
#endif
} else {
ret = ESP_ERR_NO_MEM;
free(pre_alloc_tx_channels);
@@ -506,6 +541,16 @@ esp_err_t dma2d_release_pool(dma2d_pool_handle_t dma2d_pool)
PERIPH_RCC_ATOMIC() {
dma2d_ll_enable_bus_clock(group_id, false);
}
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
sleep_retention_module_t module = dma2d_reg_retention_info.module;
if (sleep_retention_is_module_created(module)) {
sleep_retention_module_free(module);
}
if (sleep_retention_is_module_inited(module)) {
sleep_retention_module_deinit(module);
}
#endif
}
if (do_deinitialize) {
@@ -294,6 +294,14 @@ bool peripheral_domain_pd_allowed(void)
mask.bitmap[SLEEP_RETENTION_MODULE_MCPWM0 >> 5] |= BIT(SLEEP_RETENTION_MODULE_MCPWM0 % 32);
#endif
#if SOC_DMA2D_SUPPORTED
mask.bitmap[SLEEP_RETENTION_MODULE_DMA2D >> 5] |= BIT(SLEEP_RETENTION_MODULE_DMA2D % 32);
#endif
#if SOC_PPA_SUPPORTED
mask.bitmap[SLEEP_RETENTION_MODULE_PPA >> 5] |= BIT(SLEEP_RETENTION_MODULE_PPA % 32);
#endif
const sleep_retention_module_bitmap_t peripheral_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask);
const sleep_retention_module_bitmap_t peripheral_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask);
return sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules);
@@ -700,3 +700,7 @@ TEST_CASE("DMA2D_M2M_2D_window", "[DMA2D]")
TEST_ESP_OK(dma2d_m2m_deinit());
}
// Note:
// Sleep retention functionality test is not covered yet, since all basic test cases can survive with 2D-DMA registers reset to default value.
// It shall be tested when arbiter feature is supported and its test case is added.