diff --git a/components/driver/i2c/i2c.c b/components/driver/i2c/i2c.c index 5ebdddcd5d..89e016454c 100644 --- a/components/driver/i2c/i2c.c +++ b/components/driver/i2c/i2c.c @@ -276,6 +276,16 @@ static void i2c_hw_enable(i2c_port_t i2c_num) I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); } +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +static esp_err_t i2c_sleep_retention_init(void *arg) +{ + i2c_port_t i2c_num = *(i2c_port_t *)arg; + esp_err_t 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_RETURN_ON_ERROR(ret, I2C_TAG, "failed to allocate mem for sleep retention"); + return ret; +} +#endif + /* For i2c master mode, we don't need to use a buffer for the data, the APIs will execute the master commands and return after all of the commands have been sent out or when error occurs. So when we send master commands, @@ -415,8 +425,13 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ #endif // SOC_I2C_SUPPORT_SLAVE #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-9353 - 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"); + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = i2c_sleep_retention_init, .arg = &i2c_num } } + }; + ret = sleep_retention_module_init(I2C_SLEEP_RETENTION_MODULE(i2c_num), &init_param); + if (ret == ESP_OK) { + sleep_retention_module_allocate(I2C_SLEEP_RETENTION_MODULE(i2c_num)); + } #endif return ESP_OK; @@ -471,7 +486,10 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num) p_i2c->intr_handle = NULL; #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-9353 - sleep_retention_entries_destroy(I2C_SLEEP_RETENTION_MODULE(i2c_num)); + esp_err_t err = sleep_retention_module_free(I2C_SLEEP_RETENTION_MODULE(i2c_num)); + if (err == ESP_OK) { + err = sleep_retention_module_deinit(I2C_SLEEP_RETENTION_MODULE(i2c_num)); + } #endif if (p_i2c->cmd_mux) { diff --git a/components/esp_driver_i2c/i2c_common.c b/components/esp_driver_i2c/i2c_common.c index 34025ecba6..cdc6c18dd2 100644 --- a/components/esp_driver_i2c/i2c_common.c +++ b/components/esp_driver_i2c/i2c_common.c @@ -41,6 +41,17 @@ typedef struct i2c_platform_t { static i2c_platform_t s_i2c_platform = {}; // singleton platform +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP +static esp_err_t s_i2c_sleep_retention_init(void *arg) +{ + i2c_bus_t *bus = (i2c_bus_t *)arg; + i2c_port_num_t port_num = bus->port_num; + esp_err_t 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"); + return ret; +} +#endif + static esp_err_t s_i2c_bus_handle_acquire(i2c_port_num_t port_num, i2c_bus_handle_t *i2c_new_bus, i2c_bus_mode_t mode) { #if CONFIG_I2C_ENABLE_DEBUG_LOG @@ -60,8 +71,13 @@ static esp_err_t s_i2c_bus_handle_acquire(i2c_port_num_t port_num, i2c_bus_handl bus->bus_mode = mode; #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-9353 - 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"); + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = s_i2c_sleep_retention_init, .arg = (void *)bus } } + }; + ret = sleep_retention_module_init(I2C_SLEEP_RETENTION_MODULE(port_num), &init_param); + if (ret == ESP_OK) { + sleep_retention_module_allocate(I2C_SLEEP_RETENTION_MODULE(port_num)); + } #endif // Enable the I2C module @@ -138,7 +154,10 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus) do_deinitialize = true; s_i2c_platform.buses[port_num] = NULL; #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-9353 - sleep_retention_entries_destroy(I2C_SLEEP_RETENTION_MODULE(port_num)); + esp_err_t err = sleep_retention_module_free(I2C_SLEEP_RETENTION_MODULE(port_num)); + if (err == ESP_OK) { + err = sleep_retention_module_deinit(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");