Skip to content

Commit

Permalink
Merge branch 'feat/esp32c5_wifi_sleep' into 'master'
Browse files Browse the repository at this point in the history
esp32c5 wifi legacy sleep and modem state support

Closes WIFI-6424, WIFI-6425, PM-185, IDF-10597, and IDF-10601

See merge request espressif/esp-idf!33225
  • Loading branch information
esp-lis committed Sep 20, 2024
2 parents a71e0fc + 072ea6b commit 3edbd07
Show file tree
Hide file tree
Showing 20 changed files with 475 additions and 130 deletions.
27 changes: 24 additions & 3 deletions components/esp_hw_support/include/esp_private/sleep_modem.h
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -120,7 +120,7 @@ bool modem_domain_pd_allowed(void);
uint32_t sleep_modem_reject_triggers(void);

/**
* @brief Configure the parameters of the modem subsytem during the sleep process
* @brief Configure the parameters of the modem subsystem during the sleep process
*
* In light sleep mode, the wake-up early time of the WiFi module and the TBTT
* interrupt early time (trigger enabling RF) are determined by the maximum and
Expand All @@ -132,7 +132,7 @@ uint32_t sleep_modem_reject_triggers(void);
*
* @param max_freq_mhz the maximum frequency of system
* @param min_freq_mhz the minimum frequency of system
* @param light_sleep_enable ture or false for enable or disable light sleep mode, respectively
* @param light_sleep_enable true or false for enable or disable light sleep mode, respectively
*
* @return
* - ESP_OK on success
Expand Down Expand Up @@ -225,6 +225,27 @@ void sleep_modem_wifi_modem_state_deinit(void);
* - false not skip light sleep
*/
bool sleep_modem_wifi_modem_state_skip_light_sleep(void);

/**
* @brief Function to initialize and create the modem state phy link
* @param link_head the pointer that point to the head of the created phy link
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if no memory for link
* - ESP_ERR_INVALID_ARG if value is out of range
* - ESP_ERR_INVALID_STATE if the phy module retention state is invalid
*/
esp_err_t sleep_modem_state_phy_link_init(void **link_head);

/**
* @brief Function to destroy and de-initialize modem state phy link
* @param link_head the phy link head will be destroyed
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if value is out of range
* - ESP_ERR_INVALID_STATE if the phy module retention state is invalid
*/
esp_err_t sleep_modem_state_phy_link_deinit(void *link_head);
#endif

#ifdef __cplusplus
Expand Down
4 changes: 4 additions & 0 deletions components/esp_hw_support/lowpower/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ if((CONFIG_SOC_PM_SUPPORT_MODEM_PD OR CONFIG_SOC_PM_SUPPORT_TOP_PD) AND CONFIG_S
list(APPEND srcs "port/${target}/sleep_clock.c")
endif()

if(CONFIG_SOC_PM_SUPPORT_PMU_MODEM_STATE)
list(APPEND srcs "port/${target}/sleep_modem_state.c")
endif()

add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
35 changes: 33 additions & 2 deletions components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "esp_private/sleep_clock.h"
#include "soc/pcr_reg.h"
#include "soc/rtc.h"
#include "modem/modem_syscon_reg.h"
#include "modem/modem_lpcon_reg.h"
#include "soc/i2c_ana_mst_reg.h"
Expand All @@ -14,13 +15,43 @@ static const char *TAG = "sleep_clock";

esp_err_t sleep_clock_system_retention_init(void *arg)
{
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 74, 0, 0, 0xffffffff, 0xffffffff, 0x7f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) },
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 74, 0, 0, 0xffffffff, 0xffffffff, 0x7f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
#endif
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention");

