From c4c83bc0415d9e99dc5ee30c54c4e6ad70341f0d Mon Sep 17 00:00:00 2001 From: Chen Chen Date: Tue, 15 Sep 2026 11:24:56 +0800 Subject: [PATCH] feat(i2c): support i2c sleep retention on esp32h21 --- components/esp_hal_i2c/esp32h21/i2c_periph.c | 68 ++++++++++++++++++- .../esp32h21/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32h21/include/soc/soc.h | 9 ++- .../soc/esp32h21/include/soc/soc_caps.h | 2 +- 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/components/esp_hal_i2c/esp32h21/i2c_periph.c b/components/esp_hal_i2c/esp32h21/i2c_periph.c index bc8a9bdffd8..a6fcd2c2fc4 100644 --- a/components/esp_hal_i2c/esp32h21/i2c_periph.c +++ b/components/esp_hal_i2c/esp32h21/i2c_periph.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,3 +28,69 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = { .irq = ETS_I2C_EXT1_INTR_SOURCE, }, }; + +// I2C sleep retention entries +// I2C registers require set the reg_update bit to make the configuration take effect + +/* I2C Registers Context + Include: I2C_SCL_LOW_PERIOD_REG / + I2C_CTR_REG / I2C_TO_REG / I2C_SLAVE_ADDR_REG / I2C_FIFO_CONF_REG + I2C_INT_ENA_REG / I2C_SDA_HOLD_REG / I2C_SDA_SAMPLE_REG / I2C_SCL_START_HOLD_REG + I2C_SCL_RSTART_SETUP_REG / I2C_SCL_STOP_HOLD_REG / I2C_SCL_STOP_SETUP_REG /I2C_FILTER_CFG_REG / I2C_SCL_ST_TIME_OUT_REG / I2C_SCL_MAIN_ST_TIME_OUT_REG / I2C_SCL_SP_CONF_REG / I2C_SCL_STRETCH_CONF_REG +*/ +#define I2C0_RETENTION_REGS_CNT 17 +#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(0) +static const uint32_t i2c0_regs_map[4] = {0xc01f345b, 0x3, 0, 0}; +static const regdma_entries_config_t i2c0_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_MAP_BASE, I2C0_RETENTION_REGS_CNT, 0, 0, i2c0_regs_map[0], i2c0_regs_map[1], i2c0_regs_map[2], i2c0_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [1] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(0), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [2] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(0), 0x0, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [3] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(0), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [4] = { + .config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(0), 0x0, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ +}; + +#define I2C1_RETENTION_REGS_CNT 17 +#define I2C1_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(1) +static const uint32_t i2c1_regs_map[4] = {0xc01f345b, 0x3, 0, 0}; +static const regdma_entries_config_t i2c1_regs_retention[] = { + [0] = { + .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_I2C_LINK(0x00), I2C1_RETENTION_MAP_BASE, I2C1_RETENTION_MAP_BASE, I2C1_RETENTION_REGS_CNT, 0, 0, i2c1_regs_map[0], i2c1_regs_map[1], i2c1_regs_map[2], i2c1_regs_map[3]), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [1] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x01), I2C_CTR_REG(1), I2C_FSM_RST, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [2] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x02), I2C_CTR_REG(1), 0x0, I2C_FSM_RST_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [3] = { + .config = REGDMA_LINK_WRITE_INIT(REGDMA_I2C_LINK(0x03), I2C_CTR_REG(1), I2C_CONF_UPGATE, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ + [4] = { + .config = REGDMA_LINK_WAIT_INIT(REGDMA_I2C_LINK(0x04), I2C_CTR_REG(1), 0x0, I2C_CONF_UPGATE_M, 1, 0), \ + .owner = ENTRY(0) | ENTRY(2) + }, \ +}; + +const i2c_reg_ctx_link_t i2c_regs_retention[SOC_HP_I2C_NUM] = { + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention), SLEEP_RETENTION_MODULE_I2C0}, + {i2c1_regs_retention, ARRAY_SIZE(i2c1_regs_retention), SLEEP_RETENTION_MODULE_I2C1}, +}; diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 16fe97b2696..e79bdb1a48c 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -555,6 +555,10 @@ config SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE bool default y +config SOC_I2C_SUPPORT_SLEEP_RETENTION + bool + default y + config SOC_I2S_HW_VERSION_2 bool default y diff --git a/components/soc/esp32h21/include/soc/soc.h b/components/soc/esp32h21/include/soc/soc.h index 24668ac5c5b..a250b154f9e 100644 --- a/components/soc/esp32h21/include/soc/soc.h +++ b/components/soc/esp32h21/include/soc/soc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -16,16 +16,15 @@ #define PRO_CPU_NUM (0) -// TODO: IDF-11856 #define DR_REG_UHCI_BASE(i) (DR_REG_UHCI0_BASE - (i) * 0x8000) #define DR_REG_UART_BASE(i) (DR_REG_UART0_BASE + (i) * 0x1000) #define REG_UART_BASE(i) (DR_REG_UART0_BASE + (i) * 0x1000) -#define DR_REG_UART_AHB_BASE(i) (0x60000000 + (i) * 0x10000) +#define DR_REG_UART_AHB_BASE(i) (DR_REG_UART0_BASE + (i) * 0x10000) #define DR_UART_FIFO_AHB_REG(i) (REG_UART_AHB_BASE(i) + 0x0) -#define DR_REG_I2S_BASE(i) (DR_REG_I2S_BASE) // only one I2S on H21 +#define DR_REG_I2S_BASE(i) (DR_REG_I2S0_BASE) // only one I2S on H21 #define DR_REG_TIMG_BASE(i) (DR_REG_TIMERG0_BASE + (i)*0x1000) #define DR_REG_SPI_MEM_BASE(i) (DR_REG_SPIMEM0_BASE + (i) * 0x1000) -#define DR_REG_I2C_BASE(i) (DR_REG_I2C_EXT0_BASE + (i) * 0x1000) +#define DR_REG_I2C_BASE(i) (DR_REG_I2C0_BASE + (i) * 0x1000) //Registers Operation {{ #define ETS_UNCACHED_ADDR(addr) (addr) diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 776c79af83e..60d40a460a8 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -246,7 +246,7 @@ #define SOC_I2C_SLAVE_SUPPORT_BROADCAST (1) #define SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE (1) -// #define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) // TODO: [ESP32H21] IDF-11579 +#define SOC_I2C_SUPPORT_SLEEP_RETENTION (1) /*-------------------------- I2S CAPS ----------------------------------------*/ #define SOC_I2S_HW_VERSION_2 (1)