mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(ppa): add sleep retention support for DMA2D and PPA
This commit is contained in:
@@ -37,6 +37,9 @@ endif()
|
||||
|
||||
if(CONFIG_SOC_DMA2D_SUPPORTED)
|
||||
list(APPEND srcs "src/dma2d.c")
|
||||
if(CONFIG_SOC_PAU_SUPPORTED)
|
||||
list(APPEND srcs "${target}/dma2d_retention.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
|
||||
38
components/esp_driver_dma/esp32p4/dma2d_retention.c
Normal file
38
components/esp_driver_dma/esp32p4/dma2d_retention.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "dma2d_priv.h"
|
||||
#include "soc/dma2d_reg.h"
|
||||
|
||||
/** DMA2D Registers to be saved during sleep retention
|
||||
*
|
||||
* DMA2D driver is implemented in the way that channels are used as a pool,
|
||||
* therefore, only general registers are needed to be saved during sleep retention.
|
||||
*
|
||||
* DMA2D_RST_CONF_REG,
|
||||
* DMA2D_INTR_MEM_START_ADDR_REG, DMA2D_INTR_MEM_END_ADDR_REG, DMA2D_EXTR_MEM_START_ADDR_REG, DMA2D_EXTR_MEM_END_ADDR_REG
|
||||
* DMA2D_OUT_ARB_CONFIG_REG, DMA2D_IN_ARB_CONFIG_REG
|
||||
*/
|
||||
#define DMA2D_RETENTION_REGS_CNT 7
|
||||
#define DMA2D_RETENTION_REGS_BASE DMA2D_RST_CONF_REG
|
||||
static const uint32_t dma2d_regs_map[4] = {0x7f, 0x0, 0x0, 0x0};
|
||||
static const regdma_entries_config_t dma2d_regdma_entries[] = {
|
||||
[0] = {
|
||||
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_DMA2D_LINK(0x00),
|
||||
DMA2D_RETENTION_REGS_BASE, DMA2D_RETENTION_REGS_BASE,
|
||||
DMA2D_RETENTION_REGS_CNT, 0, 0,
|
||||
dma2d_regs_map[0], dma2d_regs_map[1],
|
||||
dma2d_regs_map[2], dma2d_regs_map[3]),
|
||||
.owner = ENTRY(0),
|
||||
},
|
||||
};
|
||||
|
||||
const dma2d_retention_desc_t dma2d_reg_retention_info = {
|
||||
.module = SLEEP_RETENTION_MODULE_DMA2D,
|
||||
.regdma_entry_array = dma2d_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(dma2d_regdma_entries),
|
||||
};
|
||||
38
components/esp_driver_dma/esp32s31/dma2d_retention.c
Normal file
38
components/esp_driver_dma/esp32s31/dma2d_retention.c
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "dma2d_priv.h"
|
||||
#include "soc/dma2d_reg.h"
|
||||
|
||||
/** DMA2D Registers to be saved during sleep retention
|
||||
*
|
||||
* DMA2D driver is implemented in the way that channels are used as a pool,
|
||||
* therefore, only general registers are needed to be saved during sleep retention.
|
||||
*
|
||||
* DMA2D_RST_CONF_REG,
|
||||
* DMA2D_INTR_MEM_START_ADDR_REG, DMA2D_INTR_MEM_END_ADDR_REG, DMA2D_EXTR_MEM_START_ADDR_REG, DMA2D_EXTR_MEM_END_ADDR_REG
|
||||
* DMA2D_OUT_ARB_CONFIG_REG, DMA2D_IN_ARB_CONFIG_REG
|
||||
*/
|
||||
#define DMA2D_RETENTION_REGS_CNT 7
|
||||
#define DMA2D_RETENTION_REGS_BASE DMA2D_RST_CONF_REG
|
||||
static const uint32_t dma2d_regs_map[4] = {0x7f, 0x0, 0x0, 0x0};
|
||||
static const regdma_entries_config_t dma2d_regdma_entries[] = {
|
||||
[0] = {
|
||||
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_DMA2D_LINK(0x00),
|
||||
DMA2D_RETENTION_REGS_BASE, DMA2D_RETENTION_REGS_BASE,
|
||||
DMA2D_RETENTION_REGS_CNT, 0, 0,
|
||||
dma2d_regs_map[0], dma2d_regs_map[1],
|
||||
dma2d_regs_map[2], dma2d_regs_map[3]),
|
||||
.owner = ENTRY(0) | ENTRY(2),
|
||||
},
|
||||
};
|
||||
|
||||
const dma2d_retention_desc_t dma2d_reg_retention_info = {
|
||||
.module = SLEEP_RETENTION_MODULE_DMA2D,
|
||||
.regdma_entry_array = dma2d_regdma_entries,
|
||||
.array_size = ARRAY_SIZE(dma2d_regdma_entries),
|
||||
};
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
|
||||
/**
|
||||
* The 2D-DMA driver is designed with a pool & client model + queue design pattern.
|
||||
@@ -351,6 +352,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;
|
||||
@@ -404,6 +416,34 @@ 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,
|
||||
},
|
||||
},
|
||||
.attribute = SLEEP_RETENTION_MODULE_ATTR_ATTACH,
|
||||
.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
|
||||
} else {
|
||||
if (sleep_retention_module_attach(module) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "attach retention module failed, power domain can't turn off");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
free(pre_alloc_tx_channels);
|
||||
@@ -494,6 +534,19 @@ 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_attached(module)) {
|
||||
sleep_retention_module_detach(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) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "hal/dma2d_hal.h"
|
||||
#include "hal/dma2d_ll.h"
|
||||
#include "esp_private/dma2d.h"
|
||||
#include "soc/regdma.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -89,6 +90,18 @@ struct dma2d_rx_channel_t {
|
||||
uint32_t bundled_tx_channel_mask; // Bit mask indicating the TX channels together with the RX channel to do the transaction
|
||||
};
|
||||
|
||||
#if SOC_PAU_SUPPORTED
|
||||
#include "soc/retention_periph_defs.h"
|
||||
|
||||
typedef struct {
|
||||
const periph_retention_module_t module;
|
||||
const regdma_entries_config_t *regdma_entry_array;
|
||||
uint32_t array_size;
|
||||
} dma2d_retention_desc_t;
|
||||
|
||||
extern const dma2d_retention_desc_t dma2d_reg_retention_info;
|
||||
#endif // SOC_PAU_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -732,3 +732,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.
|
||||
|
||||
Reference in New Issue
Block a user