diff --git a/components/driver/i2c/i2c.c b/components/driver/i2c/i2c.c index e9397b1752..f99e046b3e 100644 --- a/components/driver/i2c/i2c.c +++ b/components/driver/i2c/i2c.c @@ -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 */ @@ -28,6 +28,10 @@ #include "esp_rom_sys.h" #include #include "soc/clk_tree_defs.h" +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +#include "esp_private/sleep_retention.h" +#endif + #if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL #include "esp_private/esp_clk.h" @@ -316,6 +320,7 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ #if CONFIG_SPIRAM_USE_MALLOC p_i2c->intr_alloc_flags = intr_alloc_flags; #endif + #if SOC_I2C_SUPPORT_SLAVE if (mode == I2C_MODE_SLAVE) { @@ -409,6 +414,11 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ i2c_ll_slave_enable_rx_it(i2c_context[i2c_num].hal.dev); } #endif // SOC_I2C_SUPPORT_SLAVE + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + ret = sleep_retention_entries_create(i2c_regs_retention[i2c_num].link_list, i2c_regs_retention[i2c_num].link_num, REGDMA_LINK_PRI_7, I2C_SLEEP_RETENTION_MODULE(i2c_num)); + ESP_GOTO_ON_ERROR(ret, err, I2C_TAG, "failed to allocate mem for sleep retention"); +#endif return ESP_OK; err: @@ -461,6 +471,10 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num) esp_intr_free(p_i2c->intr_handle); p_i2c->intr_handle = NULL; +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + sleep_retention_entries_destroy(I2C_SLEEP_RETENTION_MODULE(i2c_num)); +#endif + if (p_i2c->cmd_mux) { // Let any command in progress finish. xSemaphoreTake(p_i2c->cmd_mux, portMAX_DELAY); diff --git a/components/driver/test_apps/legacy_i2c_driver/main/CMakeLists.txt b/components/driver/test_apps/legacy_i2c_driver/main/CMakeLists.txt index 008413a567..fd3e3938c5 100644 --- a/components/driver/test_apps/legacy_i2c_driver/main/CMakeLists.txt +++ b/components/driver/test_apps/legacy_i2c_driver/main/CMakeLists.txt @@ -2,6 +2,13 @@ set(srcs "test_app_main.c" "test_i2c.c" ) +# Only build this file with `CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP` and `CONFIG_IEEE802154_ENABLED` enabled +# Enable `CONFIG_IEEE802154_ENABLED` is for modem domain really power down. +# This reliable can be removed if the sleep retention got finished. +if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP AND CONFIG_IEEE802154_ENABLED) + list(APPEND srcs "test_legacy_i2c_sleep_retention.c") +endif() + idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity test_utils driver + PRIV_REQUIRES unity test_utils driver ieee802154 WHOLE_ARCHIVE) diff --git a/components/driver/test_apps/legacy_i2c_driver/main/test_app_main.c b/components/driver/test_apps/legacy_i2c_driver/main/test_app_main.c index 9ceeb2a3eb..ea8659d5e1 100644 --- a/components/driver/test_apps/legacy_i2c_driver/main/test_app_main.c +++ b/components/driver/test_apps/legacy_i2c_driver/main/test_app_main.c @@ -11,7 +11,7 @@ // Some resources are lazy allocated in I2C driver, so we reserved this threshold when checking memory leak // A better way to check a potential memory leak is running a same case by twice, for the second time, the memory usage delta should be zero -#define LEAKS (400) +#define LEAKS (900) void setUp(void) { diff --git a/components/driver/test_apps/legacy_i2c_driver/main/test_legacy_i2c_sleep_retention.c b/components/driver/test_apps/legacy_i2c_driver/main/test_legacy_i2c_sleep_retention.c new file mode 100644 index 0000000000..f0c6bc9d55 --- /dev/null +++ b/components/driver/test_apps/legacy_i2c_driver/main/test_legacy_i2c_sleep_retention.c @@ -0,0 +1,194 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include "unity.h" +#include "unity_config.h" +#include "driver/i2c.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_system.h" +#include "hal/i2c_types.h" +#include "test_utils.h" +#include "esp_sleep.h" +#include "esp_private/sleep_cpu.h" +#include "esp_ieee802154.h" +#include "esp_pm.h" + +#define DATA_LENGTH 100 /*! None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True, timeout=120) + + +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.generic_multi_device +@pytest.mark.parametrize( + 'count, config', + [ + (2, 'sleep_retention',), + ], + indirect=True +) +def test_i2c_sleep_retention_legacy(case_tester) -> None: # type: ignore + for case in case_tester.test_menu: + if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': + case_tester.run_multi_dev_case(case=case, reset=True, timeout=250) diff --git a/components/driver/test_apps/legacy_i2c_driver/sdkconfig.ci.sleep_retention b/components/driver/test_apps/legacy_i2c_driver/sdkconfig.ci.sleep_retention new file mode 100644 index 0000000000..219e27e6b9 --- /dev/null +++ b/components/driver/test_apps/legacy_i2c_driver/sdkconfig.ci.sleep_retention @@ -0,0 +1,5 @@ +CONFIG_PM_ENABLE=y +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_FREERTOS_USE_TICKLESS_IDLE=y +CONFIG_IEEE802154_ENABLED=y +CONFIG_IEEE802154_SLEEP_ENABLE=y diff --git a/components/esp_driver_i2c/i2c_common.c b/components/esp_driver_i2c/i2c_common.c index 9a7e7101d6..26723aad95 100644 --- a/components/esp_driver_i2c/i2c_common.c +++ b/components/esp_driver_i2c/i2c_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,6 +26,9 @@ #include "soc/i2c_periph.h" #include "esp_clk_tree.h" #include "clk_ctrl_os.h" +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +#include "esp_private/sleep_retention.h" +#endif static const char *TAG = "i2c.common"; @@ -55,6 +58,11 @@ static esp_err_t s_i2c_bus_handle_aquire(i2c_port_num_t port_num, i2c_bus_handle bus->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; bus->bus_mode = mode; +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + ret = sleep_retention_entries_create(i2c_regs_retention[port_num].link_list, i2c_regs_retention[port_num].link_num, REGDMA_LINK_PRI_7, I2C_SLEEP_RETENTION_MODULE(port_num)); + ESP_RETURN_ON_ERROR(ret, TAG, "failed to allocate mem for sleep retention"); +#endif + // Enable the I2C module I2C_RCC_ATOMIC() { i2c_ll_enable_bus_clock(bus->port_num, true); @@ -128,6 +136,9 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus) if (s_i2c_platform.count[port_num] == 0) { do_deinitialize = true; s_i2c_platform.buses[port_num] = NULL; +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP + sleep_retention_entries_destroy(I2C_SLEEP_RETENTION_MODULE(port_num)); +#endif if (i2c_bus->intr_handle) { ESP_RETURN_ON_ERROR(esp_intr_free(i2c_bus->intr_handle), TAG, "delete interrupt service failed"); } diff --git a/components/esp_driver_i2c/i2c_slave.c b/components/esp_driver_i2c/i2c_slave.c index 41e6d2fa38..7a51f0c68a 100644 --- a/components/esp_driver_i2c/i2c_slave.c +++ b/components/esp_driver_i2c/i2c_slave.c @@ -189,7 +189,7 @@ esp_err_t i2c_new_slave_device(const i2c_slave_config_t *slave_config, i2c_slave ESP_RETURN_ON_FALSE(slave_config->i2c_port < SOC_I2C_NUM || slave_config->i2c_port == -1, ESP_ERR_INVALID_ARG, TAG, "invalid i2c port number"); ESP_RETURN_ON_FALSE((slave_config->send_buf_depth > 0), ESP_ERR_INVALID_ARG, TAG, "invalid SCL speed"); #if SOC_I2C_SLAVE_SUPPORT_BROADCAST - ESP_GOTO_ON_FALSE(((slave_config->addr_bit_len != I2C_ADDR_BIT_LEN_10) || (!slave_config->flags.broadcast_en)), ESP_ERR_INVALID_STATE, err, TAG, "10bits address cannot used together with broadcast"); + ESP_RETURN_ON_FALSE(((slave_config->addr_bit_len != I2C_ADDR_BIT_LEN_10) || (!slave_config->flags.broadcast_en)), ESP_ERR_INVALID_STATE, TAG, "10bits address cannot used together with broadcast"); #endif int i2c_port_num = slave_config->i2c_port; diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt index b09b511df0..c49b446df4 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/CMakeLists.txt @@ -21,6 +21,13 @@ if(CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR AND CONFIG_SOC_I2C_SUPPORT_SLAVE) list(APPEND srcs "test_i2c_10bit.c") endif() +# Only build this file with `CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP` and `CONFIG_IEEE802154_ENABLED` enabled +# Enable `CONFIG_IEEE802154_ENABLED` is for modem domain really power down. +# This reliable can be removed if the sleep retention got finished. +if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP AND CONFIG_IEEE802154_ENABLED) + list(APPEND srcs "test_i2c_sleep_retention.c") +endif() + idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity driver test_utils + PRIV_REQUIRES unity driver test_utils ieee802154 WHOLE_ARCHIVE) diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_app_main.c b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_app_main.c index 9ceeb2a3eb..eb605f33f2 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_app_main.c +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_app_main.c @@ -11,7 +11,7 @@ // Some resources are lazy allocated in I2C driver, so we reserved this threshold when checking memory leak // A better way to check a potential memory leak is running a same case by twice, for the second time, the memory usage delta should be zero -#define LEAKS (400) +#define LEAKS (1000) void setUp(void) { diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_sleep_retention.c b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_sleep_retention.c new file mode 100644 index 0000000000..315f9f6a4d --- /dev/null +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/main/test_i2c_sleep_retention.c @@ -0,0 +1,159 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "unity.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "esp_err.h" +#include "driver/i2c_master.h" +#include "driver/i2c_slave.h" +#include "esp_log.h" +#include "test_utils.h" +#include "test_board.h" +#include "esp_sleep.h" +#include "esp_private/sleep_cpu.h" +#include "esp_ieee802154.h" +#include "esp_pm.h" + +#define DATA_LENGTH 100 + +static QueueHandle_t s_receive_queue; + +static IRAM_ATTR bool test_i2c_rx_done_callback(i2c_slave_dev_handle_t channel, const i2c_slave_rx_done_event_data_t *edata, void *user_data) +{ + BaseType_t high_task_wakeup = pdFALSE; + QueueHandle_t receive_queue = (QueueHandle_t)user_data; + xQueueSendFromISR(receive_queue, edata, &high_task_wakeup); + return high_task_wakeup == pdTRUE; +} + +static void i2c_master_write_sleep_retention_test(void) +{ + uint8_t data_wr[DATA_LENGTH] = { 0 }; + int i; + + i2c_master_bus_config_t i2c_mst_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = TEST_I2C_PORT, + .scl_io_num = I2C_MASTER_SCL_IO, + .sda_io_num = I2C_MASTER_SDA_IO, + .flags.enable_internal_pullup = true, + }; + i2c_master_bus_handle_t bus_handle; + + TEST_ESP_OK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = 0x58, + .scl_speed_hz = 100000, + }; + + i2c_master_dev_handle_t dev_handle; + TEST_ESP_OK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); + + unity_wait_for_signal("i2c slave init finish"); + + unity_send_signal("master write"); + for (i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i; + } + + disp_buf(data_wr, i); + TEST_ESP_OK(i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1)); + unity_wait_for_signal("i2c slave receive once, master to sleep"); + + TEST_ESP_OK(esp_ieee802154_enable()); + TEST_ESP_OK(sleep_cpu_configure(true)); + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(3 * 1000 * 1000)); + TEST_ESP_OK(esp_light_sleep_start()); + + printf("Waked up!!\n"); + unity_send_signal("master sleep-wakeup"); + unity_wait_for_signal("i2c slave receive again"); + + for (i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i; + } + TEST_ESP_OK(i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1)); + disp_buf(data_wr, i); + unity_send_signal("master write again"); + + unity_wait_for_signal("ready to delete"); + TEST_ESP_OK(sleep_cpu_configure(false)); + TEST_ESP_OK(esp_ieee802154_disable()); + TEST_ESP_OK(i2c_master_bus_rm_device(dev_handle)); + + TEST_ESP_OK(i2c_del_master_bus(bus_handle)); +} + +static void i2c_slave_read_sleep_retention_test(void) +{ + uint8_t data_rd[DATA_LENGTH] = {0}; + uint8_t data_rd2[DATA_LENGTH] = {0}; + + i2c_slave_config_t i2c_slv_config = { + .addr_bit_len = I2C_ADDR_BIT_LEN_7, + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = TEST_I2C_PORT, + .send_buf_depth = 256, + .scl_io_num = I2C_SLAVE_SCL_IO, + .sda_io_num = I2C_SLAVE_SDA_IO, + .slave_addr = 0x58, + }; + + i2c_slave_dev_handle_t slave_handle; + TEST_ESP_OK(i2c_new_slave_device(&i2c_slv_config, &slave_handle)); + + s_receive_queue = xQueueCreate(1, sizeof(i2c_slave_rx_done_event_data_t)); + i2c_slave_event_callbacks_t cbs = { + .on_recv_done = test_i2c_rx_done_callback, + }; + ESP_ERROR_CHECK(i2c_slave_register_event_callbacks(slave_handle, &cbs, s_receive_queue)); + + i2c_slave_rx_done_event_data_t rx_data; + TEST_ESP_OK(i2c_slave_receive(slave_handle, data_rd, DATA_LENGTH)); + + unity_send_signal("i2c slave init finish"); + + unity_wait_for_signal("master write"); + xQueueReceive(s_receive_queue, &rx_data, pdMS_TO_TICKS(10000)); + disp_buf(data_rd, DATA_LENGTH); + for (int i = 0; i < DATA_LENGTH; i++) { + TEST_ASSERT(data_rd[i] == i); + } + + unity_send_signal("i2c slave receive once, master to sleep"); + // Slave sleep as well.. + TEST_ESP_OK(esp_ieee802154_enable()); + TEST_ESP_OK(sleep_cpu_configure(true)); + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000)); + TEST_ESP_OK(esp_light_sleep_start()); + + unity_wait_for_signal("master sleep-wakeup"); + + TEST_ESP_OK(i2c_slave_receive(slave_handle, data_rd2, DATA_LENGTH)); + unity_send_signal("i2c slave receive again"); + + unity_wait_for_signal("master write again"); + + xQueueReceive(s_receive_queue, &rx_data, pdMS_TO_TICKS(10000)); + disp_buf(data_rd2, DATA_LENGTH); + for (int i = 0; i < DATA_LENGTH; i++) { + TEST_ASSERT(data_rd2[i] == i); + } + + vQueueDelete(s_receive_queue); + unity_send_signal("ready to delete"); + TEST_ESP_OK(sleep_cpu_configure(false)); + TEST_ESP_OK(esp_ieee802154_disable()); + TEST_ESP_OK(i2c_del_slave_device(slave_handle)); +} + +TEST_CASE_MULTIPLE_DEVICES("I2C sleep retention test", "[i2c][test_env=generic_multi_device][timeout=150]", i2c_master_write_sleep_retention_test, i2c_slave_read_sleep_retention_test); diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py index ba43e0a826..95ce5a8ed1 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/pytest_i2c.py @@ -1,6 +1,5 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut @@ -38,3 +37,19 @@ def test_i2c_multi_device(case_tester) -> None: # type: ignore for case in case_tester.test_menu: if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': case_tester.run_multi_dev_case(case=case, reset=True) + + +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.generic_multi_device +@pytest.mark.parametrize( + 'count, config', + [ + (2, 'sleep_retention',), + ], + indirect=True +) +def test_i2c_sleep_retention(case_tester) -> None: # type: ignore + for case in case_tester.test_menu: + if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device': + case_tester.run_multi_dev_case(case=case, reset=True, timeout=250) diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.sleep_retention b/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.sleep_retention new file mode 100644 index 0000000000..219e27e6b9 --- /dev/null +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/sdkconfig.ci.sleep_retention @@ -0,0 +1,5 @@ +CONFIG_PM_ENABLE=y +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_FREERTOS_USE_TICKLESS_IDLE=y +CONFIG_IEEE802154_ENABLED=y +CONFIG_IEEE802154_SLEEP_ENABLE=y diff --git a/components/hal/esp32c6/include/hal/i2c_ll.h b/components/hal/esp32c6/include/hal/i2c_ll.h index e9224554e9..9bf8fc8505 100644 --- a/components/hal/esp32c6/include/hal/i2c_ll.h +++ b/components/hal/esp32c6/include/hal/i2c_ll.h @@ -76,6 +76,9 @@ typedef enum { #define I2C_LL_SLAVE_TX_EVENT_INTR (I2C_TXFIFO_WM_INT_ENA_M) #define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9) +// I2C sleep retention module +#define I2C_SLEEP_RETENTION_MODULE(i2c_num) (SLEEP_RETENTION_MODULE_I2C0) + /** * @brief Calculate I2C bus frequency * Note that the clock accuracy is affected by the external pull-up resistor, diff --git a/components/hal/esp32h2/include/hal/i2c_ll.h b/components/hal/esp32h2/include/hal/i2c_ll.h index 509bcedbc7..ae4ab688fd 100644 --- a/components/hal/esp32h2/include/hal/i2c_ll.h +++ b/components/hal/esp32h2/include/hal/i2c_ll.h @@ -75,6 +75,9 @@ typedef enum { #define I2C_LL_SLAVE_TX_EVENT_INTR (I2C_TXFIFO_WM_INT_ENA_M) #define I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT (9) +// I2C sleep retention module +#define I2C_SLEEP_RETENTION_MODULE(i2c_num) ((i2c_num == 0) ? SLEEP_RETENTION_MODULE_I2C0 : SLEEP_RETENTION_MODULE_I2C1) + /** * @brief Calculate I2C bus frequency * Note that the clock accuracy is affected by the external pull-up resistor, diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 95e77b4ac6..ce60b9616a 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -335,10 +335,6 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y -config SOC_PM_SUPPORT_TOP_PD - bool - default y - config SOC_PM_SUPPORT_HP_AON_PD bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index de6b7cad42..abd5b015c6 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -508,7 +508,7 @@ #define SOC_PM_SUPPORT_RC32K_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) -#define SOC_PM_SUPPORT_TOP_PD (1) +// #define SOC_PM_SUPPORT_TOP_PD (1) // TODO: IDF-8643 #define SOC_PM_SUPPORT_HP_AON_PD (1) // #define SOC_PM_SUPPORT_MAC_BB_PD (1) #define SOC_PM_SUPPORT_RTC_PERIPH_PD (1) diff --git a/components/soc/esp32c6/i2c_periph.c b/components/soc/esp32c6/i2c_periph.c index 95a1a0fe16..0cec843a85 100644 --- a/components/soc/esp32c6/i2c_periph.c +++ b/components/soc/esp32c6/i2c_periph.c @@ -1,11 +1,13 @@ /* - * 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/i2c_periph.h" #include "soc/gpio_sig_map.h" +#include "soc/regdma.h" +#include "soc/i2c_reg.h" /* Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc @@ -20,3 +22,32 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = { .module = PERIPH_I2C0_MODULE, }, }; + +// 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_CLK_CONF_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 18 +#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(0) +static const uint32_t i2c0_regs_map[4] = {0xc03f345b, 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) }, \ +}; + +const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM] = { + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)}, +}; diff --git a/components/soc/esp32c6/include/soc/retention_periph_defs.h b/components/soc/esp32c6/include/soc/retention_periph_defs.h index 92d5b47993..8c4440f10e 100644 --- a/components/soc/esp32c6/include/soc/retention_periph_defs.h +++ b/components/soc/esp32c6/include/soc/retention_periph_defs.h @@ -38,6 +38,7 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_GDMA_CH0 = BIT(24), SLEEP_RETENTION_MODULE_GDMA_CH1 = BIT(25), SLEEP_RETENTION_MODULE_GDMA_CH2 = BIT(26), + SLEEP_RETENTION_MODULE_I2C0 = BIT(27), SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; diff --git a/components/soc/esp32h2/i2c_periph.c b/components/soc/esp32h2/i2c_periph.c index efe882ff6e..9c0d5f9b2b 100644 --- a/components/soc/esp32h2/i2c_periph.c +++ b/components/soc/esp32h2/i2c_periph.c @@ -1,11 +1,13 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "soc/i2c_periph.h" #include "soc/gpio_sig_map.h" +#include "soc/regdma.h" +#include "soc/i2c_reg.h" /* Bunch of constants for every I2C peripheral: GPIO signals, irqs, hw addr of registers etc @@ -28,3 +30,49 @@ const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM] = { .module = PERIPH_I2C1_MODULE, }, }; + +// 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_CLK_CONF_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 18 +#define I2C0_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(0) +static const uint32_t i2c0_regs_map[4] = {0xc03f345b, 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 18 +#define I2C1_RETENTION_MAP_BASE I2C_SCL_LOW_PERIOD_REG(1) +static const uint32_t i2c1_regs_map[4] = {0xc03f345b, 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_I2C_NUM] = { + {i2c0_regs_retention, ARRAY_SIZE(i2c0_regs_retention)}, + {i2c1_regs_retention, ARRAY_SIZE(i2c1_regs_retention)}, +}; diff --git a/components/soc/esp32h2/include/soc/i2c_reg.h b/components/soc/esp32h2/include/soc/i2c_reg.h index b965d0a464..923bf7a485 100644 --- a/components/soc/esp32h2/include/soc/i2c_reg.h +++ b/components/soc/esp32h2/include/soc/i2c_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,7 +15,7 @@ extern "C" { * Configures the low level width of the SCL * Clock */ -#define I2C_SCL_LOW_PERIOD_REG (DR_REG_I2C_BASE + 0x0) +#define I2C_SCL_LOW_PERIOD_REG(i) (REG_I2C_BASE(i) + 0x0) /** I2C_SCL_LOW_PERIOD : R/W; bitpos: [8:0]; default: 0; * This register is used to configure for how long SCL remains low in master mode, in * I2C module clock cycles. @@ -28,7 +28,7 @@ extern "C" { /** I2C_CTR_REG register * Transmission setting */ -#define I2C_CTR_REG (DR_REG_I2C_BASE + 0x4) +#define I2C_CTR_REG(i) (REG_I2C_BASE(i) + 0x4) /** I2C_SDA_FORCE_OUT : R/W; bitpos: [0]; default: 0; * 1: direct output, 0: open drain output. */ @@ -148,7 +148,7 @@ extern "C" { /** I2C_SR_REG register * Describe I2C work status. */ -#define I2C_SR_REG (DR_REG_I2C_BASE + 0x8) +#define I2C_SR_REG(i) (REG_I2C_BASE(i) + 0x8) /** I2C_RESP_REC : RO; bitpos: [0]; default: 0; * The received ACK value in master mode or slave mode. 0: ACK, 1: NACK. */ @@ -229,7 +229,7 @@ extern "C" { /** I2C_TO_REG register * Setting time out control for receiving data. */ -#define I2C_TO_REG (DR_REG_I2C_BASE + 0xc) +#define I2C_TO_REG(i) (REG_I2C_BASE(i) + 0xc) /** I2C_TIME_OUT_VALUE : R/W; bitpos: [4:0]; default: 16; * This register is used to configure the timeout for receiving a data bit in APB * clock cycles. @@ -249,7 +249,7 @@ extern "C" { /** I2C_SLAVE_ADDR_REG register * Local slave address setting */ -#define I2C_SLAVE_ADDR_REG (DR_REG_I2C_BASE + 0x10) +#define I2C_SLAVE_ADDR_REG(i) (REG_I2C_BASE(i) + 0x10) /** I2C_SLAVE_ADDR : R/W; bitpos: [14:0]; default: 0; * When configured as an I2C Slave, this field is used to configure the slave address. */ @@ -268,7 +268,7 @@ extern "C" { /** I2C_FIFO_ST_REG register * FIFO status register. */ -#define I2C_FIFO_ST_REG (DR_REG_I2C_BASE + 0x14) +#define I2C_FIFO_ST_REG(i) (REG_I2C_BASE(i) + 0x14) /** I2C_RXFIFO_RADDR : RO; bitpos: [4:0]; default: 0; * This is the offset address of the APB reading from rxfifo */ @@ -308,7 +308,7 @@ extern "C" { /** I2C_FIFO_CONF_REG register * FIFO configuration register. */ -#define I2C_FIFO_CONF_REG (DR_REG_I2C_BASE + 0x18) +#define I2C_FIFO_CONF_REG(i) (REG_I2C_BASE(i) + 0x18) /** I2C_RXFIFO_WM_THRHD : R/W; bitpos: [4:0]; default: 11; * The water mark threshold of rx FIFO in nonfifo access mode. When * reg_reg_fifo_prt_en is 1 and rx FIFO counter is bigger than @@ -368,7 +368,7 @@ extern "C" { /** I2C_DATA_REG register * Rx FIFO read data. */ -#define I2C_DATA_REG (DR_REG_I2C_BASE + 0x1c) +#define I2C_DATA_REG(i) (REG_I2C_BASE(i) + 0x1c) /** I2C_FIFO_RDATA : HRO; bitpos: [7:0]; default: 0; * The value of rx FIFO read data. */ @@ -380,7 +380,7 @@ extern "C" { /** I2C_INT_RAW_REG register * Raw interrupt status */ -#define I2C_INT_RAW_REG (DR_REG_I2C_BASE + 0x20) +#define I2C_INT_RAW_REG(i) (REG_I2C_BASE(i) + 0x20) /** I2C_RXFIFO_WM_INT_RAW : R/SS/WTC; bitpos: [0]; default: 0; * The raw interrupt bit for I2C_RXFIFO_WM_INT interrupt. */ @@ -518,7 +518,7 @@ extern "C" { /** I2C_INT_CLR_REG register * Interrupt clear bits */ -#define I2C_INT_CLR_REG (DR_REG_I2C_BASE + 0x24) +#define I2C_INT_CLR_REG(i) (REG_I2C_BASE(i) + 0x24) /** I2C_RXFIFO_WM_INT_CLR : WT; bitpos: [0]; default: 0; * Set this bit to clear I2C_RXFIFO_WM_INT interrupt. */ @@ -656,7 +656,7 @@ extern "C" { /** I2C_INT_ENA_REG register * Interrupt enable bits */ -#define I2C_INT_ENA_REG (DR_REG_I2C_BASE + 0x28) +#define I2C_INT_ENA_REG(i) (REG_I2C_BASE(i) + 0x28) /** I2C_RXFIFO_WM_INT_ENA : R/W; bitpos: [0]; default: 0; * The interrupt enable bit for I2C_RXFIFO_WM_INT interrupt. */ @@ -794,7 +794,7 @@ extern "C" { /** I2C_INT_STATUS_REG register * Status of captured I2C communication events */ -#define I2C_INT_STATUS_REG (DR_REG_I2C_BASE + 0x2c) +#define I2C_INT_STATUS_REG(i) (REG_I2C_BASE(i) + 0x2c) /** I2C_RXFIFO_WM_INT_ST : RO; bitpos: [0]; default: 0; * The masked interrupt status bit for I2C_RXFIFO_WM_INT interrupt. */ @@ -932,7 +932,7 @@ extern "C" { /** I2C_SDA_HOLD_REG register * Configures the hold time after a negative SCL edge. */ -#define I2C_SDA_HOLD_REG (DR_REG_I2C_BASE + 0x30) +#define I2C_SDA_HOLD_REG(i) (REG_I2C_BASE(i) + 0x30) /** I2C_SDA_HOLD_TIME : R/W; bitpos: [8:0]; default: 0; * This register is used to configure the time to hold the data after the negative * edge of SCL, in I2C module clock cycles. @@ -945,7 +945,7 @@ extern "C" { /** I2C_SDA_SAMPLE_REG register * Configures the sample time after a positive SCL edge. */ -#define I2C_SDA_SAMPLE_REG (DR_REG_I2C_BASE + 0x34) +#define I2C_SDA_SAMPLE_REG(i) (REG_I2C_BASE(i) + 0x34) /** I2C_SDA_SAMPLE_TIME : R/W; bitpos: [8:0]; default: 0; * This register is used to configure for how long SDA is sampled, in I2C module clock * cycles. @@ -958,7 +958,7 @@ extern "C" { /** I2C_SCL_HIGH_PERIOD_REG register * Configures the high level width of SCL */ -#define I2C_SCL_HIGH_PERIOD_REG (DR_REG_I2C_BASE + 0x38) +#define I2C_SCL_HIGH_PERIOD_REG(i) (REG_I2C_BASE(i) + 0x38) /** I2C_SCL_HIGH_PERIOD : R/W; bitpos: [8:0]; default: 0; * This register is used to configure for how long SCL remains high in master mode, in * I2C module clock cycles. @@ -979,7 +979,7 @@ extern "C" { /** I2C_SCL_START_HOLD_REG register * Configures the delay between the SDA and SCL negative edge for a start condition */ -#define I2C_SCL_START_HOLD_REG (DR_REG_I2C_BASE + 0x40) +#define I2C_SCL_START_HOLD_REG(i) (REG_I2C_BASE(i) + 0x40) /** I2C_SCL_START_HOLD_TIME : R/W; bitpos: [8:0]; default: 8; * This register is used to configure the time between the negative edge * of SDA and the negative edge of SCL for a START condition, in I2C module clock @@ -994,7 +994,7 @@ extern "C" { * Configures the delay between the positive * edge of SCL and the negative edge of SDA */ -#define I2C_SCL_RSTART_SETUP_REG (DR_REG_I2C_BASE + 0x44) +#define I2C_SCL_RSTART_SETUP_REG(i) (REG_I2C_BASE(i) + 0x44) /** I2C_SCL_RSTART_SETUP_TIME : R/W; bitpos: [8:0]; default: 8; * This register is used to configure the time between the positive * edge of SCL and the negative edge of SDA for a RESTART condition, in I2C module @@ -1009,7 +1009,7 @@ extern "C" { * Configures the delay after the SCL clock * edge for a stop condition */ -#define I2C_SCL_STOP_HOLD_REG (DR_REG_I2C_BASE + 0x48) +#define I2C_SCL_STOP_HOLD_REG(i) (REG_I2C_BASE(i) + 0x48) /** I2C_SCL_STOP_HOLD_TIME : R/W; bitpos: [8:0]; default: 8; * This register is used to configure the delay after the STOP condition, * in I2C module clock cycles. @@ -1023,7 +1023,7 @@ extern "C" { * Configures the delay between the SDA and * SCL positive edge for a stop condition */ -#define I2C_SCL_STOP_SETUP_REG (DR_REG_I2C_BASE + 0x4c) +#define I2C_SCL_STOP_SETUP_REG(i) (REG_I2C_BASE(i) + 0x4c) /** I2C_SCL_STOP_SETUP_TIME : R/W; bitpos: [8:0]; default: 8; * This register is used to configure the time between the positive edge * of SCL and the positive edge of SDA, in I2C module clock cycles. @@ -1036,7 +1036,7 @@ extern "C" { /** I2C_FILTER_CFG_REG register * SCL and SDA filter configuration register */ -#define I2C_FILTER_CFG_REG (DR_REG_I2C_BASE + 0x50) +#define I2C_FILTER_CFG_REG(i) (REG_I2C_BASE(i) + 0x50) /** I2C_SCL_FILTER_THRES : R/W; bitpos: [3:0]; default: 0; * When a pulse on the SCL input has smaller width than this register value * in I2C module clock cycles, the I2C controller will ignore that pulse. @@ -1071,7 +1071,7 @@ extern "C" { /** I2C_CLK_CONF_REG register * I2C CLK configuration register */ -#define I2C_CLK_CONF_REG (DR_REG_I2C_BASE + 0x54) +#define I2C_CLK_CONF_REG(i) (REG_I2C_BASE(i) + 0x54) /** I2C_SCLK_DIV_NUM : R/W; bitpos: [7:0]; default: 0; * the integral part of the fractional divisor for i2c module */ @@ -1111,7 +1111,7 @@ extern "C" { /** I2C_COMD0_REG register * I2C command register 0 */ -#define I2C_COMD0_REG (DR_REG_I2C_BASE + 0x58) +#define I2C_COMD0_REG(i) (REG_I2C_BASE(i) + 0x58) /** I2C_COMMAND0 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 0. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1136,7 +1136,7 @@ extern "C" { /** I2C_COMD1_REG register * I2C command register 1 */ -#define I2C_COMD1_REG (DR_REG_I2C_BASE + 0x5c) +#define I2C_COMD1_REG(i) (REG_I2C_BASE(i) + 0x5c) /** I2C_COMMAND1 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 1. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1161,7 +1161,7 @@ extern "C" { /** I2C_COMD2_REG register * I2C command register 2 */ -#define I2C_COMD2_REG (DR_REG_I2C_BASE + 0x60) +#define I2C_COMD2_REG(i) (REG_I2C_BASE(i) + 0x60) /** I2C_COMMAND2 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 2. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1186,7 +1186,7 @@ extern "C" { /** I2C_COMD3_REG register * I2C command register 3 */ -#define I2C_COMD3_REG (DR_REG_I2C_BASE + 0x64) +#define I2C_COMD3_REG(i) (REG_I2C_BASE(i) + 0x64) /** I2C_COMMAND3 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 3. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1211,7 +1211,7 @@ extern "C" { /** I2C_COMD4_REG register * I2C command register 4 */ -#define I2C_COMD4_REG (DR_REG_I2C_BASE + 0x68) +#define I2C_COMD4_REG(i) (REG_I2C_BASE(i) + 0x68) /** I2C_COMMAND4 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 4. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1236,7 +1236,7 @@ extern "C" { /** I2C_COMD5_REG register * I2C command register 5 */ -#define I2C_COMD5_REG (DR_REG_I2C_BASE + 0x6c) +#define I2C_COMD5_REG(i) (REG_I2C_BASE(i) + 0x6c) /** I2C_COMMAND5 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 5. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1260,7 +1260,7 @@ extern "C" { /** I2C_COMD6_REG register * I2C command register 6 */ -#define I2C_COMD6_REG (DR_REG_I2C_BASE + 0x70) +#define I2C_COMD6_REG(i) (REG_I2C_BASE(i) + 0x70) /** I2C_COMMAND6 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 6. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1284,7 +1284,7 @@ extern "C" { /** I2C_COMD7_REG register * I2C command register 7 */ -#define I2C_COMD7_REG (DR_REG_I2C_BASE + 0x74) +#define I2C_COMD7_REG(i) (REG_I2C_BASE(i) + 0x74) /** I2C_COMMAND7 : R/W; bitpos: [13:0]; default: 0; * This is the content of command 7. It consists of three parts: * op_code is the command, 0: RSTART, 1: WRITE, 2: READ, 3: STOP, 4: END. @@ -1308,7 +1308,7 @@ extern "C" { /** I2C_SCL_ST_TIME_OUT_REG register * SCL status time out register */ -#define I2C_SCL_ST_TIME_OUT_REG (DR_REG_I2C_BASE + 0x78) +#define I2C_SCL_ST_TIME_OUT_REG(i) (REG_I2C_BASE(i) + 0x78) /** I2C_SCL_ST_TO_I2C : R/W; bitpos: [4:0]; default: 16; * The threshold value of SCL_FSM state unchanged period. It should be o more than 23 */ @@ -1320,7 +1320,7 @@ extern "C" { /** I2C_SCL_MAIN_ST_TIME_OUT_REG register * SCL main status time out register */ -#define I2C_SCL_MAIN_ST_TIME_OUT_REG (DR_REG_I2C_BASE + 0x7c) +#define I2C_SCL_MAIN_ST_TIME_OUT_REG(i) (REG_I2C_BASE(i) + 0x7c) /** I2C_SCL_MAIN_ST_TO_I2C : R/W; bitpos: [4:0]; default: 16; * The threshold value of SCL_MAIN_FSM state unchanged period.nIt should be o more * than 23 @@ -1333,7 +1333,7 @@ extern "C" { /** I2C_SCL_SP_CONF_REG register * Power configuration register */ -#define I2C_SCL_SP_CONF_REG (DR_REG_I2C_BASE + 0x80) +#define I2C_SCL_SP_CONF_REG(i) (REG_I2C_BASE(i) + 0x80) /** I2C_SCL_RST_SLV_EN : R/W/SC; bitpos: [0]; default: 0; * When I2C master is IDLE, set this bit to send out SCL pulses. The number of pulses * equals to reg_scl_rst_slv_num[4:0]. @@ -1370,7 +1370,7 @@ extern "C" { /** I2C_SCL_STRETCH_CONF_REG register * Set SCL stretch of I2C slave */ -#define I2C_SCL_STRETCH_CONF_REG (DR_REG_I2C_BASE + 0x84) +#define I2C_SCL_STRETCH_CONF_REG(i) (REG_I2C_BASE(i) + 0x84) /** I2C_STRETCH_PROTECT_NUM : R/W; bitpos: [9:0]; default: 0; * Configure the period of I2C slave stretching SCL line. */ @@ -1412,7 +1412,7 @@ extern "C" { /** I2C_DATE_REG register * Version register */ -#define I2C_DATE_REG (DR_REG_I2C_BASE + 0xf8) +#define I2C_DATE_REG(i) (REG_I2C_BASE(i) + 0xf8) /** I2C_DATE : R/W; bitpos: [31:0]; default: 35656050; * This is the the version register. */ @@ -1424,7 +1424,7 @@ extern "C" { /** I2C_TXFIFO_START_ADDR_REG register * I2C TXFIFO base address register */ -#define I2C_TXFIFO_START_ADDR_REG (DR_REG_I2C_BASE + 0x100) +#define I2C_TXFIFO_START_ADDR_REG(i) (REG_I2C_BASE(i) + 0x100) /** I2C_TXFIFO_START_ADDR : HRO; bitpos: [31:0]; default: 0; * This is the I2C txfifo first address. */ @@ -1436,7 +1436,7 @@ extern "C" { /** I2C_RXFIFO_START_ADDR_REG register * I2C RXFIFO base address register */ -#define I2C_RXFIFO_START_ADDR_REG (DR_REG_I2C_BASE + 0x180) +#define I2C_RXFIFO_START_ADDR_REG(i) (REG_I2C_BASE(i) + 0x180) /** I2C_RXFIFO_START_ADDR : HRO; bitpos: [31:0]; default: 0; * This is the I2C rxfifo first address. */ diff --git a/components/soc/esp32h2/include/soc/retention_periph_defs.h b/components/soc/esp32h2/include/soc/retention_periph_defs.h index ce45f75960..b1d0874612 100644 --- a/components/soc/esp32h2/include/soc/retention_periph_defs.h +++ b/components/soc/esp32h2/include/soc/retention_periph_defs.h @@ -36,6 +36,8 @@ typedef enum periph_retention_module_bitmap { SLEEP_RETENTION_MODULE_GDMA_CH0 = BIT(24), SLEEP_RETENTION_MODULE_GDMA_CH1 = BIT(25), SLEEP_RETENTION_MODULE_GDMA_CH2 = BIT(26), + SLEEP_RETENTION_MODULE_I2C0 = BIT(27), + SLEEP_RETENTION_MODULE_I2C1 = BIT(28), SLEEP_RETENTION_MODULE_ALL = (uint32_t)-1 } periph_retention_module_bitmap_t; diff --git a/components/soc/include/soc/i2c_periph.h b/components/soc/include/soc/i2c_periph.h index 0da893cab2..7df3e8ba3c 100644 --- a/components/soc/include/soc/i2c_periph.h +++ b/components/soc/include/soc/i2c_periph.h @@ -1,22 +1,17 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "soc/i2c_reg.h" #include "soc/i2c_struct.h" #include "soc/soc_caps.h" #include "soc/periph_defs.h" +#if SOC_PM_SUPPORT_TOP_PD +#include "soc/regdma.h" +#endif #ifdef __cplusplus extern "C" { @@ -33,6 +28,15 @@ typedef struct { extern const i2c_signal_conn_t i2c_periph_signal[SOC_I2C_NUM]; +#if SOC_PM_SUPPORT_TOP_PD +typedef struct { + const regdma_entries_config_t *link_list; + uint32_t link_num; +} i2c_reg_ctx_link_t; + +extern const i2c_reg_ctx_link_t i2c_regs_retention[SOC_I2C_NUM]; +#endif + #ifdef __cplusplus } #endif diff --git a/components/soc/include/soc/regdma.h b/components/soc/include/soc/regdma.h index 819ce99b7b..1f3ea3bb75 100644 --- a/components/soc/include/soc/regdma.h +++ b/components/soc/include/soc/regdma.h @@ -44,6 +44,7 @@ extern "C" { #define REGDMA_MODEM_BT_BB_LINK(_pri) ((0x16 << 8) | _pri) #define REGDMA_MODEM_IEEE802154_LINK(_pri) ((0x17 << 8) | _pri) #define REGDMA_GDMA_LINK(_pri) ((0x18 << 8) | _pri) +#define REGDMA_I2C_LINK(_pri) ((0x19 << 8) | _pri) #define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) #define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0 diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index 70f500ced8..5a4dee5e7f 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -154,7 +154,6 @@ Light-sleep Peripheral Power Down - Trace - Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA - SPI2 - - I2C - I2S - PCNT - USB-Serial-JTAG diff --git a/docs/zh_CN/api-reference/system/power_management.rst b/docs/zh_CN/api-reference/system/power_management.rst index e0d3802a40..03a2f997bf 100644 --- a/docs/zh_CN/api-reference/system/power_management.rst +++ b/docs/zh_CN/api-reference/system/power_management.rst @@ -154,7 +154,6 @@ Light-sleep 外设下电 - Trace - Crypto: AES/ECC/HMAC/RSA/SHA/DS/XTA_AES/ECDSA - SPI2 - - I2C - I2S - PCNT - USB-Serial-JTAG diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 6c7863ad41..85a19d2be9 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -755,7 +755,6 @@ components/soc/esp32s3/uart_periph.c components/soc/include/soc/dedic_gpio_periph.h components/soc/include/soc/emac_periph.h components/soc/include/soc/gpio_periph.h -components/soc/include/soc/i2c_periph.h components/soc/include/soc/ledc_periph.h components/soc/lldesc.c components/spi_flash/include/spi_flash_chip_boya.h