diff --git a/components/driver/twai/include/driver/twai.h b/components/driver/twai/include/driver/twai.h index 78bc71106a..6cde097f0c 100644 --- a/components/driver/twai/include/driver/twai.h +++ b/components/driver/twai/include/driver/twai.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -114,6 +114,11 @@ typedef struct { uint32_t alerts_enabled; /**< Bit field of alerts to enable (see documentation) */ uint32_t clkout_divider; /**< CLKOUT divider. Can be 1 or any even number from 2 to 14 (optional, set to 0 if unused) */ int intr_flags; /**< Interrupt flags to set the priority of the driver's ISR. Note that to use the ESP_INTR_FLAG_IRAM, the CONFIG_TWAI_ISR_IN_IRAM option should be enabled first. */ + struct { + uint32_t sleep_allow_pd; /**< Set to allow power down. When this flag set, the driver will backup/restore the TWAI registers before/after entering/exist sleep mode. + By this approach, the system can power off TWAI's power domain. + This can save power, but at the expense of more RAM being consumed. */ + } general_flags; /**< General flags */ } twai_general_config_t; /** diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index b6e0e982b5..0878239115 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -28,6 +28,9 @@ #include "soc/gpio_sig_map.h" #include "hal/twai_hal.h" #include "esp_rom_gpio.h" +#if SOC_TWAI_SUPPORT_SLEEP_RETENTION +#include "esp_private/sleep_retention.h" +#endif /* ---------------------------- Definitions --------------------------------- */ //Internal Macros @@ -64,6 +67,8 @@ #define TWAI_PERI_ATOMIC() #endif +#define TWAI_USE_RETENTION_LINK (SOC_TWAI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP) + /* ------------------ Typedefs, structures, and variables ------------------- */ //Control structure for TWAI driver @@ -96,6 +101,11 @@ typedef struct twai_obj_t { static twai_handle_t g_twai_objs[SOC_TWAI_CONTROLLER_NUM]; static portMUX_TYPE g_spinlock = portMUX_INITIALIZER_UNLOCKED; +/* -------------------- Sleep Retention ------------------------ */ +#if TWAI_USE_RETENTION_LINK +static esp_err_t s_twai_create_sleep_retention_link_cb(void *obj); +#endif + /* -------------------- Interrupt and Alert Handlers ------------------------ */ static void twai_alert_handler(twai_obj_t *p_twai_obj, uint32_t alert_code, int *alert_req) @@ -334,6 +344,19 @@ static void twai_free_driver_obj(twai_obj_t *p_obj) if (p_obj->alert_semphr != NULL) { vSemaphoreDeleteWithCaps(p_obj->alert_semphr); } + +#if TWAI_USE_RETENTION_LINK + const periph_retention_module_t retention_id = twai_reg_retention_info[p_obj->controller_id].module_id; + if (sleep_retention_get_created_modules() & BIT(retention_id)) { + assert(sleep_retention_get_inited_modules() & BIT(retention_id)); + sleep_retention_module_free(retention_id); + } + if (sleep_retention_get_inited_modules() & BIT(retention_id)) { + sleep_retention_module_deinit(retention_id); + } + +#endif + heap_caps_free(p_obj); } @@ -365,6 +388,9 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw if (ret != ESP_OK) { goto err; } + + p_obj->controller_id = controller_id; + #if CONFIG_PM_ENABLE #if SOC_TWAI_CLK_SUPPORT_APB // DFS can change APB frequency. So add lock to prevent sleep and APB freq from changing @@ -384,6 +410,28 @@ static esp_err_t twai_alloc_driver_obj(const twai_general_config_t *g_config, tw #endif //SOC_TWAI_CLK_SUPPORT_APB #endif //CONFIG_PM_ENABLE +#if TWAI_USE_RETENTION_LINK + sleep_retention_module_t module = twai_reg_retention_info[controller_id].module_id; + sleep_retention_module_init_param_t init_param = { + .cbs = { + .create = { + .handle = s_twai_create_sleep_retention_link_cb, + .arg = p_obj, + }, + }, + .depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM) + }; + if (sleep_retention_module_init(module, &init_param) != ESP_OK) { + ESP_LOGW(TWAI_TAG, "init sleep retention failed for TWAI%d, power domain may be turned off during sleep", controller_id); + } + + if (g_config->general_flags.sleep_allow_pd) { + if (sleep_retention_module_allocate(module) != ESP_OK) { + ESP_LOGW(TWAI_TAG, "create retention module failed, power domain can't turn off"); + } + } +#endif + *p_twai_obj_ret = p_obj; return ESP_OK; @@ -408,6 +456,9 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw #endif int controller_id = g_config->controller_id; TWAI_CHECK(g_twai_objs[controller_id] == NULL, ESP_ERR_INVALID_STATE); +#if !SOC_TWAI_SUPPORT_SLEEP_RETENTION + TWAI_CHECK(!g_config->general_flags.sleep_allow_pd, ESP_ERR_INVALID_ARG); +#endif //Get clock source resolution uint32_t clock_source_hz = 0; @@ -437,7 +488,6 @@ esp_err_t twai_driver_install_v2(const twai_general_config_t *g_config, const tw //Initialize flags and variables. All other members are already set to zero by twai_alloc_driver_obj() portMUX_INITIALIZE(&p_twai_obj->spinlock); - p_twai_obj->controller_id = controller_id; p_twai_obj->state = TWAI_STATE_STOPPED; p_twai_obj->mode = g_config->mode; p_twai_obj->alerts_enabled = g_config->alerts_enabled; @@ -874,3 +924,14 @@ esp_err_t twai_clear_receive_queue(void) // the handle-less driver API only support one TWAI controller, i.e. the g_twai_objs[0] return twai_clear_receive_queue_v2(g_twai_objs[0]); } + +#if TWAI_USE_RETENTION_LINK +static esp_err_t s_twai_create_sleep_retention_link_cb(void *obj) +{ + twai_obj_t *host = (twai_obj_t *)obj; + return sleep_retention_entries_create(twai_reg_retention_info[host->controller_id].entry_array, + twai_reg_retention_info[host->controller_id].array_size, + REGDMA_LINK_PRI_TWAI, + twai_reg_retention_info[host->controller_id].module_id); +} +#endif diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 297b260f12..f0617c05ea 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1175,6 +1175,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS bool default y +config SOC_TWAI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_EFUSE_DIS_DOWNLOAD_ICACHE bool default y diff --git a/components/soc/esp32c6/include/soc/retention_periph_defs.h b/components/soc/esp32c6/include/soc/retention_periph_defs.h index c7c3a452a1..12fefa081a 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -39,6 +39,8 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_I2S0 = 16, SLEEP_RETENTION_MODULE_ETM0 = 17, SLEEP_RETENTION_MODULE_TEMP_SENSOR = 18, + SLEEP_RETENTION_MODULE_TWAI0 = 19, + SLEEP_RETENTION_MODULE_TWAI1 = 20, /* Modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_WIFI_MAC = 26, @@ -74,6 +76,8 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), + SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0), + SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1), /* modem module, which includes WiFi, BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC), SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB), @@ -99,6 +103,8 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_I2S0 \ | SLEEP_RETENTION_MODULE_BM_ETM0 \ | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ + | SLEEP_RETENTION_MODULE_BM_TWAI0 \ + | SLEEP_RETENTION_MODULE_BM_TWAI1 \ ) #ifdef __cplusplus diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index bdae84ebd2..fcdd897de5 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -456,11 +456,12 @@ #define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- TWAI CAPS ---------------------------------------*/ -#define SOC_TWAI_CONTROLLER_NUM 2 -#define SOC_TWAI_CLK_SUPPORT_XTAL 1 -#define SOC_TWAI_BRP_MIN 2 -#define SOC_TWAI_BRP_MAX 32768 -#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_CONTROLLER_NUM 2 +#define SOC_TWAI_CLK_SUPPORT_XTAL 1 +#define SOC_TWAI_BRP_MIN 2 +#define SOC_TWAI_BRP_MAX 32768 +#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- eFuse CAPS----------------------------*/ #define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 1 diff --git a/components/soc/esp32c6/twai_periph.c b/components/soc/esp32c6/twai_periph.c index 712102bf14..3066be7bf8 100644 --- a/components/soc/esp32c6/twai_periph.c +++ b/components/soc/esp32c6/twai_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/twai_periph.h" +#include "soc/twai_reg.h" #include "soc/gpio_sig_map.h" const twai_controller_signal_conn_t twai_controller_periph_signals = { @@ -29,3 +30,49 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = { } } }; + +/** + * TWAI Registers to be saved during sleep retention + * - TWAI_MODE_REG + * - TWAI_INTERRUPT_ENABLE_REG + * - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG + * - TWAI_ERR_WARNING_LIMIT_REG + * - TWAI_RX_ERR_CNT_REG + * - TWAI_TX_ERR_CNT_REG + * - TWAI_DATA_x_REG + * - TWAI_CLOCK_DIVIDER_REG + * - TWAI_SW_STANDBY_CFG_REG + * - TWAI_HW_CFG_REG + * - TWAI_HW_STANDBY_CNT_REG + * - TWAI_IDLE_INTR_CNT_REG + * - TWAI_ECO_CFG_REG + * - TWAI_TIMESTAMP_PRESCALER_REG + * - TWAI_TIMESTAMP_CFG_REG +*/ +#define TWAI_RETENTION_REGS_CNT 28 +#define TWAI_RETENTION_REGS_BASE(i) REG_TWAI_BASE(i) +static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0}; +#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \ + TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \ + TWAI_RETENTION_REGS_CNT, 0, 0, \ + twai_regs_map[0], twai_regs_map[1], \ + twai_regs_map[2], twai_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1); + +const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = { + [0] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI0, + .entry_array = twai0_regs_retention, + .array_size = ARRAY_SIZE(twai0_regs_retention) + }, + [1] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI1, + .entry_array = twai1_regs_retention, + .array_size = ARRAY_SIZE(twai1_regs_retention) + }, +}; diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index a2254cbb3c..898a807419 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1175,6 +1175,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS bool default y +config SOC_TWAI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_EFUSE_DIS_PAD_JTAG bool default y diff --git a/components/soc/esp32h2/include/soc/retention_periph_defs.h b/components/soc/esp32h2/include/soc/retention_periph_defs.h index e3b7c02076..c172edab27 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -40,6 +40,7 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_I2S0 = 17, SLEEP_RETENTION_MODULE_ETM0 = 18, SLEEP_RETENTION_MODULE_TEMP_SENSOR = 19, + SLEEP_RETENTION_MODULE_TWAI0 = 20, /* Modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BLE_MAC = 28, @@ -74,6 +75,7 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_I2S0 = BIT(SLEEP_RETENTION_MODULE_I2S0), SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR = BIT(SLEEP_RETENTION_MODULE_TEMP_SENSOR), + SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0), /* modem module, which includes BLE and 802.15.4 */ SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC), SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB), @@ -98,6 +100,7 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_I2S0 \ | SLEEP_RETENTION_MODULE_BM_ETM0 \ | SLEEP_RETENTION_MODULE_BM_TEMP_SENSOR \ + | SLEEP_RETENTION_MODULE_BM_TWAI0 \ ) #ifdef __cplusplus diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 1fc679eea0..77e49d37f7 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -453,11 +453,12 @@ #define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- TWAI CAPS ---------------------------------------*/ -#define SOC_TWAI_CONTROLLER_NUM 1UL -#define SOC_TWAI_CLK_SUPPORT_XTAL 1 -#define SOC_TWAI_BRP_MIN 2 -#define SOC_TWAI_BRP_MAX 32768 -#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_CONTROLLER_NUM 1UL +#define SOC_TWAI_CLK_SUPPORT_XTAL 1 +#define SOC_TWAI_BRP_MIN 2 +#define SOC_TWAI_BRP_MAX 32768 +#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- eFuse CAPS----------------------------*/ #define SOC_EFUSE_DIS_PAD_JTAG 1 diff --git a/components/soc/esp32h2/twai_periph.c b/components/soc/esp32h2/twai_periph.c index 5104c78ed8..b81202a741 100644 --- a/components/soc/esp32h2/twai_periph.c +++ b/components/soc/esp32h2/twai_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/twai_periph.h" +#include "soc/twai_reg.h" #include "soc/gpio_sig_map.h" const twai_controller_signal_conn_t twai_controller_periph_signals = { @@ -20,3 +21,42 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = { } } }; + +/** + * TWAI Registers to be saved during sleep retention + * - TWAI_MODE_REG + * - TWAI_INTERRUPT_ENABLE_REG + * - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG + * - TWAI_ERR_WARNING_LIMIT_REG + * - TWAI_RX_ERR_CNT_REG + * - TWAI_TX_ERR_CNT_REG + * - TWAI_DATA_x_REG + * - TWAI_CLOCK_DIVIDER_REG + * - TWAI_SW_STANDBY_CFG_REG + * - TWAI_HW_CFG_REG + * - TWAI_HW_STANDBY_CNT_REG + * - TWAI_IDLE_INTR_CNT_REG + * - TWAI_ECO_CFG_REG + * - TWAI_TIMESTAMP_PRESCALER_REG + * - TWAI_TIMESTAMP_CFG_REG +*/ +#define TWAI_RETENTION_REGS_CNT 28 +#define TWAI_RETENTION_REGS_BASE(i) DR_REG_TWAI_BASE +static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0}; +#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \ + TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \ + TWAI_RETENTION_REGS_CNT, 0, 0, \ + twai_regs_map[0], twai_regs_map[1], \ + twai_regs_map[2], twai_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) }, \ +} + +static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0); +const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = { + [0] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI0, + .entry_array = twai0_regs_retention, + .array_size = ARRAY_SIZE(twai0_regs_retention) + }, +}; diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 402a686f3e..20222f6734 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1643,6 +1643,10 @@ config SOC_TWAI_SUPPORTS_RX_STATUS bool default y +config SOC_TWAI_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_EFUSE_DIS_PAD_JTAG bool default y diff --git a/components/soc/esp32p4/include/soc/retention_periph_defs.h b/components/soc/esp32p4/include/soc/retention_periph_defs.h index d7ca81d804..8e0b575377 100644 --- a/components/soc/esp32p4/include/soc/retention_periph_defs.h +++ b/components/soc/esp32p4/include/soc/retention_periph_defs.h @@ -47,6 +47,9 @@ typedef enum periph_retention_module { SLEEP_RETENTION_MODULE_I2C0 = 22, SLEEP_RETENTION_MODULE_I2C1 = 23, SLEEP_RETENTION_MODULE_ETM0 = 24, + SLEEP_RETENTION_MODULE_TWAI0 = 25, + SLEEP_RETENTION_MODULE_TWAI1 = 26, + SLEEP_RETENTION_MODULE_TWAI2 = 27, SLEEP_RETENTION_MODULE_MAX = 31 } periph_retention_module_t; @@ -83,6 +86,9 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_BM_ETM0 = BIT(SLEEP_RETENTION_MODULE_ETM0), SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0), SLEEP_RETENTION_MODULE_BM_I2C1 = BIT(SLEEP_RETENTION_MODULE_I2C1), + SLEEP_RETENTION_MODULE_BM_TWAI0 = BIT(SLEEP_RETENTION_MODULE_TWAI0), + SLEEP_RETENTION_MODULE_BM_TWAI1 = BIT(SLEEP_RETENTION_MODULE_TWAI1), + SLEEP_RETENTION_MODULE_BM_TWAI2 = BIT(SLEEP_RETENTION_MODULE_TWAI2), SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; @@ -110,6 +116,9 @@ typedef enum periph_retention_module_bitmap { | SLEEP_RETENTION_MODULE_BM_ETM0 \ | SLEEP_RETENTION_MODULE_BM_I2C0 \ | SLEEP_RETENTION_MODULE_BM_I2C1 \ + | SLEEP_RETENTION_MODULE_BM_TWAI0 \ + | SLEEP_RETENTION_MODULE_BM_TWAI1 \ + | SLEEP_RETENTION_MODULE_BM_TWAI2 \ ) #ifdef __cplusplus diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 725d954dd4..70b0f3d03a 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -612,11 +612,12 @@ #define SOC_TOUCH_SAMPLE_CFG_NUM (3) /*!< The sample configurations number in total, each sampler can be used to sample on one frequency */ /*-------------------------- TWAI CAPS ---------------------------------------*/ -#define SOC_TWAI_CONTROLLER_NUM 3 -#define SOC_TWAI_CLK_SUPPORT_XTAL 1 -#define SOC_TWAI_BRP_MIN 2 -#define SOC_TWAI_BRP_MAX 32768 -#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_CONTROLLER_NUM 3 +#define SOC_TWAI_CLK_SUPPORT_XTAL 1 +#define SOC_TWAI_BRP_MIN 2 +#define SOC_TWAI_BRP_MAX 32768 +#define SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define SOC_TWAI_SUPPORT_SLEEP_RETENTION 1 /*-------------------------- eFuse CAPS----------------------------*/ #define SOC_EFUSE_DIS_PAD_JTAG 1 diff --git a/components/soc/esp32p4/twai_periph.c b/components/soc/esp32p4/twai_periph.c index 67b016fa0d..b9fde3d047 100644 --- a/components/soc/esp32p4/twai_periph.c +++ b/components/soc/esp32p4/twai_periph.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/twai_periph.h" +#include "soc/twai_reg.h" #include "soc/gpio_sig_map.h" const twai_controller_signal_conn_t twai_controller_periph_signals = { @@ -38,3 +39,55 @@ const twai_controller_signal_conn_t twai_controller_periph_signals = { } } }; + +/** + * TWAI Registers to be saved during sleep retention + * - TWAI_MODE_REG + * - TWAI_INTERRUPT_ENABLE_REG + * - TWAI_BUS_TIMING_0_REG / TWAI_BUS_TIMING_1_REG + * - TWAI_ERR_WARNING_LIMIT_REG + * - TWAI_RX_ERR_CNT_REG + * - TWAI_TX_ERR_CNT_REG + * - TWAI_DATA_x_REG + * - TWAI_CLOCK_DIVIDER_REG + * - TWAI_SW_STANDBY_CFG_REG + * - TWAI_HW_CFG_REG + * - TWAI_HW_STANDBY_CNT_REG + * - TWAI_IDLE_INTR_CNT_REG + * - TWAI_ECO_CFG_REG + * - TWAI_TIMESTAMP_PRESCALER_REG + * - TWAI_TIMESTAMP_CFG_REG +*/ +#define TWAI_RETENTION_REGS_CNT 28 +#define TWAI_RETENTION_REGS_BASE(i) REG_TWAI_BASE(i) +static const uint32_t twai_regs_map[4] = {0x9fffe0d1, 0xdf, 0x0, 0x0}; +#define TWAI_SLEEP_RETENTION_ENTRIES(id) { \ + [0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TWAI_LINK(0x00), \ + TWAI_RETENTION_REGS_BASE(id), TWAI_RETENTION_REGS_BASE(id), \ + TWAI_RETENTION_REGS_CNT, 0, 0, \ + twai_regs_map[0], twai_regs_map[1], \ + twai_regs_map[2], twai_regs_map[3]), \ + .owner = ENTRY(0) }, \ +} + +static const regdma_entries_config_t twai0_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(0); +static const regdma_entries_config_t twai1_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(1); +static const regdma_entries_config_t twai2_regs_retention[] = TWAI_SLEEP_RETENTION_ENTRIES(2); + +const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM] = { + [0] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI0, + .entry_array = twai0_regs_retention, + .array_size = ARRAY_SIZE(twai0_regs_retention) + }, + [1] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI1, + .entry_array = twai1_regs_retention, + .array_size = ARRAY_SIZE(twai1_regs_retention) + }, + [2] = { + .module_id = SLEEP_RETENTION_MODULE_TWAI2, + .entry_array = twai2_regs_retention, + .array_size = ARRAY_SIZE(twai2_regs_retention) + }, +}; diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index 6dbc3cbc78..350adfcf88 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -56,6 +56,7 @@ extern "C" { #define REGDMA_I2S_LINK(_pri) ((0x1E << 8) | _pri) #define REGDMA_ETM_LINK(_pri) ((0x1F << 8) | _pri) #define REGDMA_TSENS_LINK(_pri) ((0x20 << 8) | _pri) +#define REGDMA_TWAI_LINK(_pri) ((0x21 << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) #define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0 @@ -76,6 +77,7 @@ extern "C" { #define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH #define REGDMA_LINK_PRI_TEMPERATURE_SENSOR REGDMA_LINK_PRI_GENERAL_PERIPH +#define REGDMA_LINK_PRI_TWAI REGDMA_LINK_PRI_GENERAL_PERIPH typedef enum { REGDMA_LINK_PRI_0 = 0, diff --git a/components/soc/include/soc/twai_periph.h b/components/soc/include/soc/twai_periph.h index 72a37210a2..89ca029f02 100644 --- a/components/soc/include/soc/twai_periph.h +++ b/components/soc/include/soc/twai_periph.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,10 @@ #include #include "soc/soc_caps.h" #include "soc/periph_defs.h" +#if SOC_PAU_SUPPORTED +#include "soc/regdma.h" +#include "soc/retention_periph_defs.h" +#endif #ifdef __cplusplus extern "C" { @@ -30,6 +34,16 @@ typedef struct { extern const twai_controller_signal_conn_t twai_controller_periph_signals; +#if SOC_PAU_SUPPORTED +typedef struct { + const periph_retention_module_t module_id; + const regdma_entries_config_t *entry_array; + uint32_t array_size; +} twai_reg_retention_info_t; + +extern const twai_reg_retention_info_t twai_reg_retention_info[SOC_TWAI_CONTROLLER_NUM]; +#endif // SOC_PAU_SUPPORTED + #endif // SOC_TWAI_SUPPORTED #ifdef __cplusplus