const static sleep_retention_entries_config_t modem_ahb_config[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(3), PCR_AHB_FREQ_CONF_REG, 3, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(1) }, /* Set AHB bus frequency to 40 MHz under PMU MODEM state */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(4), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(1) },
};
err = sleep_retention_entries_create(modem_ahb_config, ARRAY_SIZE(modem_ahb_config), REGDMA_LINK_PRI_4, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention, 4 level priority");

#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP && CONFIG_XTAL_FREQ_AUTO
uint32_t xtal_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get();
if (xtal_freq_mhz == SOC_XTAL_FREQ_48M) {

/* For the 48 MHz main XTAL, we need regdma to configured BBPLL by exec
* the PHY_I2C_MST_CMD_TYPE_BBPLL_CFG command from PHY i2c master
* command memory */
sleep_retention_entries_config_t bbpll_config[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(5), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(1) }, /* I2C MST enable */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(6), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 1, 0), .owner = ENTRY(1) },
[2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PCR_LINK(7), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_BURST_DONE, 0x1, 1, 0), .owner = ENTRY(1) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(8), MODEM_LPCON_CLK_CONF_REG, 0, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = ENTRY(1) }, /* I2C MST disable */
};
extern uint32_t phy_ana_i2c_master_burst_bbpll_config(void);
bbpll_config[1].config.write_wait.value = phy_ana_i2c_master_burst_bbpll_config();
err = sleep_retention_entries_create(bbpll_config, ARRAY_SIZE(bbpll_config), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for bbpll configure, 0 level priority");
}
#endif

ESP_LOGI(TAG, "System Power, Clock and Reset sleep retention initialization");
return ESP_OK;
}
Expand Down
120 changes: 120 additions & 0 deletions components/esp_hw_support/lowpower/port/esp32c5/sleep_modem_state.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_log.h"
#include "esp_check.h"

#include "soc/soc_caps.h"
#include "soc/i2c_ana_mst_reg.h"
#include "soc/pmu_reg.h"

#include "modem/modem_syscon_reg.h"
#include "modem/modem_lpcon_reg.h"

#include "esp_private/sleep_modem.h"
#include "esp_private/sleep_retention.h"

#if SOC_PM_SUPPORT_PMU_MODEM_STATE

#define SARADC_TSENS_REG (0x6000e058)
#define SARADC_TSENS_PU (BIT(22))
#define PMU_RF_PWR_REG (0x600b0158)

#define FECOEX_SET_FREQ_SET_CHAN_REG (0x600a001c)
#define FECOEX_SET_CHAN_EN (BIT(17))
#define FECOEX_SET_FREQ_SET_CHAN_ST_REG (0x600a0028)
#define FECOEX_SET_CHAN_DONE (BIT(8))
#define FECOEX_AGC_CONF_REG (0x600a7030)
#define FECOEX_AGC_DIS (BIT(29))

#define WDEVTXQ_BLOCK (0x600A4ca8)
#define WDEV_RXBLOCK (BIT(12))
#define MODEM_FE_DATA_BASE (0x600a0400)
#define MODEM_FE_CTRL_BASE (0x600a0800)

static __attribute__((unused)) const char *TAG = "sleep";

#if SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC
static esp_err_t sleep_modem_state_phy_wifi_init(void *arg)
{
#define WIFIMAC_ENTRY() (BIT(SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC))

static sleep_retention_entries_config_t wifi_modem_config[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x00), MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN, MODEM_LPCON_CLK_I2C_MST_EN_M, 1, 0), .owner = WIFIMAC_ENTRY() }, /* I2C MST enable */

/* PMU or software to trigger enable RF PHY */
[1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x01), I2C_ANA_MST_ANA_CONF0_REG, 0x8, 0xc, 1, 0), .owner = WIFIMAC_ENTRY() }, /* BBPLL calibration enable */
[2] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x02), PMU_RF_PWR_REG, 0xf3800000, 0xf3800000, 1, 0), .owner = WIFIMAC_ENTRY() },
[3] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x03), SARADC_TSENS_REG, SARADC_TSENS_PU, 0x400000, 1, 0), .owner = WIFIMAC_ENTRY() },
[4] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x04), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 1, 0), .owner = WIFIMAC_ENTRY() },
[5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x05), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_BURST_DONE, 0x1, 1, 0), .owner = WIFIMAC_ENTRY() },
[6] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x06), FECOEX_SET_FREQ_SET_CHAN_REG, FECOEX_SET_CHAN_EN, 0x20000, 1, 0), .owner = WIFIMAC_ENTRY() },
[7] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x07), FECOEX_SET_FREQ_SET_CHAN_REG, 0, 0x20000, 1, 0), .owner = WIFIMAC_ENTRY() },
[8] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x08), FECOEX_SET_FREQ_SET_CHAN_ST_REG, FECOEX_SET_CHAN_DONE, 0x100, 1, 0), .owner = WIFIMAC_ENTRY() },
[9] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x09), MODEM_SYSCON_WIFI_BB_CFG_REG, BIT(1), 0x2, 1, 0), .owner = WIFIMAC_ENTRY() },
[10] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0a), FECOEX_AGC_CONF_REG, 0, 0x20000000, 1, 0), .owner = WIFIMAC_ENTRY() },

