Skip to content

Commit

Permalink
Merge branch 'feat/sleep_retention_depends_power_state_management' in…
Browse files Browse the repository at this point in the history
…to 'master'

sleep retention multiple modules initialization and dependency management

Closes WIFI-5252 and IDFGH-11302

See merge request espressif/esp-idf!28941
  • Loading branch information
jack0c committed Apr 1, 2024
2 parents 557ad14 + d9682ea commit 0c68b9b
Show file tree
Hide file tree
Showing 38 changed files with 1,114 additions and 434 deletions.
23 changes: 21 additions & 2 deletions components/bt/controller/esp32c6/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,9 +512,10 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
}

#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
static esp_err_t sleep_modem_ble_mac_retention_init(void *arg)
{
uint8_t size;
int extra = *(int *)arg;
const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra);
esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_BT_MAC_BB, SLEEP_RETENTION_MODULE_BLE_MAC);
if (err == ESP_OK) {
Expand All @@ -523,9 +524,27 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
return err;
}

static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
{
int retention_args = extra;
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } },
.depends = BIT(SLEEP_RETENTION_MODULE_BT_BB)
};
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param);
if (err == ESP_OK) {
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC);
}
return err;
}

static void sleep_modem_ble_mac_modem_state_deinit(void)
{
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC);
esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC);
if (err == ESP_OK) {
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC);
assert(err == ESP_OK);
}
}

void sleep_modem_light_sleep_overhead_set(uint32_t overhead)
Expand Down
23 changes: 21 additions & 2 deletions components/bt/controller/esp32h2/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,10 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
}

#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE
static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
static esp_err_t sleep_modem_ble_mac_retention_init(void *arg)
{
uint8_t size;
int extra = *(int *)arg;
const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra);
esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_BT_MAC_BB, SLEEP_RETENTION_MODULE_BLE_MAC);
if (err == ESP_OK) {
Expand All @@ -512,9 +513,27 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
return err;
}

static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
{
int retention_args = extra;
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } },
.depends = BIT(SLEEP_RETENTION_MODULE_BT_BB)
};
esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param);
if (err == ESP_OK) {
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC);
}
return err;
}

static void sleep_modem_ble_mac_modem_state_deinit(void)
{
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC);
esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC);
if (err == ESP_OK) {
err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC);
assert(err == ESP_OK);
}
}

void sleep_modem_light_sleep_overhead_set(uint32_t overhead)
Expand Down
24 changes: 21 additions & 3 deletions components/driver/i2c/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down
25 changes: 22 additions & 3 deletions components/esp_driver_i2c/i2c_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#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
Expand Down Expand Up @@ -69,7 +68,6 @@ static void i2c_master_write_sleep_retention_test(void)
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());
Expand All @@ -87,7 +85,6 @@ static void i2c_master_write_sleep_retention_test(void)

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));
Expand Down Expand Up @@ -131,7 +128,6 @@ static void i2c_slave_read_sleep_retention_test(void)

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());
Expand All @@ -152,7 +148,6 @@ static void i2c_slave_read_sleep_retention_test(void)
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));
}

Expand Down
48 changes: 43 additions & 5 deletions components/esp_hw_support/dma/gdma_sleep_retention.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,68 @@
#include "soc/soc_caps.h"

#include "esp_err.h"
#include "esp_check.h"
#if CONFIG_GDMA_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include "esp_log.h"
#include "esp_check.h"
#include "esp_private/sleep_retention.h"
#include "esp_private/esp_regdma.h"

#include "hal/gdma_ll.h"

static const char *TAG = "gdma";

esp_err_t gdma_sleep_retention_init(int group_id, int pair_id)
typedef struct {
int group_id;
int pair_id;
} gdma_channel_retention_arg_t;

static esp_err_t sleep_gdma_channel_retention_init(void *arg)
{
gdma_channel_retention_arg_t *parg = (gdma_channel_retention_arg_t *)arg;
int group_id = parg->group_id;
int pair_id = parg->pair_id;

sleep_retention_module_bitmap_t module = GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id);
esp_err_t err = sleep_retention_entries_create(gdma_chx_regs_retention[group_id][pair_id].link_list, gdma_chx_regs_retention[group_id][pair_id].link_num, REGDMA_LINK_PRI_GDMA, module);
if (err == ESP_OK) {
ESP_LOGI(TAG, "GDMA pair (%d, %d) retention initialization", group_id, pair_id);
ESP_LOGD(TAG, "GDMA pair (%d, %d) retention initialization", group_id, pair_id);
}

