diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 3463e7221e..d9ea2d483a 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -21,11 +21,9 @@ extern "C" { #include "hal/pmu_hal.h" #include "pmu_param.h" -#define RTC_SLEEP_PD_DIG PMU_SLEEP_PD_TOP //!< Deep sleep (power down digital domain) +#define RTC_SLEEP_PD_DIG PMU_SLEEP_PD_TOP //!< Deep sleep (power down digital domain, includes all power domains + // except CPU, Modem, LP peripheral, AON,VDDSDIO, MEM and clock power domains) #define RTC_SLEEP_PD_RTC_PERIPH PMU_SLEEP_PD_LP_PERIPH //!< Power down RTC peripherals -// #define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) //!< Power down RTC SLOW memory -// #define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory -// #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU #define RTC_SLEEP_PD_VDDSDIO PMU_SLEEP_PD_VDDSDIO //!< Power down VDDSDIO regulator #define RTC_SLEEP_PD_CPU PMU_SLEEP_PD_CPU //!< Power down CPU when in lightsleep, but not restart #define RTC_SLEEP_PD_DIG_PERIPH PMU_SLEEP_PD_HP_PERIPH //!< Power down DIG peripherals @@ -151,6 +149,13 @@ void pmu_sleep_enable_regdma_backup(void); */ void pmu_sleep_disable_regdma_backup(void); +/** + * @brief Get sleep PLL enable status + * + * @return true if PLL is enabled by PMU in modem state + */ +bool pmu_sleep_pll_already_enabled(void); + /** * @brief Calculate the hardware time overhead during sleep to compensate for sleep time * diff --git a/components/esp_hw_support/include/esp_private/esp_regdma.h b/components/esp_hw_support/include/esp_private/esp_regdma.h index 2235d83b86..85a3fe8386 100644 --- a/components/esp_hw_support/include/esp_private/esp_regdma.h +++ b/components/esp_hw_support/include/esp_private/esp_regdma.h @@ -26,6 +26,7 @@ extern "C" { #define ENTRY(n) (BIT(n)) +#define REGDMA_PHY_LINK(_pri) ((0x00 << 8) | _pri) #define REGDMA_PCR_LINK(_pri) ((0x01 << 8) | _pri) #define REGDMA_MODEMSYSCON_LINK(_pri) ((0x02 << 8) | _pri) @@ -38,6 +39,7 @@ extern "C" { #define REGDMA_IOMUX_LINK(_pri) ((0x12 << 8) | _pri) #define REGDMA_SPIMEM_LINK(_pri) ((0x13 << 8) | _pri) #define REGDMA_SYSTIMER_LINK(_pri) ((0x14 << 8) | _pri) +#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri) typedef enum { REGDMA_LINK_PRI_0 = 0, diff --git a/components/esp_hw_support/include/esp_private/sleep_modem.h b/components/esp_hw_support/include/esp_private/sleep_modem.h index ae131ba739..3ffa6d465a 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -38,6 +38,33 @@ void mac_bb_power_up_cb_execute(void); #endif // CONFIG_MAC_BB_PD +#if SOC_PM_SUPPORT_PMU_MODEM_STATE + +/** + * @brief Get WiFi modem state + * + * @return true or false for WiFi modem state is enabled or disabled + */ +bool sleep_modem_wifi_modem_state_enabled(void); + +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ + +/** + * @brief Whether to allow the Modem or TOP power domain to be powered off. + * + * In light sleep mode, only when the system can provide enough memory + * for modem (WiFi, Bluetooth, IEEE802.15.4) retention, the Modem or TOP + * power domain can be powered off. + */ +bool modem_domain_pd_allowed(void); + +/** + * @brief Get the reject trigger signal of Modem system + * + * @return the reject trigger signal of Modem system. + */ +uint32_t sleep_modem_reject_triggers(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 5d967b579d..4210a5169a 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -359,6 +359,20 @@ esp_err_t esp_sleep_enable_wifi_wakeup(void); */ esp_err_t esp_sleep_disable_wifi_wakeup(void); +/** + * @brief Enable beacon wakeup by WiFi MAC, it will wake up the system into modem state + * @return + * - ESP_OK on success + */ +esp_err_t esp_sleep_enable_wifi_beacon_wakeup(void); + +/** + * @brief Disable beacon wakeup by WiFi MAC + * @return + * - ESP_OK on success + */ +esp_err_t esp_sleep_disable_wifi_beacon_wakeup(void); + /** * @brief Get the bit mask of GPIOs which caused wakeup (ext1) * diff --git a/components/esp_hw_support/port/esp32c6/pmu_param.c b/components/esp_hw_support/port/esp32c6/pmu_param.c index 1121e91109..6d2d818419 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_param.c +++ b/components/esp_hw_support/port/esp32c6/pmu_param.c @@ -279,7 +279,7 @@ const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_m .hp_sleep2active_retention_en = 0, \ .hp_modem2active_retention_en = 0, \ .hp_sleep2active_backup_clk_sel = 0, \ - .hp_modem2active_backup_clk_sel = 0, \ + .hp_modem2active_backup_clk_sel = 1, \ .hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \ .hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \ .hp_sleep2active_backup_en = 0, \ diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index 7178601124..de07db0e36 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -77,7 +77,7 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe * |<-- PMU guard time, also the maximum time for the SOC -->| * | wake-up delay | */ -#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_AUTO_BEACON_ENABLE +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP const int rf_on_protect_time_us = mc->hp.regdma_rf_on_work_time_us; const int total_hw_wait_time_us = lp_hw_wait_time_us + hp_hw_wait_time_us + mc->hp.clock_domain_sync_time_us; #else @@ -236,6 +236,11 @@ static void pmu_sleep_param_init(pmu_context_t *ctx, const pmu_sleep_param_confi pmu_ll_set_pll_stable_wait_cycle(ctx->hal->dev, param->hp_sys.pll_stable_wait_cycle); } +bool pmu_sleep_pll_already_enabled(void) +{ + return (pmu_ll_get_sysclk_sleep_select_state(PMU_instance()->hal->dev) != 0); +} + void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp) { assert(PMU_instance()); diff --git a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h index 99846d0c5a..caff125218 100644 --- a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h +++ b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h @@ -333,7 +333,7 @@ typedef struct pmu_sleep_machine_constant { .power_up_wait_time_us = 2, \ .regdma_s2m_work_time_us = 172, \ .regdma_s2a_work_time_us = 430, \ - .regdma_m2a_work_time_us = 265, \ + .regdma_m2a_work_time_us = 239, \ .regdma_a2s_work_time_us = 338, \ .regdma_rf_on_work_time_us = 70, \ .regdma_rf_off_work_time_us = 23, \ diff --git a/components/esp_hw_support/port/esp32c6/rtc_clk.c b/components/esp_hw_support/port/esp32c6/rtc_clk.c index 72986907b4..b21523b5cb 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c6/rtc_clk.c @@ -324,6 +324,12 @@ void rtc_clk_cpu_set_to_default_config(void) rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); } +void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz) +{ + rtc_clk_cpu_freq_to_pll_mhz(cpu_freq_mhz); + clk_ll_cpu_clk_src_lock_release(); +} + rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c index cc48d28b61..1e82041597 100644 --- a/components/esp_hw_support/sleep_clock.c +++ b/components/esp_hw_support/sleep_clock.c @@ -48,12 +48,43 @@ esp_err_t sleep_clock_modem_retention_init(void) { #define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1) + #define MODEM_WIFI_RETENTION_CLOCK (MODEM_SYSCON_CLK_WIFI_APB_EN | MODEM_SYSCON_CLK_FE_APB_EN) + + #define WIFI_MAC_MODEM_STATE_CLK_EN (MODEM_SYSCON_CLK_WIFIMAC_EN | MODEM_SYSCON_CLK_WIFI_APB_EN) + #define WIFI_BB_MODEM_STATE_CLK_EN (MODEM_SYSCON_CLK_WIFIBB_22M_EN | \ + MODEM_SYSCON_CLK_WIFIBB_40M_EN | \ + MODEM_SYSCON_CLK_WIFIBB_44M_EN | \ + MODEM_SYSCON_CLK_WIFIBB_80M_EN | \ + MODEM_SYSCON_CLK_WIFIBB_40X_EN | \ + MODEM_SYSCON_CLK_WIFIBB_80X_EN | \ + MODEM_SYSCON_CLK_WIFIBB_40X1_EN | \ + MODEM_SYSCON_CLK_WIFIBB_80X1_EN | \ + MODEM_SYSCON_CLK_WIFIBB_160X1_EN) + #define FE_MODEM_STATE_CLK_EN (MODEM_SYSCON_CLK_FE_80M_EN | \ + MODEM_SYSCON_CLK_FE_160M_EN | \ + MODEM_SYSCON_CLK_FE_CAL_160M_EN | \ + MODEM_SYSCON_CLK_FE_APB_EN) + #define WIFI_MODEM_STATE_CLOCK_EN (WIFI_MAC_MODEM_STATE_CLK_EN | WIFI_BB_MODEM_STATE_CLK_EN | FE_MODEM_STATE_CLK_EN) + + const static sleep_retention_entries_config_t modem_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) } /* MODEM SYSCON */ + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(0x00), MODEM_SYSCON_CLK_CONF1_REG, 0x0, 0x200, 0, 1), .owner = ENTRY(0) }, /* WiFi MAC clock disable */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0x01), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM SYSCON */ + [2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(0x02), MODEM_SYSCON_CLK_CONF1_REG, MODEM_SYSCON_CLK_WIFIMAC_EN,0x200, 1, 0), .owner = ENTRY(0) }, /* WiFi MAC clock enable */ + [3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(0x03), MODEM_SYSCON_CLK_CONF1_REG, MODEM_WIFI_RETENTION_CLOCK, 0x10400, 0, 0), .owner = ENTRY(0) }, /* WiFi (MAC, BB and FE) retention clock enable */ + [4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(0x04), MODEM_SYSCON_CLK_CONF1_REG, WIFI_MODEM_STATE_CLOCK_EN, 0x1e7ff, 1, 0), .owner = ENTRY(1) } + }; + + const static sleep_retention_entries_config_t modem_retention_clock[] = { + [0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_MODEMSYSCON_LINK(0xff), MODEM_SYSCON_CLK_CONF1_REG, 0x0, 0x10400, 0, 0), .owner = ENTRY(0) } /* WiFi (MAC, BB and FE) retention clock disable */ }; esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_2, SLEEP_RETENTION_MODULE_CLOCK_MODEM); - ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (SYSCON) retention"); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (SYSCON) retention, 2 level priority"); + + err = sleep_retention_entries_create(modem_retention_clock, ARRAY_SIZE(modem_retention_clock), REGDMA_LINK_PRI_7, SLEEP_RETENTION_MODULE_CLOCK_MODEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (SYSCON) retention, lowest level priority"); + ESP_LOGI(TAG, "Modem Power, Clock and Reset sleep retention initialization"); return ESP_OK; } @@ -78,7 +109,10 @@ bool IRAM_ATTR clock_domain_pd_allowed(void) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP || CONFIG_MAC_BB_PD ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, BIT(0), 106) { +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP sleep_clock_system_retention_init(); +#endif + #if CONFIG_MAC_BB_PD sleep_clock_modem_retention_init(); #endif diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index 4931eb4cc1..0260383d51 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -9,14 +9,28 @@ #include #include +#include "esp_log.h" #include "esp_attr.h" #include "esp_sleep.h" #include "soc/soc_caps.h" #include "esp_private/sleep_modem.h" +#include "esp_private/sleep_retention.h" #include "sdkconfig.h" -#if CONFIG_MAC_BB_PD +#if SOC_PM_MODEM_RETENTION_BY_REGDMA +#include "modem/modem_syscon_reg.h" +#include "modem/modem_lpcon_reg.h" +#include "soc/i2c_ana_mst_reg.h" +#include "esp_pau.h" +#endif +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +#include "soc/pmu_reg.h" +#endif + +static __attribute__((unused)) const char *TAG = "sleep_modem"; + +#if CONFIG_MAC_BB_PD #define MAC_BB_POWER_DOWN_CB_NO (2) #define MAC_BB_POWER_UP_CB_NO (2) @@ -106,3 +120,149 @@ void IRAM_ATTR mac_bb_power_up_cb_execute(void) } #endif ///CONFIG_MAC_BB_PD + +#if SOC_PM_SUPPORT_PMU_MODEM_STATE + +#define PMU_RF_PWR_REG (0x600b0154) +#define SARADC_TSENS_REG (0x6000e058) +#define SARADC_TSENS_PU (BIT(22)) +#define FECOEX_SET_FREQ_SET_CHAN_REG (0x600a00c0) +#define FECOEX_SET_CHAN_EN (BIT(14)) +#define FECOEX_SET_FREQ_SET_CHAN_ST_REG (0x600a00cc) +#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) + +#define I2C_BURST_VAL(host, start, end) (((host) << 31) | ((end) << 22) | ((start) << 16)) + +typedef struct { + struct { + uint8_t start, end; /* the start and end index of phy i2c master command memory */ + uint8_t host_id; /* phy i2c master host id */ + } config[2]; +} phy_i2c_master_command_attribute_t; + +typedef struct sleep_modem_config { + struct { + void *phy_link; + } wifi; +} sleep_modem_config_t; + +static sleep_modem_config_t s_sleep_modem = { .wifi.phy_link = NULL }; + +static __attribute__((unused)) esp_err_t sleep_modem_wifi_modem_state_init(void) +{ + esp_err_t err = ESP_OK; + phy_i2c_master_command_attribute_t cmd; + + /* get RF on or off configuration info of i2c master command memory */ + extern void phy_i2c_master_mem_cfg(phy_i2c_master_command_attribute_t *); + phy_i2c_master_mem_cfg(&cmd); + + ESP_LOGD(TAG, "Modem link i2c master configuration: (%d,%d,%d), (%d,%d,%d)", cmd.config[0].host_id, cmd.config[0].start, + cmd.config[0].end, cmd.config[1].host_id, cmd.config[1].start, cmd.config[1].end); + + static regdma_link_config_t wifi_modem_config[] = { + [0] = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_FE_LINK(0), MODEM_FE_DATA_BASE, MODEM_FE_DATA_BASE, 41, 0, 0), + [1] = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEM_FE_LINK(1), MODEM_FE_CTRL_BASE, MODEM_FE_CTRL_BASE, 87, 0, 0), + + [2] = 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), /* I2C MST enable */ + [3] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x01), MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M, MODEM_LPCON_CLK_I2C_MST_SEL_160M_M, 1, 0), /* I2C MST sel 160m enable */ + + /* PMU or software to trigger enable RF PHY */ + [4] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x02), I2C_ANA_MST_ANA_CONF0_REG, 0x8, 0xc, 1, 0), /* BBPLL calibration enable */ + [5] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x03), PMU_RF_PWR_REG, 0xf0000000, 0xf0000000, 1, 0), + [6] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x04), SARADC_TSENS_REG, SARADC_TSENS_PU, 0x400000, 1, 0), + [7] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x05), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 1, 0), + [8] = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x06), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_BURST_DONE, 0x1, 1, 0), + [9] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x07), FECOEX_SET_FREQ_SET_CHAN_REG, FECOEX_SET_CHAN_EN, 0x4000, 1, 0), + [10] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x08), FECOEX_SET_FREQ_SET_CHAN_REG, 0, 0x4000, 1, 0), + [11] = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x09), FECOEX_SET_FREQ_SET_CHAN_ST_REG, FECOEX_SET_CHAN_DONE, 0x100, 1, 0), + [12] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0a), MODEM_SYSCON_WIFI_BB_CFG_REG, BIT(1), 0x2, 1, 0), + [13] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0b), FECOEX_AGC_CONF_REG, 0, 0x20000000, 1, 0), + + /* PMU to trigger enable RXBLOCK */ + [14] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0c), WDEVTXQ_BLOCK, 0, 0x1000, 1, 0), + + /* PMU or software to trigger disable RF PHY */ + [15] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0d), FECOEX_AGC_CONF_REG, FECOEX_AGC_DIS, 0x20000000, 0, 1), + [16] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0e), MODEM_SYSCON_WIFI_BB_CFG_REG, 0, 0x2, 0, 1), + [17] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x0f), FECOEX_SET_FREQ_SET_CHAN_REG, 0, 0x4000, 0, 1), + [18] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x10), I2C_ANA_MST_I2C_BURST_CONF_REG, 0, 0xffffffff, 0, 1), + [19] = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x11), I2C_ANA_MST_I2C_BURST_STATUS_REG, I2C_ANA_MST_BURST_DONE, 0x1, 0, 1), + [20] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x12), SARADC_TSENS_REG, 0, 0x400000, 0, 1), + [21] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x13), PMU_RF_PWR_REG, 0, 0xf0000000, 0, 1), + [22] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x14), I2C_ANA_MST_ANA_CONF0_REG, 0x4, 0xc, 0, 1), /* BBPLL calibration disable */ + + [23] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x15), MODEM_LPCON_CLK_CONF_REG, 0, MODEM_LPCON_CLK_I2C_MST_EN_M, 0, 1), /* I2C MST disable */ + [24] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x16), MODEM_LPCON_I2C_MST_CLK_CONF_REG, 0, MODEM_LPCON_CLK_I2C_MST_SEL_160M_M, 0, 1), /* I2C MST sel 160m disable */ + + /* PMU to trigger disable RXBLOCK */ + [25] = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x17), WDEVTXQ_BLOCK, 0, 0x6000, 0, 1), + [26] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x18), WDEVTXQ_BLOCK, WDEV_RXBLOCK, 0x1000, 0, 1), + [27] = REGDMA_LINK_WAIT_INIT (REGDMA_PHY_LINK(0x19), WDEVTXQ_BLOCK, 0, 0x6000, 0, 1), + + [28] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x1a), PMU_SLP_WAKEUP_CNTL7_REG, 0x200000, 0xffff0000, 1, 0), + [29] = REGDMA_LINK_WRITE_INIT(REGDMA_PHY_LINK(0x1b), PMU_SLP_WAKEUP_CNTL7_REG, 0x9730000, 0xffff0000, 0, 1) + }; + wifi_modem_config[7].write_wait.value = I2C_BURST_VAL(cmd.config[1].host_id, cmd.config[1].start, cmd.config[1].end); + wifi_modem_config[18].write_wait.value = I2C_BURST_VAL(cmd.config[0].host_id, cmd.config[0].start, cmd.config[0].end); + + void *link = NULL; + if (s_sleep_modem.wifi.phy_link == NULL) { + for (int i = ARRAY_SIZE(wifi_modem_config) - 1; (err == ESP_OK) && (i >= 0); i--) { + void *next = regdma_link_init_safe(&wifi_modem_config[i], false, 0, link); + if (next) { + link = next; + } else { + regdma_link_destroy(link, 0); + err = ESP_ERR_NO_MEM; + } + } + if (err == ESP_OK) { + pau_regdma_set_modem_link_addr(link); + s_sleep_modem.wifi.phy_link = link; + } + } + return err; +} + +static __attribute__((unused)) void sleep_modem_wifi_modem_state_deinit(void) +{ + if (s_sleep_modem.wifi.phy_link) { + regdma_link_destroy(s_sleep_modem.wifi.phy_link, 0); + s_sleep_modem.wifi.phy_link = NULL; + } +} + +bool sleep_modem_wifi_modem_state_enabled(void) +{ + return (s_sleep_modem.wifi.phy_link != NULL) ? true : false; +} + +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE */ + +bool IRAM_ATTR modem_domain_pd_allowed(void) +{ +#if SOC_PM_MODEM_RETENTION_BY_REGDMA + const uint32_t modules = sleep_retention_get_modules(); + const uint32_t mask = (const uint32_t) (SLEEP_RETENTION_MODULE_WIFI_MAC | SLEEP_RETENTION_MODULE_WIFI_BB); + return ((modules & mask) == mask); +#else + return false; /* MODEM power domain is controlled by each module (WiFi, Bluetooth or 15.4) of modem */ +#endif +} + + +uint32_t IRAM_ATTR sleep_modem_reject_triggers(void) +{ + uint32_t reject_triggers = 0; +#if SOC_PM_SUPPORT_PMU_MODEM_STATE + reject_triggers = (s_sleep_modem.wifi.phy_link != NULL) ? BIT(16) : 0; +#endif + return reject_triggers; +} diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 354aabda03..fa412209cc 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -25,6 +25,10 @@ #include "driver/rtc_io.h" #include "hal/rtc_io_hal.h" +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +#include "esp_private/pm_impl.h" +#endif + #if SOC_LP_AON_SUPPORTED #include "hal/lp_aon_hal.h" #else @@ -52,6 +56,7 @@ #include "esp_rom_sys.h" #include "esp_private/brownout.h" #include "esp_private/sleep_cpu.h" +#include "esp_private/sleep_modem.h" #include "esp_private/esp_clk.h" #include "esp_private/esp_task_wdt.h" @@ -66,10 +71,8 @@ #include "esp_private/gpio.h" #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/rtc.h" -#include "esp_private/sleep_modem.h" #elif CONFIG_IDF_TARGET_ESP32C3 #include "esp32c3/rom/rtc.h" -#include "esp_private/sleep_modem.h" #elif CONFIG_IDF_TARGET_ESP32H4 #include "esp32h4/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C2 @@ -80,7 +83,6 @@ #include "esp_private/esp_pmu.h" #include "esp_private/sleep_sys_periph.h" #include "esp_private/sleep_clock.h" -#include "esp_private/sleep_modem.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/cache.h" @@ -524,7 +526,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo /* Light sleep, enable sleep reject for faster return from this function, * in case the wakeup is already triggerred. */ - reject_triggers = s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK; + reject_triggers = (s_config.wakeup_triggers & RTC_SLEEP_REJECT_MASK) | sleep_modem_reject_triggers(); } //Append some flags in addition to power domains @@ -613,7 +615,14 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo } // Restore CPU frequency - rtc_clk_cpu_freq_set_config(&cpu_freq_config); +#if SOC_PM_SUPPORT_PMU_MODEM_STATE + if (pmu_sleep_pll_already_enabled()) { + rtc_clk_cpu_freq_to_pll_and_pll_lock_release(esp_pm_impl_get_cpu_freq(PM_MODE_CPU_MAX)); + } else +#endif + { + rtc_clk_cpu_freq_set_config(&cpu_freq_config); + } if (!deep_sleep) { s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); @@ -1331,6 +1340,26 @@ esp_err_t esp_sleep_disable_wifi_wakeup(void) #endif } +esp_err_t esp_sleep_enable_wifi_beacon_wakeup(void) +{ +#if SOC_PM_SUPPORT_BEACON_WAKEUP + s_config.wakeup_triggers |= PMU_WIFI_BEACON_WAKEUP_EN; + return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif +} + +esp_err_t esp_sleep_disable_wifi_beacon_wakeup(void) +{ +#if SOC_PM_SUPPORT_BEACON_WAKEUP + s_config.wakeup_triggers &= (~PMU_WIFI_BEACON_WAKEUP_EN); + return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif +} + esp_err_t esp_sleep_enable_bt_wakeup(void) { #if SOC_PM_SUPPORT_BT_WAKEUP @@ -1507,6 +1536,11 @@ static uint32_t get_power_down_flags(void) } #endif +/** + * The modules in the CPU and modem power domains still depend on the top power domain. + * To be safe, the CPU and Modem power domains must also be powered off and saved when + * the TOP is powered off. + */ #if SOC_PM_SUPPORT_TOP_PD if (!cpu_domain_pd_allowed() || !clock_domain_pd_allowed() || !peripheral_domain_pd_allowed() || !modem_domain_pd_allowed()) { diff --git a/components/esp_phy/Kconfig b/components/esp_phy/Kconfig index d9a5cd2275..f31edc8a75 100644 --- a/components/esp_phy/Kconfig +++ b/components/esp_phy/Kconfig @@ -90,7 +90,7 @@ menu "PHY" config ESP_PHY_MAC_BB_PD bool "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled" - depends on ((IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) && FREERTOS_USE_TICKLESS_IDLE) + depends on SOC_PM_SUPPORT_MAC_BB_PD && FREERTOS_USE_TICKLESS_IDLE default n help If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered diff --git a/components/esp_phy/include/esp_private/phy.h b/components/esp_phy/include/esp_private/phy.h index c8d1018288..60eea4ab44 100644 --- a/components/esp_phy/include/esp_private/phy.h +++ b/components/esp_phy/include/esp_private/phy.h @@ -13,6 +13,19 @@ extern "C" { #define ESP_CAL_DATA_CHECK_FAIL 1 +typedef enum { + PHY_I2C_MST_CMD_TYPE_OFF = 0, + PHY_I2C_MST_CMD_TYPE_ON, + PHY_I2C_MST_CMD_TYPE_MAX +} phy_i2c_master_command_type_t; + +typedef struct { + struct { + uint8_t start, end; /* the start and end index of phy i2c master command memory */ + uint8_t host_id; /* phy i2c master host id */ + } config[PHY_I2C_MST_CMD_TYPE_MAX]; +} phy_i2c_master_command_attribute_t; + /** * @file phy.h * @brief Declarations for functions provided by libphy.a @@ -75,6 +88,15 @@ void phy_xpd_tsens(void); void phy_init_flag(void); #endif +#if CONFIG_IDF_TARGET_ESP32C6 +/** + * @brief Get the configuration info of PHY i2c master command memory. + * + * @param attr the configuration info of PHY i2c master command memory + */ +void phy_i2c_master_mem_cfg(phy_i2c_master_command_attribute_t *attr); +#endif + /** * @brief Store and load PHY digital registers. * diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index 371a13ffa6..6e98168c8a 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -38,9 +38,16 @@ #if CONFIG_IDF_TARGET_ESP32 #include "soc/dport_reg.h" +#elif CONFIG_IDF_TARGET_ESP32C6 +#include "esp_private/sleep_modem.h" +#include "esp_private/esp_pau.h" #endif #include "hal/efuse_hal.h" +#if SOC_PM_MODEM_RETENTION_BY_REGDMA +#include "esp_private/sleep_retention.h" +#endif + #if CONFIG_IDF_TARGET_ESP32 extern wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb; #endif @@ -56,19 +63,9 @@ static DRAM_ATTR struct { } s_wifi_bt_pd_controller = { .count = 0 }; #endif -/* Indicate PHY is calibrated or not */ -static bool s_is_phy_calibrated = false; - -static bool s_is_phy_reg_stored = false; - /* Reference count of enabling PHY */ static uint8_t s_phy_access_ref = 0; -#if CONFIG_MAC_BB_PD -/* Reference of powering down MAC and BB */ -static bool s_mac_bb_pu = true; -#endif - #if CONFIG_IDF_TARGET_ESP32 /* time stamp updated when the PHY/RF is turned on */ static int64_t s_phy_rf_en_ts = 0; @@ -77,15 +74,17 @@ static int64_t s_phy_rf_en_ts = 0; /* PHY spinlock for libphy.a */ static DRAM_ATTR portMUX_TYPE s_phy_int_mux = portMUX_INITIALIZER_UNLOCKED; +/* Indicate PHY is calibrated or not */ +static bool s_is_phy_calibrated = false; + +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA +/* Indicate PHY regs is stored or not */ +static bool s_is_phy_reg_stored = false; /* Memory to store PHY digital registers */ static uint32_t* s_phy_digital_regs_mem = NULL; static uint8_t s_phy_modem_init_ref = 0; +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA -#if CONFIG_MAC_BB_PD -uint32_t* s_mac_bb_pd_mem = NULL; -/* Reference count of MAC BB backup memory */ -static uint8_t s_macbb_backup_mem_ref = 0; -#endif #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED @@ -212,6 +211,7 @@ IRAM_ATTR void esp_phy_common_clock_disable(void) wifi_bt_common_module_disable(); } +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA static inline void phy_digital_regs_store(void) { if (s_phy_digital_regs_mem != NULL) { @@ -226,6 +226,7 @@ static inline void phy_digital_regs_load(void) phy_dig_reg_backup(false, s_phy_digital_regs_mem); } } +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA void esp_phy_enable(void) { @@ -245,8 +246,22 @@ void esp_phy_enable(void) s_is_phy_calibrated = true; } else { +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + extern bool pm_mac_modem_rf_already_enabled(void); + if (!pm_mac_modem_rf_already_enabled()) { + if (sleep_modem_wifi_modem_state_enabled()) { + pau_regdma_trigger_modem_link_restore(); + } else { + phy_wakeup_init(); + } + } +#else phy_wakeup_init(); +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP */ + +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA phy_digital_regs_load(); +#endif } #if CONFIG_IDF_TARGET_ESP32 @@ -264,13 +279,22 @@ void esp_phy_disable(void) s_phy_access_ref--; if (s_phy_access_ref == 0) { +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA phy_digital_regs_store(); - // Disable PHY and RF. - phy_close_rf(); -#if !CONFIG_IDF_TARGET_ESP32 - // Disable PHY temperature sensor - phy_xpd_tsens(); #endif +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + if (sleep_modem_wifi_modem_state_enabled()) { + pau_regdma_trigger_modem_link_backup(); + } else +#endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP */ + { + // Disable PHY and RF. + phy_close_rf(); +#if !CONFIG_IDF_TARGET_ESP32 + // Disable PHY temperature sensor + phy_xpd_tsens(); +#endif + } #if CONFIG_IDF_TARGET_ESP32 // Update WiFi MAC time before disalbe WiFi/BT common peripheral clock phy_update_wifi_mac_time(true, esp_timer_get_time()); @@ -312,19 +336,19 @@ void esp_wifi_bt_power_domain_off(void) void esp_phy_modem_init(void) { +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA _lock_acquire(&s_phy_access_lock); - s_phy_modem_init_ref++; if (s_phy_digital_regs_mem == NULL) { s_phy_digital_regs_mem = (uint32_t *)heap_caps_malloc(SOC_PHY_DIG_REGS_MEM_SIZE, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); } - _lock_release(&s_phy_access_lock); - +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA } void esp_phy_modem_deinit(void) { +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA _lock_acquire(&s_phy_access_lock); s_phy_modem_init_ref--; @@ -341,50 +365,76 @@ void esp_phy_modem_deinit(void) } _lock_release(&s_phy_access_lock); +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA } #if CONFIG_MAC_BB_PD +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA +static uint32_t* s_mac_bb_pd_mem = NULL; +/* Reference count of MAC BB backup memory */ +static uint8_t s_macbb_backup_mem_ref = 0; +/* Reference of powering down MAC and BB */ +static bool s_mac_bb_pu = true; +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA + void esp_mac_bb_pd_mem_init(void) { +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA _lock_acquire(&s_phy_access_lock); - s_macbb_backup_mem_ref++; if (s_mac_bb_pd_mem == NULL) { s_mac_bb_pd_mem = (uint32_t *)heap_caps_malloc(SOC_MAC_BB_PD_MEM_SIZE, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); } - _lock_release(&s_phy_access_lock); +#elif SOC_PM_MODEM_RETENTION_BY_REGDMA + const static sleep_retention_entries_config_t bb_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b00, 0x600a7000, 0x600a7000, 121, 0, 0), .owner = BIT(0) | BIT(1) }, /* AGC */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b01, 0x600a7400, 0x600a7400, 14, 0, 0), .owner = BIT(0) | BIT(1) }, /* TX */ + [2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b02, 0x600a7800, 0x600a7800, 136, 0, 0), .owner = BIT(0) | BIT(1) }, /* NRX */ + [3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b03, 0x600a7c00, 0x600a7c00, 53, 0, 0), .owner = BIT(0) | BIT(1) }, /* BB */ + [4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(0x0b05, 0x600a0000, 0x600a0000, 58, 0, 0), .owner = BIT(0) | BIT(1) } /* FE COEX */ + }; + esp_err_t err = sleep_retention_entries_create(bb_regs_retention, ARRAY_SIZE(bb_regs_retention), 3, SLEEP_RETENTION_MODULE_WIFI_BB); + if (err != ESP_OK) { + ESP_LOGW(TAG, "failed to allocate memory for WiFi baseband retention"); + } +#endif } void esp_mac_bb_pd_mem_deinit(void) { +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA _lock_acquire(&s_phy_access_lock); - s_macbb_backup_mem_ref--; if (s_macbb_backup_mem_ref == 0) { free(s_mac_bb_pd_mem); s_mac_bb_pd_mem = NULL; } - _lock_release(&s_phy_access_lock); +#elif SOC_PM_MODEM_RETENTION_BY_REGDMA + sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_WIFI_BB); +#endif } IRAM_ATTR void esp_mac_bb_power_up(void) { + esp_wifi_bt_power_domain_on(); +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA if (s_mac_bb_pd_mem == NULL) { return; } - esp_wifi_bt_power_domain_on(); if (!s_mac_bb_pu) { esp_phy_common_clock_enable(); phy_freq_mem_backup(false, s_mac_bb_pd_mem); esp_phy_common_clock_disable(); s_mac_bb_pu = true; } +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA } IRAM_ATTR void esp_mac_bb_power_down(void) { +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA if (s_mac_bb_pd_mem == NULL) { return; } @@ -394,9 +444,10 @@ IRAM_ATTR void esp_mac_bb_power_down(void) esp_phy_common_clock_disable(); s_mac_bb_pu = false; } +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA esp_wifi_bt_power_domain_off(); } -#endif +#endif // CONFIG_MAC_BB_PD // PHY init data handling functions #if CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index b56346ba81..74f65fd5b2 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -292,6 +292,11 @@ esp_err_t esp_pm_configure(const void* vconfig) } #endif +#if CONFIG_ESP_WIFI_AUTO_BEACON_ENABLE + extern int esp_wifi_internal_mac_sleep_configure(bool, bool); + esp_wifi_internal_mac_sleep_configure(config->light_sleep_enable, true); +#endif + #if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT if (config->light_sleep_enable) { esp_pm_light_sleep_default_params_config(min_freq_mhz, max_freq_mhz); diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 12e627e2e8..d8eb6b97fd 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -338,6 +338,13 @@ menu "Wi-Fi" help WiFi module can be compiled without SoftAP to save code size. + config ESP_WIFI_AUTO_BEACON_ENABLE + bool "WiFi modem automatically receives the beacon" + default n + depends on ESP_PHY_MAC_BB_PD + help + The wifi modem automatically receives the beacon frame during light sleep. + config ESP_WIFI_SLP_BEACON_LOST_OPT bool "Wifi sleep optimize when beacon lost" help diff --git a/components/esp_wifi/esp32c2/esp_adapter.c b/components/esp_wifi/esp32c2/esp_adapter.c index a6dfd46059..e370d19de9 100644 --- a/components/esp_wifi/esp32c2/esp_adapter.c +++ b/components/esp_wifi/esp32c2/esp_adapter.c @@ -295,20 +295,6 @@ static void wifi_reset_mac_wrapper(void) periph_module_reset(PERIPH_WIFI_MODULE); } -static void IRAM_ATTR wifi_rtc_enable_iso_wrapper(void) -{ -#if CONFIG_MAC_BB_PD - esp_mac_bb_power_down(); -#endif -} - -static void IRAM_ATTR wifi_rtc_disable_iso_wrapper(void) -{ -#if CONFIG_MAC_BB_PD - esp_mac_bb_power_up(); -#endif -} - static void wifi_clock_enable_wrapper(void) { wifi_module_enable(); @@ -603,8 +589,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._wifi_reset_mac = wifi_reset_mac_wrapper, ._wifi_clock_enable = wifi_clock_enable_wrapper, ._wifi_clock_disable = wifi_clock_disable_wrapper, - ._wifi_rtc_enable_iso = wifi_rtc_enable_iso_wrapper, - ._wifi_rtc_disable_iso = wifi_rtc_disable_iso_wrapper, + ._wifi_rtc_enable_iso = esp_empty_wrapper, + ._wifi_rtc_disable_iso = esp_empty_wrapper, ._esp_timer_get_time = esp_timer_get_time, ._nvs_set_i8 = nvs_set_i8, ._nvs_get_i8 = nvs_get_i8, diff --git a/components/esp_wifi/esp32c6/esp_adapter.c b/components/esp_wifi/esp32c6/esp_adapter.c index 86cc1b7005..4aa2658404 100644 --- a/components/esp_wifi/esp32c6/esp_adapter.c +++ b/components/esp_wifi/esp32c6/esp_adapter.c @@ -43,6 +43,11 @@ #include "esp32c6/rom/ets_sys.h" #include "esp_modem_wrapper.h" +#if SOC_PM_MODEM_RETENTION_BY_REGDMA +#include "esp_private/esp_regdma.h" +#include "esp_private/sleep_retention.h" +#endif + #define TAG "esp_adapter" #ifdef CONFIG_PM_ENABLE @@ -295,18 +300,6 @@ static void wifi_reset_mac_wrapper(void) ESP_LOGW(TAG, "wifi_reset_mac_wrapper() has not been implemented yet"); } -static void IRAM_ATTR wifi_rtc_enable_iso_wrapper(void) -{ - // TODO: IDF-5351 - ESP_LOGW(TAG, "wifi_rtc_enable_iso_wrapper() has not been implemented yet"); -} - -static void IRAM_ATTR wifi_rtc_disable_iso_wrapper(void) -{ - // TODO: IDF-5351 - ESP_LOGW(TAG, "wifi_rtc_disable_iso_wrapper() has not been implemented yet"); -} - static void wifi_clock_enable_wrapper(void) { wifi_module_enable(); @@ -601,8 +594,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._wifi_reset_mac = wifi_reset_mac_wrapper, ._wifi_clock_enable = wifi_clock_enable_wrapper, ._wifi_clock_disable = wifi_clock_disable_wrapper, - ._wifi_rtc_enable_iso = wifi_rtc_enable_iso_wrapper, - ._wifi_rtc_disable_iso = wifi_rtc_disable_iso_wrapper, + ._wifi_rtc_enable_iso = esp_empty_wrapper, + ._wifi_rtc_disable_iso = esp_empty_wrapper, ._esp_timer_get_time = esp_timer_get_time, ._nvs_set_i8 = nvs_set_i8, ._nvs_get_i8 = nvs_get_i8, @@ -651,8 +644,7 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper, ._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper, ._coex_register_start_cb = coex_register_start_cb_wrapper, -#if 0//CONFIG_IDF_TARGET_ESP32C6 - // TODO: WIFI-5150 +#if SOC_PM_MODEM_RETENTION_BY_REGDMA ._regdma_link_set_write_wait_content = regdma_link_set_write_wait_content, ._sleep_retention_find_link_by_id = sleep_retention_find_link_by_id, ._sleep_retention_entries_create = (int (*)(const void *, int, int, int))sleep_retention_entries_create, diff --git a/components/esp_wifi/include/esp_private/wifi_os_adapter.h b/components/esp_wifi/include/esp_private/wifi_os_adapter.h index d23cbdeacb..9cd909538c 100644 --- a/components/esp_wifi/include/esp_private/wifi_os_adapter.h +++ b/components/esp_wifi/include/esp_private/wifi_os_adapter.h @@ -143,7 +143,7 @@ typedef struct { uint8_t (* _coex_schm_curr_period_get)(void); void * (* _coex_schm_curr_phase_get)(void); int (* _coex_register_start_cb)(int (* cb)(void)); -#if CONFIG_IDF_TARGET_ESP32C6 +#if SOC_PM_MODEM_RETENTION_BY_REGDMA void (* _regdma_link_set_write_wait_content)(void *, uint32_t, uint32_t); void * (* _sleep_retention_find_link_by_id)(int); int (* _sleep_retention_entries_create)(const void *, int, int, int); diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 2e1d0db691..d787b3f66d 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -123,8 +123,11 @@ esp_err_t esp_wifi_deinit(void) esp_pm_unregister_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active); esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time); esp_sleep_disable_wifi_wakeup(); -#endif -#endif +# if CONFIG_ESP_WIFI_AUTO_BEACON_ENABLE + esp_sleep_disable_wifi_beacon_wakeup(); +# endif +#endif /* SOC_WIFI_HW_TSF */ +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ #if CONFIG_MAC_BB_PD esp_unregister_mac_bb_pd_callback(pm_mac_sleep); esp_unregister_mac_bb_pu_callback(pm_mac_wakeup); @@ -236,11 +239,14 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) return ret; } esp_sleep_enable_wifi_wakeup(); +# if CONFIG_ESP_WIFI_AUTO_BEACON_ENABLE + esp_sleep_enable_wifi_beacon_wakeup(); +# endif #if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE coex_wifi_register_update_lpclk_callback(esp_wifi_update_tsf_tick_interval); #endif -#endif -#endif +#endif /* SOC_WIFI_HW_TSF */ +#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ #if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE coex_init(); diff --git a/components/hal/esp32c6/include/hal/clk_tree_ll.h b/components/hal/esp32c6/include/hal/clk_tree_ll.h index 8f8cfaa5ae..8b6199968e 100644 --- a/components/hal/esp32c6/include/hal/clk_tree_ll.h +++ b/components/hal/esp32c6/include/hal/clk_tree_ll.h @@ -78,6 +78,14 @@ static inline __attribute__((always_inline)) void clk_ll_bbpll_disable(void) SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_REG, PMU_TIE_LOW_XPD_BBPLL | PMU_TIE_LOW_XPD_BBPLL_I2C); } +/** + * @brief Release the root clock source locked by PMU + */ +static inline __attribute__((always_inline)) void clk_ll_cpu_clk_src_lock_release(void) +{ + SET_PERI_REG_MASK(PMU_IMM_SLEEP_SYSCLK_REG, PMU_UPDATE_DIG_SYS_CLK_SEL); +} + /** * @brief Enable the 32kHz crystal oscillator * diff --git a/components/hal/esp32c6/include/hal/pmu_ll.h b/components/hal/esp32c6/include/hal/pmu_ll.h index 6e74944f48..b5cc2b3193 100644 --- a/components/hal/esp32c6/include/hal/pmu_ll.h +++ b/components/hal/esp32c6/include/hal/pmu_ll.h @@ -661,6 +661,11 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t * return hw->power.wait_timer0.powerup_timer; } +static inline uint32_t pmu_ll_get_sysclk_sleep_select_state(pmu_dev_t *hw) +{ + return hw->clk_state0.sysclk_slp_sel; +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c6/include/soc/i2c_ana_mst_reg.h b/components/soc/esp32c6/include/soc/i2c_ana_mst_reg.h new file mode 100644 index 0000000000..0f94765f8f --- /dev/null +++ b/components/soc/esp32c6/include/soc/i2c_ana_mst_reg.h @@ -0,0 +1,104 @@ +/** + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2C_ANA_MST_I2C0_CTRL_REG (DR_REG_I2C_ANA_MST_BASE + 0x0000) +#define I2C_ANA_MST_I2C0_BUSY (BIT(25)) +#define I2C_ANA_MST_I2C0_BUSY_S 25 +#define I2C_ANA_MST_I2C0_CTRL 0x01FFFFFF +#define I2C_ANA_MST_I2C0_CTRL_S 0 + +#define I2C_ANA_MST_I2C1_CTRL_REG (DR_REG_I2C_ANA_MST_BASE + 0x0004) +#define I2C_ANA_MST_I2C1_BUSY (BIT(25)) +#define I2C_ANA_MST_I2C1_BUSY_S 25 +#define I2C_ANA_MST_I2C1_CTRL 0x01FFFFFF +#define I2C_ANA_MST_I2C1_CTRL_S 0 + +#define I2C_ANA_MST_I2C0_CONF_REG (DR_REG_I2C_ANA_MST_BASE + 0x0008) +#define I2C_ANA_MST_I2C0_STATUS 0x000000FF +#define I2C_ANA_MST_I2C0_STATUS_S 24 +#define I2C_ANA_MST_I2C0_CONF 0x00FFFFFF +#define I2C_ANA_MST_I2C0_CONF_S 0 + +#define I2C_ANA_MST_I2C1_CONF_REG (DR_REG_I2C_ANA_MST_BASE + 0x000C) +#define I2C_ANA_MST_I2C1_STATUS 0x000000FF +#define I2C_ANA_MST_I2C1_STATUS_S 24 +#define I2C_ANA_MST_I2C1_CONF 0x00FFFFFF +#define I2C_ANA_MST_I2C1_CONF_S 0 + +#define I2C_ANA_MST_I2C_BURST_CONF_REG (DR_REG_I2C_ANA_MST_BASE + 0x0010) +#define I2C_ANA_MST_BURST_CTRL 0xFFFFFFFF +#define I2C_ANA_MST_BURST_CTRL_S 0 + +#define I2C_ANA_MST_I2C_BURST_STATUS_REG (DR_REG_I2C_ANA_MST_BASE + 0x0014) +#define I2C_ANA_MST_BURST_TIMEOUT_CNT 0x00000FFF +#define I2C_ANA_MST_BURST_TIMEOUT_CNT_S 20 +#define I2C_ANA_MST1_BURST_ERR_FLAG (BIT(2)) +#define I2C_ANA_MST1_BURST_ERR_FLAG_S 2 +#define I2C_ANA_MST0_BURST_ERR_FLAG (BIT(1)) +#define I2C_ANA_MST0_BURST_ERR_FLAG_S 1 +#define I2C_ANA_MST_BURST_DONE (BIT(0)) +#define I2C_ANA_MST_BURST_DONE_S 0 + +#define I2C_ANA_MST_ANA_CONF0_REG (DR_REG_I2C_ANA_MST_BASE + 0x0018) +#define I2C_ANA_MST_ANA_STATUS0 0x000000FF +#define I2C_ANA_MST_ANA_STATUS0_S 24 +#define I2C_ANA_MST_ANA_CONF0 0x00FFFFFF +#define I2C_ANA_MST_ANA_CONF0_S 0 + +#define I2C_ANA_MST_ANA_CONF1_REG (DR_REG_I2C_ANA_MST_BASE + 0x001C) +#define I2C_ANA_MST_ANA_STATUS1 0x000000FF +#define I2C_ANA_MST_ANA_STATUS1_S 24 +#define I2C_ANA_MST_ANA_CONF1 0x00FFFFFF +#define I2C_ANA_MST_ANA_CONF1_S 0 + +#define I2C_ANA_MST_ANA_CONF2_REG (DR_REG_I2C_ANA_MST_BASE + 0x0020) +#define I2C_ANA_MST_ANA_STATUS2 0x000000FF +#define I2C_ANA_MST_ANA_STATUS2_S 24 +#define I2C_ANA_MST_ANA_CONF2 0x00FFFFFF +#define I2C_ANA_MST_ANA_CONF2_S 0 + +#define I2C_ANA_MST_I2C0_CTRL1_REG (DR_REG_I2C_ANA_MST_BASE + 0x0024) +#define I2C_ANA_MST_I2C0_SDA_SIDE_GUARD 0x0000001F +#define I2C_ANA_MST_I2C0_SDA_SIDE_GUARD_S 6 +#define I2C_ANA_MST_I2C0_SCL_PULSE_DUR 0x0000003F +#define I2C_ANA_MST_I2C0_SCL_PULSE_DUR_S 0 + +#define I2C_ANA_MST_I2C1_CTRL1_REG (DR_REG_I2C_ANA_MST_BASE + 0x0028) +#define I2C_ANA_MST_I2C1_SDA_SIDE_GUARD 0x0000001F +#define I2C_ANA_MST_I2C1_SDA_SIDE_GUARD_S 6 +#define I2C_ANA_MST_I2C1_SCL_PULSE_DUR 0x0000003F +#define I2C_ANA_MST_I2C1_SCL_PULSE_DUR_S 0 + +#define I2C_ANA_MST_HW_I2C_CTRL_REG (DR_REG_I2C_ANA_MST_BASE + 0x002C) +#define I2C_ANA_MST_ARBITER_DIS (BIT(11)) +#define I2C_ANA_MST_ARBITER_DIS_S 11 +#define I2C_ANA_MST_HW_I2C_SDA_SIDE_GUARD 0x0000001F +#define I2C_ANA_MST_HW_I2C_SDA_SIDE_GUARD_S 6 +#define I2C_ANA_MST_HW_I2C_SCL_PULSE_DUR 0x0000003F +#define I2C_ANA_MST_HW_I2C_SCL_PULSE_DUR_S 0 + +#define I2C_ANA_MST_NOUSE_REG (DR_REG_I2C_ANA_MST_BASE + 0x0030) +#define I2C_ANA_MST_NOUSE 0xFFFFFFFF +#define I2C_ANA_MST_NOUSE_S 0 + +#define I2C_ANA_MST_DATE_REG (DR_REG_I2C_ANA_MST_BASE + 0x0034) +#define I2C_ANA_MST_CLK_EN (BIT(28)) +#define I2C_ANA_MST_CLK_EN_S 28 +#define I2C_ANA_MST_DATE 0x0FFFFFFF +#define I2C_ANA_MST_DATE_S 0 + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32c6/include/soc/reg_base.h b/components/soc/esp32c6/include/soc/reg_base.h index d08aed17c6..4575659382 100644 --- a/components/soc/esp32c6/include/soc/reg_base.h +++ b/components/soc/esp32c6/include/soc/reg_base.h @@ -55,6 +55,8 @@ #define DR_REG_LP_APM0_BASE 0x60099800 #define DR_REG_MISC_BASE 0x6009F000 +#define DR_REG_I2C_ANA_MST_BASE 0x600AF800 + #define DR_REG_PMU_BASE 0x600B0000 #define DR_REG_LP_CLKRST_BASE 0x600B0400 #define DR_REG_EFUSE_BASE 0x600B0800 diff --git a/components/soc/esp32c6/include/soc/rtc.h b/components/soc/esp32c6/include/soc/rtc.h index 407e6d636e..3458c33ce7 100644 --- a/components/soc/esp32c6/include/soc/rtc.h +++ b/components/soc/esp32c6/include/soc/rtc.h @@ -372,6 +372,19 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); */ void rtc_clk_cpu_freq_set_xtal(void); +/** + * @brief Switch root clock source to PLL (only used by sleep) release root clock source locked by PMU + * + * wifi receiving beacon frame in PMU modem state strongly depends on the BBPLL + * clock, PMU will forcibly lock the root clock source as PLL, when the root + * clock source of the software system is selected as PLL, we need to release + * the root clock source locking and switch the root clock source to PLL in the + * sleep process (a critical section). + * + * @param[in] Maximum CPU frequency, in MHz + */ +void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz); + /** * @brief Get the current APB frequency. * @return The calculated APB frequency value, in Hz.