/* PMU to trigger enable RXBLOCK */
[11] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0b), WDEVTXQ_BLOCK, 0, 0x1000, 1, 0), .owner = WIFIMAC_ENTRY() },

/* PMU or software to trigger disable RF PHY */
[12] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0c), FECOEX_AGC_CONF_REG, FECOEX_AGC_DIS, 0x20000000, 0, 1), .owner = WIFIMAC_ENTRY() },
[13] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0d), MODEM_SYSCON_WIFI_BB_CFG_REG, 0, 0x2, 0, 1), .owner = WIFIMAC_ENTRY() },
[14] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0e), FECOEX_SET_FREQ_SET_CHAN_REG, 0, 0x20000, 0, 1), .owner = WIFIMAC_ENTRY() },
[15] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0f), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 1, 1), .owner = WIFIMAC_ENTRY() },
[16] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x10), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_BURST_DONE, 0x1, 1, 1), .owner = WIFIMAC_ENTRY() },
[17] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x11), SARADC_TSENS_REG, 0, 0x400000, 0, 1), .owner = WIFIMAC_ENTRY() },
[18] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x12), PMU_RF_PWR_REG, 0, 0xf3800000, 0, 1), .owner = WIFIMAC_ENTRY() },
[19] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x13), I2C_ANA_MST_ANA_CONF0_REG, 0x4, 0xc, 0, 1), .owner = WIFIMAC_ENTRY() }, /* BBPLL calibration disable */

[20] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x14), MODEM_LPCON_CLK_CONF_REG, 0, MODEM_LPCON_CLK_I2C_MST_EN_M, 0, 1), .owner = WIFIMAC_ENTRY() }, /* I2C MST disable */

/* PMU to trigger disable RXBLOCK */
[21] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x15), WDEVTXQ_BLOCK, 0, 0x6000, 0, 1), .owner = WIFIMAC_ENTRY() },
[22] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x16), WDEVTXQ_BLOCK, WDEV_RXBLOCK, 0x1000, 0, 1), .owner = WIFIMAC_ENTRY() },
[23] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x17), WDEVTXQ_BLOCK, 0, 0x6000, 0, 1), .owner = WIFIMAC_ENTRY() },

[24] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x18), PMU_SLP_WAKEUP_CNTL7_REG, 0x200000, 0xffff0000, 1, 0), .owner = WIFIMAC_ENTRY() },
[25] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x19), PMU_SLP_WAKEUP_CNTL7_REG, 0x9730000, 0xffff0000, 0, 1), .owner = WIFIMAC_ENTRY() }
};
extern uint32_t phy_ana_i2c_master_burst_rf_onoff(bool on);
wifi_modem_config[4].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(true);
wifi_modem_config[15].config.write_wait.value = phy_ana_i2c_master_burst_rf_onoff(false);
esp_err_t err = sleep_retention_entries_create(wifi_modem_config, ARRAY_SIZE(wifi_modem_config), 7, SLEEP_RETENTION_MODULE_MODEM_PHY);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate modem phy link for wifi modem state");
return ESP_OK;
}
#endif

esp_err_t sleep_modem_state_phy_link_init(void **link_head)
{
esp_err_t err = ESP_OK;

#if SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC
sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_modem_state_phy_wifi_init, .arg = NULL } } };
err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_MODEM_PHY, &init_param);
if (err == ESP_OK) {
err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_MODEM_PHY);
if (err == ESP_OK) {
*link_head = sleep_retention_find_link_by_id(REGDMA_PHY_LINK(0x00));
}
}
#endif
return err;
}

esp_err_t sleep_modem_state_phy_link_deinit(void *link_head)
{
esp_err_t err = ESP_OK;
#if SOC_PM_PAU_REGDMA_LINK_IDX_WIFIMAC
err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_MODEM_PHY);
if (err == ESP_OK) {
sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_MODEM_PHY);
}
#endif
return err;
}

#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */
Loading

0 comments on commit 3edbd07

Please sign in to comment.