ESP_RETURN_ON_ERROR(err, TAG, "Failed to create sleep retention linked list for GDMA pair (%d, %d) retention", group_id, pair_id);
return err;
}

esp_err_t gdma_sleep_retention_init(int group_id, int pair_id)
{
gdma_channel_retention_arg_t arg = { .group_id = group_id, .pair_id = pair_id };
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = sleep_gdma_channel_retention_init, .arg = &arg } },
.depends = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM)
};
sleep_retention_module_bitmap_t module = GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id);
esp_err_t err = sleep_retention_module_init(module, &init_param);
if (err == ESP_OK) {
err = sleep_retention_module_allocate(module);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Failed to allocate sleep retention linked list for GDMA retention");
}
}
return err;
}

esp_err_t gdma_sleep_retention_deinit(int group_id, int pair_id)
{
esp_err_t err = ESP_OK;
sleep_retention_entries_destroy(GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id));
esp_err_t err = sleep_retention_module_free(GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id));
if (err != ESP_OK) {
ESP_LOGW(TAG, "GDMA pair (%d, %d) retention destroy failed", group_id, pair_id);
}
err = sleep_retention_module_deinit(GDMA_CH_RETENTION_GET_MODULE_ID(group_id, pair_id));
if (err != ESP_OK) {
ESP_LOGW(TAG, "GDMA pair (%d, %d) retention deinit failed", group_id, pair_id);
}
return err;
}
8 changes: 4 additions & 4 deletions components/esp_hw_support/include/esp_private/esp_regdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,11 @@ void regdma_link_stats(void *link, int entry);
void regdma_link_set_write_wait_content(void *link, uint32_t value, uint32_t mask);

/**
* @brief Print all node information of the REGDMA linked list indicated by the entry argument
* @brief Dump all node information of the REGDMA linked list indicated by the entry argument
* @param link The REGDMA linkded list head pointer
* @param entry For nodes that support branching, use the branch specified by entry argument recursively
*/
void regdma_link_show_memories(void *link, int entry);
void regdma_link_dump(FILE *out, void *link, int entry);

/**
* @brief Update REGDMA linked list node next pointers
Expand Down Expand Up @@ -371,7 +371,7 @@ void *regdma_find_module_link_tail(void *link, void *tail, int entry, uint32_t m

/**
* @brief Find the tail node of the previous module of the specified module in the REGDMA linked list
* indicated by the entry argument starting from the link argment to the end of the tail argument
* indicated by the entry argument starting from the link argument to the end of the tail argument
* @param link The REGDMA linkded list head pointer
* @param tail The REGDMA linkded list tail pointer
* @param entry For nodes that support branching, use the branch specified by entry argument recursively
Expand All @@ -382,7 +382,7 @@ void *regdma_find_prev_module_link_tail(void *link, void *tail, int entry, uint3

/**
* @brief Find the head node of the next module of the specified module in the REGDMA linked list
* indicated by the entry argument starting from the link argment to the end of the tail argument
* indicated by the entry argument starting from the link argument to the end of the tail argument
* @param link The REGDMA linkded list head pointer
* @param tail The REGDMA linkded list tail pointer
* @param entry For nodes that support branching, use the branch specified by entry argument recursively
Expand Down
34 changes: 14 additions & 20 deletions components/esp_hw_support/include/esp_private/sleep_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,32 +42,26 @@ extern "C" {
bool clock_domain_pd_allowed(void);

/**
* @brief PCR module power down initialize
* @brief SoC system clock retention initialize.
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args
* No memory for the retention link
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM not enough memory for system clock retention
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
*/
esp_err_t sleep_clock_system_retention_init(void);
esp_err_t sleep_clock_system_retention_init(void *arg);

#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
/**
* @brief PCR module power down deinitialize
*/
void sleep_clock_system_retention_deinit(void);

/**
* @brief Modem syscon module power down initialize
* @brief Modem system clock retention initialize.
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args
* No memory for the retention link
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM not enough memory for modem clock retention
* - ESP_ERR_INVALID_ARG if either of the arguments is out of range
*/
esp_err_t sleep_clock_modem_retention_init(void);

/**
* @brief Modem syscon module power down deinitialize
*/
void sleep_clock_modem_retention_deinit(void);
esp_err_t sleep_clock_modem_retention_init(void *arg);
#endif

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 0c68b9b

Please sign in to comment.