diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index e6ad10abd1..eec66402a3 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -23,7 +23,7 @@ if(NOT BOOTLOADER_BUILD) "rtc_module.c" "sleep_modes.c" "sleep_gpio.c" - "sleep_mac_bb.c" + "sleep_modem.c" "regi2c_ctrl.c" "port/${target}/io_mux.c" "port/${target}/clk_tree.c" @@ -38,7 +38,7 @@ if(NOT BOOTLOADER_BUILD) endif() if(CONFIG_SOC_PAU_SUPPORTED) - list(APPEND srcs "sleep_retention.c" "sleep_peripheral.c" "sleep_clock.c") + list(APPEND srcs "sleep_retention.c" "sleep_system_peripheral.c" "sleep_clock.c") endif() # [refactor-todo]: requires "driver" for GPIO and RTC (by sleep_gpio and sleep_modes) 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_cpu.h b/components/esp_hw_support/include/esp_private/sleep_cpu.h index 0e05797443..49ed6d5a45 100644 --- a/components/esp_hw_support/include/esp_private/sleep_cpu.h +++ b/components/esp_hw_support/include/esp_private/sleep_cpu.h @@ -28,6 +28,16 @@ extern "C" { */ bool cpu_domain_pd_allowed(void); +/** + * @brief Configure the parameters of the CPU domain during the sleep process + * + * @param light_sleep_enable true for enable light sleep mode, false for disable light sleep mode + * + * @return + * - ESP_OK on success + */ +esp_err_t sleep_cpu_configure(bool light_sleep_enable); + #endif #if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL diff --git a/components/esp_hw_support/include/esp_private/sleep_mac_bb.h b/components/esp_hw_support/include/esp_private/sleep_mac_bb.h deleted file mode 100644 index 6b4019639d..0000000000 --- a/components/esp_hw_support/include/esp_private/sleep_mac_bb.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once -#include -#include "sdkconfig.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file sleep_mac_bb.h - * - * This file contains declarations of MAC and baseband power consumption related functions in light sleep mode. - */ - -#if CONFIG_MAC_BB_PD - -/** - * @brief A callback function completes MAC and baseband power down operation - * - * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband - * power down and backup register configuration information operations. - */ -void mac_bb_power_down_cb_execute(void); - -/** - * @brief A callback function completes MAC and baseband power up operation - * - * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband - * power up and restore register configuration information operations. - */ -void mac_bb_power_up_cb_execute(void); - -#endif // CONFIG_MAC_BB_PD - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_hw_support/include/esp_private/sleep_modem.h b/components/esp_hw_support/include/esp_private/sleep_modem.h new file mode 100644 index 0000000000..7e11d88a9e --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -0,0 +1,152 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include +#include "sdkconfig.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_modem.h + * + * This file contains declarations of MAC and baseband power consumption related functions in light sleep mode. + */ + +#if CONFIG_MAC_BB_PD + +/** + * @brief A callback function completes MAC and baseband power down operation + * + * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband + * power down and backup register configuration information operations. + */ +void mac_bb_power_down_cb_execute(void); + +/** + * @brief A callback function completes MAC and baseband power up operation + * + * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband + * power up and restore register configuration information operations. + */ +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 the current target allows Modem or the TOP power domain to be powered off during light sleep + * + * During light sleep on some targets, it is possible to power OFF the Modem or TOP + * power domains in order to further lower power power consumption. However, this + * can only occur on targets that support REGDMA for modem (WiFi, Bluetooth, + * IEEE802.15.4) retention. + */ +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); + +/** + * @brief Configure the parameters of the modem subsytem 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 + * minimum frequency of system (higher system frequency means less time to wake + * up and enable RF). + * For the esp32c6 SOC, the modem state is strongly dependent on the light sleep + * mode, and the modem state will be enabled only when light sleep is enabled + * and the `CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP` is configured in menuconfig. + * + * @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 + * + * @return + * - ESP_OK on success + */ +esp_err_t sleep_modem_configure(int max_freq_mhz, int min_freq_mhz, bool light_sleep_enable); + +/** + * @brief Callback function type for peripherals to know light sleep wakeup overhead. + * + */ +typedef void (* inform_out_light_sleep_overhead_cb_t)(uint32_t); + +/** + * @brief Register informing peripherals light sleep wakeup overhead time callback + * + * This function allows you to register a callback that informs the peripherals of + * the wakeup overhead time of light sleep. + * @param cb function to inform time + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if no more callback slots are available + */ +esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb); + +/** + * @brief Unregister informing peripherals light sleep wakeup overhead time callback + * + * This function allows you to unregister a callback that informs the peripherals of + * the wakeup overhead time of light sleep. + * @param cb function to inform time + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if the given callback hasn't been registered before + */ +esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb); + +/** + * @brief A callback that informs the peripherals of the wakeup overhead time of light sleep + * + * @param out_light_sleep_time wakeup overhead time of light sleep + */ +void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time); + +/** + * @brief Callback function type for peripherals to know light sleep default parameters + */ +typedef void (* update_light_sleep_default_params_config_cb_t)(int, int); + +/** + * @brief Register peripherals light sleep default parameters configure callback + * + * This function allows you to register a callback that configure the peripherals + * of default parameters of light sleep + * @param cb function to update default parameters + */ +void esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t cb); + +/** + * @brief Unregister peripherals light sleep default parameters configure Callback + * + * This function allows you to unregister a callback that configure the peripherals + * of default parameters of light sleep + */ +void esp_pm_unregister_light_sleep_default_params_config_callback(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_private/sleep_peripheral.h b/components/esp_hw_support/include/esp_private/sleep_sys_periph.h similarity index 87% rename from components/esp_hw_support/include/esp_private/sleep_peripheral.h rename to components/esp_hw_support/include/esp_private/sleep_sys_periph.h index 5c16a5110a..ee4af519ce 100644 --- a/components/esp_hw_support/include/esp_private/sleep_peripheral.h +++ b/components/esp_hw_support/include/esp_private/sleep_sys_periph.h @@ -14,7 +14,7 @@ extern "C" { #endif /** - * @file sleep_peripheral.h + * @file sleep_sys_periph.h * * This file contains declarations of digital peripheral retention related functions in light sleep mode. */ @@ -30,13 +30,13 @@ extern "C" { bool peripheral_domain_pd_allowed(void); /** - * @brief Digital peripheral power down initialize\ + * @brief Digital peripheral power down initialize * * @return ESP_OK on success * ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args * No memory for the retention link */ -void sleep_peripheral_retention_init(void); +void sleep_sys_periph_retention_init(void); #ifdef __cplusplus } diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index ed23aac6b5..4210a5169a 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -62,6 +62,9 @@ typedef enum { #if SOC_PM_SUPPORT_VDDSDIO_PD ESP_PD_DOMAIN_VDDSDIO, //!< VDD_SDIO #endif +#if SOC_PM_SUPPORT_MODEM_PD + ESP_PD_DOMAIN_MODEM, //!< MODEM, includes WiFi, Bluetooth and IEEE802.15.4 +#endif #if SOC_PM_SUPPORT_TOP_PD ESP_PD_DOMAIN_TOP, //!< SoC TOP #endif @@ -356,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/linker.lf b/components/esp_hw_support/linker.lf index 2a06811a95..864467b6fb 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -20,6 +20,8 @@ entries: rtc_time (noflash_text) if SOC_PMU_SUPPORTED = y: pmu_sleep (noflash) + if PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32 = n: + sleep_modem:periph_inform_out_light_sleep_overhead (noflash) if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y: rtc_wdt (noflash_text) if PERIPH_CTRL_FUNC_IN_IRAM = y: 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 90f00dc130..de07db0e36 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -44,21 +44,21 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_pe const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc; /* LP core hardware wait time, microsecond */ - const int lp_wakeup_wait_time = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period); - const int lp_clk_switch_time = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period); - const int lp_clk_power_on_wait_time = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_ms \ + const int lp_wakeup_wait_time_us = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period); + const int lp_clk_switch_time_us = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period); + const int lp_clk_power_on_wait_time_us = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_us \ : rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period); - const int lp_hw_wait_time = mc->lp.min_slp_time_ms + mc->lp.analog_wait_time_ms + lp_clk_power_on_wait_time \ - + lp_wakeup_wait_time + lp_clk_switch_time + mc->lp.power_supply_wait_time_ms \ - + mc->lp.power_up_wait_time_ms; + const int lp_hw_wait_time_us = mc->lp.min_slp_time_us + mc->lp.analog_wait_time_us + lp_clk_power_on_wait_time_us \ + + lp_wakeup_wait_time_us + lp_clk_switch_time_us + mc->lp.power_supply_wait_time_us \ + + mc->lp.power_up_wait_time_us; /* HP core hardware wait time, microsecond */ - const int hp_digital_power_up_wait_time_ms = mc->hp.power_supply_wait_time_ms + mc->hp.power_up_wait_time_ms; - const int hp_regdma_wait_time = MAX(mc->hp.regdma_s2m_work_time_ms + mc->hp.regdma_m2a_work_time_ms, mc->hp.regdma_s2a_work_time_ms); - const int hp_clock_wait_time = mc->hp.xtal_wait_stable_time_ms + mc->hp.pll_wait_stable_time_ms; + const int hp_digital_power_up_wait_time_us = mc->hp.power_supply_wait_time_us + mc->hp.power_up_wait_time_us; + const int hp_regdma_wait_time_us = MAX(mc->hp.regdma_s2m_work_time_us + mc->hp.regdma_m2a_work_time_us, mc->hp.regdma_s2a_work_time_us); + const int hp_clock_wait_time_us = mc->hp.xtal_wait_stable_time_us + mc->hp.pll_wait_stable_time_us; - const int hp_hw_wait_time = mc->hp.analog_wait_time_ms + MAX(hp_digital_power_up_wait_time_ms + hp_regdma_wait_time, hp_clock_wait_time); + const int hp_hw_wait_time_us = mc->hp.analog_wait_time_us + MAX(hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us, hp_clock_wait_time_us); /* When the SOC wakeup (lp timer or GPIO wakeup) and Modem wakeup (Beacon wakeup) complete, the soc * wakeup will be delayed until the RF is turned on in Modem state. @@ -77,14 +77,14 @@ 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 - const int rf_on_protect_time = mc->hp.regdma_rf_on_work_time_ms; - const int total_hw_wait_time = lp_hw_wait_time + hp_hw_wait_time + mc->hp.clock_domain_sync_time_ms; +#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 - const int rf_on_protect_time = 0; - const int total_hw_wait_time = lp_hw_wait_time + hp_hw_wait_time; + const int rf_on_protect_time_us = 0; + const int total_hw_wait_time_us = lp_hw_wait_time_us + hp_hw_wait_time_us; #endif - return total_hw_wait_time + rf_on_protect_time; + return total_hw_wait_time_us + rf_on_protect_time_us; } #define rtc_time_us_to_fastclk(time_us, period) rtc_time_us_to_slowclk((time_us), (period)) @@ -100,26 +100,26 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default( { const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc; - param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_ms, slowclk_period); - param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_ms, fastclk_period); - param->hp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_supply_wait_time_ms, fastclk_period); - param->hp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_up_wait_time_ms, fastclk_period); - param->hp_sys.pll_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.pll_wait_stable_time_ms, fastclk_period); + param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period); + param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_us, fastclk_period); + param->hp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_supply_wait_time_us, fastclk_period); + param->hp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_up_wait_time_us, fastclk_period); + param->hp_sys.pll_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.pll_wait_stable_time_us, fastclk_period); - const int hw_wait_time = pmu_sleep_calculate_hw_wait_time(pd_flags, slowclk_period, fastclk_period); - const int modem_state_skip_time = mc->hp.regdma_m2a_work_time_ms + mc->hp.system_dfs_up_work_time_ms + mc->lp.min_slp_time_ms; - const int modem_wakeup_wait_time = adjustment - hw_wait_time + modem_state_skip_time + mc->hp.regdma_rf_on_work_time_ms; - param->hp_sys.modem_wakeup_wait_cycle = rtc_time_us_to_fastclk(modem_wakeup_wait_time, fastclk_period); + const int hw_wait_time_us = pmu_sleep_calculate_hw_wait_time(pd_flags, slowclk_period, fastclk_period); + const int modem_state_skip_time_us = mc->hp.regdma_m2a_work_time_us + mc->hp.system_dfs_up_work_time_us + mc->lp.min_slp_time_us; + const int modem_wakeup_wait_time_us = adjustment - hw_wait_time_us + modem_state_skip_time_us + mc->hp.regdma_rf_on_work_time_us; + param->hp_sys.modem_wakeup_wait_cycle = rtc_time_us_to_fastclk(modem_wakeup_wait_time_us, fastclk_period); - param->lp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.min_slp_time_ms, slowclk_period); - param->lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(mc->lp.analog_wait_time_ms, slowclk_period); - param->lp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_supply_wait_time_ms, fastclk_period); - param->lp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_up_wait_time_ms, fastclk_period); + param->lp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.min_slp_time_us, slowclk_period); + param->lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(mc->lp.analog_wait_time_us, slowclk_period); + param->lp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_supply_wait_time_us, fastclk_period); + param->lp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_up_wait_time_us, fastclk_period); if (power->hp_sys.xtal.xpd_xtal) { - param->hp_lp.xtal_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_ms, fastclk_period); + param->hp_lp.xtal_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_us, fastclk_period); } else { - param->hp_lp.xtal_stable_wait_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.xtal_wait_stable_time_ms, slowclk_period); + param->hp_lp.xtal_stable_wait_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.xtal_wait_stable_time_us, slowclk_period); } return param; } @@ -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 dd3fbd7da9..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 @@ -284,61 +284,61 @@ typedef struct { typedef struct pmu_sleep_machine_constant { struct { - uint16_t min_slp_time_ms; /* Mininum sleep protection time (unit: microsecond) */ + uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */ uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */ uint8_t reserved0; uint16_t reserved1; - uint16_t analog_wait_time_ms; /* LP LDO power up wait time (unit: microsecond) */ - uint16_t xtal_wait_stable_time_ms; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint16_t analog_wait_time_us; /* LP LDO power up wait time (unit: microsecond) */ + uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */ uint8_t clk_switch_cycle; /* Clock switch to FOSC (unit: slow clock cycle) */ uint8_t clk_power_on_wait_cycle; /* Clock power on wait cycle (unit: slow clock cycle) */ - uint16_t power_supply_wait_time_ms; /* (unit: microsecond) */ - uint16_t power_up_wait_time_ms; /* (unit: microsecond) */ + uint16_t power_supply_wait_time_us; /* (unit: microsecond) */ + uint16_t power_up_wait_time_us; /* (unit: microsecond) */ } lp; struct { - uint16_t min_slp_time_ms; /* Mininum sleep protection time (unit: microsecond) */ - uint16_t clock_domain_sync_time_ms; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */ - uint16_t system_dfs_up_work_time_ms; /* System DFS up scaling work time (unit: microsecond) */ - uint16_t analog_wait_time_ms; /* HP LDO power up wait time (unit: microsecond) */ - uint16_t power_supply_wait_time_ms; /* (unit: microsecond) */ - uint16_t power_up_wait_time_ms; /* (unit: microsecond) */ - uint16_t regdma_s2m_work_time_ms; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */ - uint16_t regdma_s2a_work_time_ms; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */ - uint16_t regdma_m2a_work_time_ms; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */ - uint16_t regdma_a2s_work_time_ms; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */ - uint16_t regdma_rf_on_work_time_ms; /* The REGDMA work time of RF enable (unit: microsecond) */ - uint16_t regdma_rf_off_work_time_ms; /* The REGDMA work time of RF disable (unit: microsecond) */ - uint16_t xtal_wait_stable_time_ms; /* Main XTAL stabilization wait time (unit: microsecond) */ - uint16_t pll_wait_stable_time_ms; /* PLL stabilization wait time (unit: microsecond) */ + uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */ + uint16_t clock_domain_sync_time_us; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */ + uint16_t system_dfs_up_work_time_us; /* System DFS up scaling work time (unit: microsecond) */ + uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */ + uint16_t power_supply_wait_time_us; /* (unit: microsecond) */ + uint16_t power_up_wait_time_us; /* (unit: microsecond) */ + uint16_t regdma_s2m_work_time_us; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_s2a_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */ + uint16_t regdma_m2a_work_time_us; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_a2s_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */ + uint16_t regdma_rf_on_work_time_us; /* The REGDMA work time of RF enable (unit: microsecond) */ + uint16_t regdma_rf_off_work_time_us; /* The REGDMA work time of RF disable (unit: microsecond) */ + uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint16_t pll_wait_stable_time_us; /* PLL stabilization wait time (unit: microsecond) */ } hp; } pmu_sleep_machine_constant_t; #define PMU_SLEEP_MC_DEFAULT() { \ .lp = { \ - .min_slp_time_ms = 450, \ + .min_slp_time_us = 450, \ .wakeup_wait_cycle = 4, \ - .analog_wait_time_ms = 154, \ - .xtal_wait_stable_time_ms = 250, \ + .analog_wait_time_us = 154, \ + .xtal_wait_stable_time_us = 250, \ .clk_switch_cycle = 1, \ .clk_power_on_wait_cycle = 1, \ - .power_supply_wait_time_ms = 2, \ - .power_up_wait_time_ms = 2 \ + .power_supply_wait_time_us = 2, \ + .power_up_wait_time_us = 2 \ }, \ .hp = { \ - .min_slp_time_ms = 450, \ - .clock_domain_sync_time_ms = 150, \ - .system_dfs_up_work_time_ms = 124, \ - .analog_wait_time_ms = 154, \ - .power_supply_wait_time_ms = 2, \ - .power_up_wait_time_ms = 2, \ - .regdma_s2m_work_time_ms = 172, \ - .regdma_s2a_work_time_ms = 430, \ - .regdma_m2a_work_time_ms = 265, \ - .regdma_a2s_work_time_ms = 338, \ - .regdma_rf_on_work_time_ms = 70, \ - .regdma_rf_off_work_time_ms = 23, \ - .xtal_wait_stable_time_ms = 250, \ - .pll_wait_stable_time_ms = 1 \ + .min_slp_time_us = 450, \ + .clock_domain_sync_time_us = 150, \ + .system_dfs_up_work_time_us = 124, \ + .analog_wait_time_us = 154, \ + .power_supply_wait_time_us = 2, \ + .power_up_wait_time_us = 2, \ + .regdma_s2m_work_time_us = 172, \ + .regdma_s2a_work_time_us = 430, \ + .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, \ + .xtal_wait_stable_time_us = 250, \ + .pll_wait_stable_time_us = 1 \ } \ } 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_cpu.c b/components/esp_hw_support/sleep_cpu.c index 28f6eeb2d3..93e750452b 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -11,6 +11,7 @@ #include #include "esp_attr.h" +#include "esp_check.h" #include "esp_sleep.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -642,4 +643,16 @@ bool cpu_domain_pd_allowed(void) #endif } +esp_err_t sleep_cpu_configure(bool light_sleep_enable) +{ +#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP + if (light_sleep_enable) { + ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep."); + } else { + ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_deinit(), TAG, "Failed to release CPU retention memory"); + } +#endif + return ESP_OK; +} + #endif diff --git a/components/esp_hw_support/sleep_mac_bb.c b/components/esp_hw_support/sleep_mac_bb.c deleted file mode 100644 index 4c53852070..0000000000 --- a/components/esp_hw_support/sleep_mac_bb.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -#include "esp_attr.h" -#include "esp_sleep.h" -#include "soc/soc_caps.h" -#include "esp_private/sleep_mac_bb.h" -#include "sdkconfig.h" - -#if CONFIG_MAC_BB_PD - -#define MAC_BB_POWER_DOWN_CB_NO (2) -#define MAC_BB_POWER_UP_CB_NO (2) - -static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO]; -static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO]; - -esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) -{ - int index = MAC_BB_POWER_DOWN_CB_NO; - for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_down_cb[i] == cb) { - return ESP_OK; - } - - if (s_mac_bb_power_down_cb[i] == NULL) { - index = i; - } - } - - if (index < MAC_BB_POWER_DOWN_CB_NO) { - s_mac_bb_power_down_cb[index] = cb; - return ESP_OK; - } - - return ESP_ERR_NO_MEM; -} - -esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) -{ - for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_down_cb[i] == cb) { - s_mac_bb_power_down_cb[i] = NULL; - return ESP_OK; - } - } - return ESP_ERR_INVALID_STATE; -} - -void IRAM_ATTR mac_bb_power_down_cb_execute(void) -{ - for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { - if (s_mac_bb_power_down_cb[i]) { - s_mac_bb_power_down_cb[i](); - } - } -} - -esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) -{ - int index = MAC_BB_POWER_UP_CB_NO; - for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_up_cb[i] == cb) { - return ESP_OK; - } - - if (s_mac_bb_power_up_cb[i] == NULL) { - index = i; - } - } - - if (index < MAC_BB_POWER_UP_CB_NO) { - s_mac_bb_power_up_cb[index] = cb; - return ESP_OK; - } - - return ESP_ERR_NO_MEM; -} - -esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) -{ - for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_up_cb[i] == cb) { - s_mac_bb_power_up_cb[i] = NULL; - return ESP_OK; - } - } - return ESP_ERR_INVALID_STATE; -} - -void IRAM_ATTR mac_bb_power_up_cb_execute(void) -{ - for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { - if (s_mac_bb_power_up_cb[i]) { - s_mac_bb_power_up_cb[i](); - } - } -} - -#endif ///CONFIG_MAC_BB_PD diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c new file mode 100644 index 0000000000..f5ebf1b854 --- /dev/null +++ b/components/esp_hw_support/sleep_modem.c @@ -0,0 +1,355 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#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 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_PM_SLP_DEFAULT_PARAMS_OPT +static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz); +#endif + +#if CONFIG_MAC_BB_PD +#define MAC_BB_POWER_DOWN_CB_NO (2) +#define MAC_BB_POWER_UP_CB_NO (2) + +static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO]; +static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO]; + +esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) +{ + int index = MAC_BB_POWER_DOWN_CB_NO; + for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_down_cb[i] == cb) { + return ESP_OK; + } + + if (s_mac_bb_power_down_cb[i] == NULL) { + index = i; + } + } + + if (index < MAC_BB_POWER_DOWN_CB_NO) { + s_mac_bb_power_down_cb[index] = cb; + return ESP_OK; + } + + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) +{ + for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_down_cb[i] == cb) { + s_mac_bb_power_down_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void IRAM_ATTR mac_bb_power_down_cb_execute(void) +{ + for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { + if (s_mac_bb_power_down_cb[i]) { + s_mac_bb_power_down_cb[i](); + } + } +} + +esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) +{ + int index = MAC_BB_POWER_UP_CB_NO; + for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_up_cb[i] == cb) { + return ESP_OK; + } + + if (s_mac_bb_power_up_cb[i] == NULL) { + index = i; + } + } + + if (index < MAC_BB_POWER_UP_CB_NO) { + s_mac_bb_power_up_cb[index] = cb; + return ESP_OK; + } + + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) +{ + for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_up_cb[i] == cb) { + s_mac_bb_power_up_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void IRAM_ATTR mac_bb_power_up_cb_execute(void) +{ + for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { + if (s_mac_bb_power_up_cb[i]) { + s_mac_bb_power_up_cb[i](); + } + } +} + +#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; +} + +esp_err_t sleep_modem_configure(int max_freq_mhz, int min_freq_mhz, bool light_sleep_enable) +{ +#if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + extern int esp_wifi_internal_mac_sleep_configure(bool, bool); + if (light_sleep_enable) { + if (sleep_modem_wifi_modem_state_init() == ESP_OK) { + esp_wifi_internal_mac_sleep_configure(light_sleep_enable, true); /* require WiFi to enable automatically receives the beacon */ + } + } else { + esp_wifi_internal_mac_sleep_configure(light_sleep_enable, false); /* require WiFi to disable automatically receives the beacon */ + sleep_modem_wifi_modem_state_deinit(); + } +#endif +#if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT + if (light_sleep_enable) { + esp_pm_light_sleep_default_params_config(min_freq_mhz, max_freq_mhz); + } +#endif + return ESP_OK; +} + +#define PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO 1 + +/* Inform peripherals of light sleep wakeup overhead time */ +static inform_out_light_sleep_overhead_cb_t s_periph_inform_out_light_sleep_overhead_cb[PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO]; + +esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { + if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { + return ESP_OK; + } else if (s_periph_inform_out_light_sleep_overhead_cb[i] == NULL) { + s_periph_inform_out_light_sleep_overhead_cb[i] = cb; + return ESP_OK; + } + } + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { + if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { + s_periph_inform_out_light_sleep_overhead_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { + if (s_periph_inform_out_light_sleep_overhead_cb[i]) { + s_periph_inform_out_light_sleep_overhead_cb[i](out_light_sleep_time); + } + } +} + +static update_light_sleep_default_params_config_cb_t s_light_sleep_default_params_config_cb = NULL; + +void esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t cb) +{ + if (s_light_sleep_default_params_config_cb == NULL) { + s_light_sleep_default_params_config_cb = cb; + } +} + +void esp_pm_unregister_light_sleep_default_params_config_callback(void) +{ + if (s_light_sleep_default_params_config_cb) { + s_light_sleep_default_params_config_cb = NULL; + } +} + +#if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT +static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz) +{ + if (s_light_sleep_default_params_config_cb) { + (*s_light_sleep_default_params_config_cb)(min_freq_mhz, max_freq_mhz); + } +} +#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index d2f36ee43a..e6b02e1d22 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_mac_bb.h" #elif CONFIG_IDF_TARGET_ESP32C3 #include "esp32c3/rom/rtc.h" -#include "esp_private/sleep_mac_bb.h" #elif CONFIG_IDF_TARGET_ESP32H4 #include "esp32h4/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C2 @@ -78,7 +81,7 @@ #include "esp32c6/rom/rtc.h" #include "hal/lp_timer_hal.h" #include "esp_private/esp_pmu.h" -#include "esp_private/sleep_peripheral.h" +#include "esp_private/sleep_sys_periph.h" #include "esp_private/sleep_clock.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" @@ -136,8 +139,6 @@ #define DEEP_SLEEP_WAKEUP_DELAY 0 #endif -extern void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time); - // Minimal amount of time we can sleep for #define LIGHT_SLEEP_MIN_TIME_US 200 @@ -523,7 +524,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 @@ -591,8 +592,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo /* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode. In order to avoid the leakage of the SPI cs pin, hold it here */ -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND - rtcio_ll_force_hold_enable(SPI_CS0_GPIO_NUM); +#if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND) + if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) { + rtcio_ll_force_hold_enable(SPI_CS0_GPIO_NUM); + } #endif #if SOC_PM_CPU_RETENTION_BY_SW @@ -606,13 +609,22 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo #endif /* Unhold the SPI CS pin */ -#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND - rtcio_ll_force_hold_disable(SPI_CS0_GPIO_NUM); +#if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND) + if(!(pd_flags & PMU_SLEEP_PD_VDDSDIO)) { + rtcio_ll_force_hold_disable(SPI_CS0_GPIO_NUM); + } #endif } // 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(); @@ -679,13 +691,17 @@ void IRAM_ATTR esp_deep_sleep_start(void) #endif + +#if SOC_PM_SUPPORT_MODEM_PD + force_pd_flags |= PMU_SLEEP_PD_MODEM; +#else // !SOC_PM_SUPPORT_MODEM_PD #if SOC_PM_SUPPORT_WIFI_PD force_pd_flags |= RTC_SLEEP_PD_WIFI; #endif - #if SOC_PM_SUPPORT_BT_PD force_pd_flags |= RTC_SLEEP_PD_BT; #endif +#endif // !SOC_PM_SUPPORT_MODEM_PD // Enter sleep esp_sleep_start(force_pd_flags | pd_flags, ESP_SLEEP_MODE_DEEP_SLEEP); @@ -837,6 +853,9 @@ esp_err_t esp_light_sleep_start(void) + rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_slp_cycles + RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES, s_config.rtc_clk_cal_period); #endif +#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-6930 + const uint32_t flash_enable_time_us = 0; +#else // Decide if VDD_SDIO needs to be powered down; // If it needs to be powered down, adjust sleep time. const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US + DEEP_SLEEP_WAKEUP_DELAY; @@ -878,6 +897,7 @@ esp_err_t esp_light_sleep_start(void) } } } +#endif periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in); @@ -1326,6 +1346,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 @@ -1496,9 +1536,20 @@ static uint32_t get_power_down_flags(void) #endif } #endif +#if SOC_PM_SUPPORT_MODEM_PD + if (!modem_domain_pd_allowed()) { + s_config.domain[ESP_PD_DOMAIN_MODEM].pd_option = ESP_PD_OPTION_ON; + } +#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()) { + if (!cpu_domain_pd_allowed() || !clock_domain_pd_allowed() || + !peripheral_domain_pd_allowed() || !modem_domain_pd_allowed()) { s_config.domain[ESP_PD_DOMAIN_TOP].pd_option = ESP_PD_OPTION_ON; } #endif @@ -1565,6 +1616,13 @@ static uint32_t get_power_down_flags(void) pd_flags |= PMU_SLEEP_PD_TOP; } #endif + +#if SOC_PM_SUPPORT_MODEM_PD + if (s_config.domain[ESP_PD_DOMAIN_MODEM].pd_option != ESP_PD_OPTION_ON) { + pd_flags |= PMU_SLEEP_PD_MODEM; + } +#endif + #if SOC_PM_SUPPORT_VDDSDIO_PD if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_VDDSDIO; diff --git a/components/esp_hw_support/sleep_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c similarity index 93% rename from components/esp_hw_support/sleep_peripheral.c rename to components/esp_hw_support/sleep_system_peripheral.c index 6448f2dae7..f98d0719ba 100644 --- a/components/esp_hw_support/sleep_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -29,11 +29,11 @@ #include "soc/io_mux_reg.h" #include "soc/interrupt_matrix_reg.h" -static __attribute__((unused)) const char *TAG = "sleep_peripheral"; +static __attribute__((unused)) const char *TAG = "sleep_sys_periph"; #define SLEEP_RETENTION_PERIPHERALS_PRIORITY_DEFAULT (REGDMA_LINK_PRI_6) -esp_err_t sleep_peripheral_intr_matrix_retention_init(void) +esp_err_t sleep_sys_periph_intr_matrix_retention_init(void) { #define N_REGS_INTR_MATRIX() (((INTMTX_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_MATRIX_BASE) / 4) + 1) @@ -47,7 +47,7 @@ esp_err_t sleep_peripheral_intr_matrix_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_hp_system_retention_init(void) +esp_err_t sleep_sys_periph_hp_system_retention_init(void) { #define N_REGS_HP_SYSTEM() (((HP_SYSTEM_MEM_TEST_CONF_REG - DR_REG_HP_SYSTEM_BASE) / 4) + 1) @@ -61,14 +61,14 @@ esp_err_t sleep_peripheral_hp_system_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_tee_apm_retention_init(void) +esp_err_t sleep_sys_periph_tee_apm_retention_init(void) { #define N_REGS_TEE() (((TEE_CLOCK_GATE_REG - DR_REG_TEE_BASE) / 4) + 1) #define N_REGS_APM() (((HP_APM_CLOCK_GATE_REG - DR_REG_HP_APM_BASE) / 4) + 1) const static sleep_retention_entries_config_t tee_apm_regs_retention[] = { [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(0), DR_REG_TEE_BASE, DR_REG_TEE_BASE, N_REGS_TEE(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* tee */ - [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(0), DR_REG_HP_APM_BASE, DR_REG_HP_APM_BASE, N_REGS_APM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* apm */ + [1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(1), DR_REG_HP_APM_BASE, DR_REG_HP_APM_BASE, N_REGS_APM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* apm */ }; esp_err_t err = sleep_retention_entries_create(tee_apm_regs_retention, ARRAY_SIZE(tee_apm_regs_retention), REGDMA_LINK_PRI_4, SLEEP_RETENTION_MODULE_TEE_APM); @@ -77,7 +77,7 @@ esp_err_t sleep_peripheral_tee_apm_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_uart0_retention_init(void) +esp_err_t sleep_sys_periph_uart0_retention_init(void) { #define N_REGS_UART() (((UART_ID_REG(0) - REG_UART_BASE(0)) / 4) + 1) @@ -94,7 +94,7 @@ esp_err_t sleep_peripheral_uart0_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_tg0_retention_init(void) +esp_err_t sleep_sys_periph_tg0_retention_init(void) { #define N_REGS_TG() (((TIMG_REGCLK_REG(0) - REG_TIMG_BASE(0)) / 4) + 1) @@ -116,7 +116,7 @@ esp_err_t sleep_peripheral_tg0_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_iomux_retention_init(void) +esp_err_t sleep_sys_periph_iomux_retention_init(void) { #define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_SPID_U - REG_IO_MUX_BASE) / 4) + 1) #define N_REGS_IOMUX_1() (((GPIO_FUNC34_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1) @@ -136,7 +136,7 @@ esp_err_t sleep_peripheral_iomux_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_spimem_retention_init(void) +esp_err_t sleep_sys_periph_spimem_retention_init(void) { #define N_REGS_SPI1_MEM_0() (((SPI_MEM_SPI_SMEM_DDR_REG(1) - REG_SPI_MEM_BASE(1)) / 4) + 1) #define N_REGS_SPI1_MEM_1() (((SPI_MEM_SPI_SMEM_AC_REG(1) - SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1)) / 4) + 1) @@ -168,7 +168,7 @@ esp_err_t sleep_peripheral_spimem_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_systimer_retention_init(void) +esp_err_t sleep_sys_periph_systimer_retention_init(void) { #define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1) @@ -207,24 +207,24 @@ esp_err_t sleep_peripheral_systimer_retention_init(void) return ESP_OK; } -esp_err_t sleep_peripheral_retention_init(void) +esp_err_t sleep_sys_periph_retention_init(void) { esp_err_t err; - err = sleep_peripheral_intr_matrix_retention_init(); + err = sleep_sys_periph_intr_matrix_retention_init(); if(err) goto error; - err = sleep_peripheral_hp_system_retention_init(); + err = sleep_sys_periph_hp_system_retention_init(); if(err) goto error; - err = sleep_peripheral_tee_apm_retention_init(); + err = sleep_sys_periph_tee_apm_retention_init(); if(err) goto error; - err = sleep_peripheral_uart0_retention_init(); + err = sleep_sys_periph_uart0_retention_init(); if(err) goto error; - err = sleep_peripheral_tg0_retention_init(); + err = sleep_sys_periph_tg0_retention_init(); if(err) goto error; - err = sleep_peripheral_iomux_retention_init(); + err = sleep_sys_periph_iomux_retention_init(); if(err) goto error; - err = sleep_peripheral_spimem_retention_init(); + err = sleep_sys_periph_spimem_retention_init(); if(err) goto error; - err = sleep_peripheral_systimer_retention_init(); + err = sleep_sys_periph_systimer_retention_init(); error: return err; @@ -246,9 +246,9 @@ bool IRAM_ATTR peripheral_domain_pd_allowed(void) } #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP -ESP_SYSTEM_INIT_FN(sleep_peripheral_startup_init, BIT(0), 107) +ESP_SYSTEM_INIT_FN(sleep_sys_periph_startup_init, BIT(0), 107) { - sleep_peripheral_retention_init(); + sleep_sys_periph_retention_init(); return ESP_OK; } #endif 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/include/esp_private/pm_impl.h b/components/esp_pm/include/esp_private/pm_impl.h index e208d2bcf5..02364050c7 100644 --- a/components/esp_pm/include/esp_private/pm_impl.h +++ b/components/esp_pm/include/esp_private/pm_impl.h @@ -1,16 +1,8 @@ -// Copyright 2016-2017 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: 2016-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -149,58 +141,6 @@ esp_err_t esp_pm_register_skip_light_sleep_callback(skip_light_sleep_cb_t cb); */ esp_err_t esp_pm_unregister_skip_light_sleep_callback(skip_light_sleep_cb_t cb); -/** - * @brief Callback function type for peripherals to know light sleep wakeup overhead. - * - */ -typedef void (* inform_out_light_sleep_overhead_cb_t)(uint32_t); - -/** - * @brief Register informing peripherals light sleep wakeup overhead time callback - * - * This function allows you to register a callback that informs the peripherals of - * the wakeup overhead time of light sleep. - * @param cb function to inform time - * @return - * - ESP_OK on success - * - ESP_ERR_NO_MEM if no more callback slots are available - */ -esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb); - -/** - * @brief Unregister informing peripherals light sleep wakeup overhead time callback - * - * This function allows you to unregister a callback that informs the peripherals of - * the wakeup overhead time of light sleep. - * @param cb function to inform time - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_STATE if the given callback hasn't been registered before - */ -esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb); - -/** - * @brief Callback function type for peripherals to know light sleep default parameters - */ -typedef void (* update_light_sleep_default_params_config_cb_t)(int, int); - -/** - * @brief Register peripherals light sleep default parameters configure callback - * - * This function allows you to register a callback that configure the peripherals - * of default parameters of light sleep - * @param cb function to update default parameters - */ -void esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t cb); - -/** - * @brief Unregister peripherals light sleep default parameters configure Callback - * - * This function allows you to unregister a callback that configure the peripherals - * of default parameters of light sleep - */ -void esp_pm_unregister_light_sleep_default_params_config_callback(void); - #ifdef CONFIG_PM_PROFILING #define WITH_PROFILING #endif diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index cad3fb2397..be988f0a0e 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -4,8 +4,6 @@ entries: if PM_RTOS_IDLE_OPT = y: pm_impl:esp_pm_impl_idle_hook (noflash) pm_impl:esp_pm_impl_waiti (noflash) - if PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32 = n: - pm_impl:periph_inform_out_light_sleep_overhead (noflash) [mapping:esp_hw_support_pm] archive: libesp_hw_support.a diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index b56346ba81..c020dd1004 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -35,7 +35,9 @@ #include "esp_private/pm_trace.h" #include "esp_private/esp_timer_private.h" #include "esp_private/esp_clk.h" - +#include "esp_private/sleep_cpu.h" +#include "esp_private/sleep_gpio.h" +#include "esp_private/sleep_modem.h" #include "esp_sleep.h" #include "sdkconfig.h" @@ -178,9 +180,6 @@ static const char* TAG = "pm"; static void do_switch(pm_mode_t new_mode); static void leave_idle(void); static void on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_per_us); -#if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT -static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz); -#endif pm_mode_t esp_pm_impl_get_mode(esp_pm_lock_type_t type, int arg) { @@ -197,6 +196,22 @@ pm_mode_t esp_pm_impl_get_mode(esp_pm_lock_type_t type, int arg) } } +static esp_err_t esp_pm_sleep_configure(const void *vconfig) +{ + esp_err_t err = ESP_OK; + const esp_pm_config_t* config = (const esp_pm_config_t*) vconfig; + +#if SOC_PM_SUPPORT_CPU_PD + err = sleep_cpu_configure(config->light_sleep_enable); + if (err != ESP_OK) { + return err; + } +#endif + + err = sleep_modem_configure(config->max_freq_mhz, config->min_freq_mhz, config->light_sleep_enable); + return err; +} + esp_err_t esp_pm_configure(const void* vconfig) { #ifndef CONFIG_PM_ENABLE @@ -282,21 +297,7 @@ esp_err_t esp_pm_configure(const void* vconfig) s_config_changed = true; portEXIT_CRITICAL(&s_switch_lock); -#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_SUPPORT_CPU_PD - if (config->light_sleep_enable) { - if (esp_sleep_cpu_retention_init() != ESP_OK) { - ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep."); - } - } else { - esp_sleep_cpu_retention_deinit(); - } -#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); - } -#endif + esp_pm_sleep_configure(config); return ESP_OK; } @@ -816,66 +817,3 @@ void esp_pm_impl_waiti(void) esp_cpu_wait_for_intr(); #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE } - -#define PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO 1 - -/* Inform peripherals of light sleep wakeup overhead time */ -static inform_out_light_sleep_overhead_cb_t s_periph_inform_out_light_sleep_overhead_cb[PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO]; - -esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) -{ - for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { - if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { - return ESP_OK; - } else if (s_periph_inform_out_light_sleep_overhead_cb[i] == NULL) { - s_periph_inform_out_light_sleep_overhead_cb[i] = cb; - return ESP_OK; - } - } - return ESP_ERR_NO_MEM; -} - -esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) -{ - for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { - if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { - s_periph_inform_out_light_sleep_overhead_cb[i] = NULL; - return ESP_OK; - } - } - return ESP_ERR_INVALID_STATE; -} - -void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time) -{ - for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { - if (s_periph_inform_out_light_sleep_overhead_cb[i]) { - s_periph_inform_out_light_sleep_overhead_cb[i](out_light_sleep_time); - } - } -} - -static update_light_sleep_default_params_config_cb_t s_light_sleep_default_params_config_cb = NULL; - -void esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t cb) -{ - if (s_light_sleep_default_params_config_cb == NULL) { - s_light_sleep_default_params_config_cb = cb; - } -} - -void esp_pm_unregister_light_sleep_default_params_config_callback(void) -{ - if (s_light_sleep_default_params_config_cb) { - s_light_sleep_default_params_config_cb = NULL; - } -} - -#if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT -static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz) -{ - if (s_light_sleep_default_params_config_cb) { - (*s_light_sleep_default_params_config_cb)(min_freq_mhz, max_freq_mhz); - } -} -#endif diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld index 91eda2dc40..4ff90dace2 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld @@ -1569,16 +1569,16 @@ pm_set_beacon_filter = 0x40001b90; pm_is_in_wifi_slice_threshold = 0x40001b94; pm_is_waked = 0x40001b98; pm_keep_alive = 0x40001b9c; -pm_on_beacon_rx = 0x40001ba0; +/* pm_on_beacon_rx = 0x40001ba0; */ pm_on_data_rx = 0x40001ba4; pm_on_tbtt = 0x40001ba8; /* pm_parse_beacon = 0x40001bac;*/ -pm_process_tim = 0x40001bb0; +/* pm_process_tim = 0x40001bb0; */ /*pm_rx_beacon_process = 0x40001bb4;*/ -pm_rx_data_process = 0x40001bb8; +/* pm_rx_data_process = 0x40001bb8; */ pm_sleep = 0x40001bbc; pm_sleep_for = 0x40001bc0; -pm_tbtt_process = 0x40001bc4; +/* pm_tbtt_process = 0x40001bc4; */ ppAMPDU2Normal = 0x40001bc8; ppAssembleAMPDU = 0x40001bcc; ppCalFrameTimes = 0x40001bd0; @@ -1734,7 +1734,7 @@ config_get_wifi_task_stack_size = 0x40001e24; pp_create_task = 0x40001e28; hal_set_sta_tsf_wakeup = 0x40001e2c; hal_set_rx_beacon_pti = 0x40001e30; -pm_start = 0x40001e34; +/* pm_start = 0x40001e34; */ pm_stop = 0x40001e38; hal_disable_sta_tbtt = 0x40001e3c; ppCalTxopDur = 0x40001e40; @@ -1742,7 +1742,7 @@ wDev_IndicateCtrlFrame = 0x40001e44; hal_enable_sta_tbtt = 0x40001e48; hal_set_sta_tbtt = 0x40001e4c; /* pm_update_next_tbtt = 0x40001e50;*/ -pm_set_sleep_type = 0x40001e54; +/* pm_set_sleep_type = 0x40001e54; */ wDev_Rxbuf_Init = 0x40001e58; wDev_Rxbuf_Deinit = 0x40001e5c; ppCalTkipMic = 0x40001e60; @@ -1767,7 +1767,7 @@ rcUpdatePhyMode = 0x40001ea8; rcGetHighestRateIdx = 0x40001eac; pm_tx_null_data_done_process = 0x40001eb0; pm_tx_data_process = 0x40001eb4; -pm_attach = 0x40001eb8; +/* pm_attach = 0x40001eb8; */ /* pm_coex_schm_process = 0x40001ebc; */ ppInitTxq = 0x40001ec0; pp_attach = 0x40001ec4; diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index 5203dfd4c3..157578efa9 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld @@ -1549,9 +1549,9 @@ pm_keep_alive = 0x40001678; pm_on_data_rx = 0x40001680; pm_on_tbtt = 0x40001684; /* pm_parse_beacon = 0x40001688;*/ -pm_process_tim = 0x4000168c; +/* pm_process_tim = 0x4000168c; */ /*pm_rx_beacon_process = 0x40001690;*/ -pm_rx_data_process = 0x40001694; +/* pm_rx_data_process = 0x40001694; */ /*pm_sleep = 0x40001698;*/ pm_sleep_for = 0x4000169c; /* pm_tbtt_process = 0x400016a0; */ diff --git a/components/esp_rom/esp32c6/ld/esp32c6.rom.pp.ld b/components/esp_rom/esp32c6/ld/esp32c6.rom.pp.ld index 00ea485ddf..f54e63e007 100644 --- a/components/esp_rom/esp32c6/ld/esp32c6.rom.pp.ld +++ b/components/esp_rom/esp32c6/ld/esp32c6.rom.pp.ld @@ -31,7 +31,7 @@ hal_mac_tx_get_blockack = 0x40000bfc; //hal_mac_tx_set_ppdu = 0x40000c00; ic_get_trc = 0x40000c04; //ic_mac_deinit = 0x40000c08; -ic_mac_init = 0x40000c0c; +/* ic_mac_init = 0x40000c0c; */ ic_interface_enabled = 0x40000c10; is_lmac_idle = 0x40000c14; lmacAdjustTimestamp = 0x40000c18; @@ -57,7 +57,7 @@ mac_tx_set_duration = 0x40000c60; mac_tx_set_plcp1 = 0x40000c68; mac_tx_set_plcp2 = 0x40000c6c; pm_check_state = 0x40000c70; -pm_disable_dream_timer = 0x40000c74; +/* pm_disable_dream_timer = 0x40000c74; */ pm_disable_sleep_delay_timer = 0x40000c78; pm_dream = 0x40000c7c; pm_mac_wakeup = 0x40000c80; @@ -69,13 +69,13 @@ pm_local_tsf_process = 0x40000c90; pm_is_in_wifi_slice_threshold = 0x40000c98; pm_is_waked = 0x40000c9c; //pm_keep_alive = 0x40000ca0; -pm_on_beacon_rx = 0x40000ca4; +/* pm_on_beacon_rx = 0x40000ca4; */ pm_on_data_rx = 0x40000ca8; pm_on_tbtt = 0x40000cac; pm_parse_beacon = 0x40000cb0; //pm_process_tim = 0x40000cb4; //pm_rx_beacon_process = 0x40000cb8; -pm_rx_data_process = 0x40000cbc; +/* pm_rx_data_process = 0x40000cbc; */ //pm_sleep = 0x40000cc0; pm_sleep_for = 0x40000cc4; //pm_tbtt_process = 0x40000cc8; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld index e58b1e13c5..d7fb7e7d79 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld @@ -1854,9 +1854,9 @@ pm_keep_alive = 0x400054a8; pm_on_data_rx = 0x400054c0; pm_on_tbtt = 0x400054cc; /* pm_parse_beacon = 0x400054d8;*/ -pm_process_tim = 0x400054e4; +/* pm_process_tim = 0x400054e4; */ /*pm_rx_beacon_process = 0x400054f0;*/ -pm_rx_data_process = 0x400054fc; +/* pm_rx_data_process = 0x400054fc; */ /*pm_sleep = 0x40005508;*/ pm_sleep_for = 0x40005514; /* pm_tbtt_process = 0x40005520; */ diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 1b699c3fa8..2f8557962a 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -19,7 +19,7 @@ # esp_sleep doesn't have init dependencies 105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0) 106: sleep_clock_startup_init in components/esp_hw_support/sleep_clock.c on BIT(0) -107: sleep_peripheral_startup_init in components/esp_hw_support/sleep_peripheral.c on BIT(0) +107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) # app_trace has to be initialized before systemview 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 12e627e2e8..61988a83c3 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_ENHANCED_LIGHT_SLEEP + bool "WiFi modem automatically receives the beacon" + default n + depends on ESP_PHY_MAC_BB_PD && SOC_PM_SUPPORT_BEACON_WAKEUP + 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 @@ -365,7 +372,7 @@ menu "Wi-Fi" int "Delta early time for RF PHY on" range 0 100 default 2 - depends on ESP_WIFI_SLP_BEACON_LOST_OPT + depends on ESP_WIFI_SLP_BEACON_LOST_OPT && SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW help Delta early time for rf phy on, When the beacon is lost, the next rf phy on will be earlier the time specified by the configuration item, Unit: 32 microsecond. @@ -374,7 +381,7 @@ menu "Wi-Fi" int "Delta timeout time for RF PHY off" range 0 8 default 2 - depends on ESP_WIFI_SLP_BEACON_LOST_OPT + depends on ESP_WIFI_SLP_BEACON_LOST_OPT && SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW help Delta timeout time for rf phy off, When the beacon is lost, the next rf phy off will be delayed for the time specified by the configuration item. Unit: 1024 microsecond. 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.h b/components/esp_wifi/include/esp_private/wifi.h index 01b11f4709..90edc7e3b3 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -624,11 +624,20 @@ void esp_wifi_set_keep_alive_time(uint32_t keep_alive_time); /** * @brief Configure wifi beacon montior default parameters * - * @param enable: enable or disable beacon monitor - * @param timeout: timeout time for close rf phy when beacon loss occurs, Unit: 1024 microsecond - * @param threshold: maximum number of consecutive lost beacons allowed + * @param config: the configuration parameters for wifi beacon monitor */ -void esp_wifi_beacon_monitor_configure(bool enable, int timeout, int threshold, int delta_intr_early, int delta_timeout); +void esp_wifi_beacon_monitor_configure(wifi_beacon_monitor_config_t *config); + +/** + * @brief Require WiFi to enable or disable Advanced DTIM sleep function + * + * @param light_sleep_enable: true for light sleep mode is enabled, false for light sleep mode is disabled. + * @param modem_state_enable: true for require WiFi to enable Advanced DTIM sleep function, + * false for require WiFi to disable Advanced DTIM sleep function. + * @return + * - ESP_OK: succeed + */ +void esp_wifi_internal_mac_sleep_configure(bool light_sleep_enable, bool modem_state_enable); #ifdef __cplusplus } 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..4b55b9c6b4 100644 --- a/components/esp_wifi/include/esp_private/wifi_os_adapter.h +++ b/components/esp_wifi/include/esp_private/wifi_os_adapter.h @@ -142,6 +142,8 @@ typedef struct { uint32_t (* _coex_schm_interval_get)(void); uint8_t (* _coex_schm_curr_period_get)(void); void * (* _coex_schm_curr_phase_get)(void); + int (* _coex_schm_process_restart)(void); + int (* _coex_schm_register_cb)(int, int (* cb)(int)); int (* _coex_register_start_cb)(int (* cb)(void)); #if CONFIG_IDF_TARGET_ESP32C6 void (* _regdma_link_set_write_wait_content)(void *, uint32_t, uint32_t); @@ -149,8 +151,6 @@ typedef struct { int (* _sleep_retention_entries_create)(const void *, int, int, int); void (* _sleep_retention_entries_destroy)(int); #endif - int (* _coex_schm_process_restart)(void); - int (* _coex_schm_register_cb)(int, int (* cb)(int)); int32_t _magic; } wifi_osi_funcs_t; diff --git a/components/esp_wifi/include/esp_wifi_types.h b/components/esp_wifi/include/esp_wifi_types.h index d2732c9a73..8784730fe7 100644 --- a/components/esp_wifi/include/esp_wifi_types.h +++ b/components/esp_wifi/include/esp_wifi_types.h @@ -891,6 +891,23 @@ typedef struct { uint8_t peer_macaddr[6]; /**< Enrollee mac address */ } wifi_event_ap_wps_rg_success_t; +/** WiFi beacon monitor parameter configuration */ +typedef struct { + bool enable; /**< Enable or disable beacon monitor */ + uint8_t loss_timeout; /**< Beacon lost timeout */ + uint8_t loss_threshold; /**< Maximum number of consecutive lost beacons allowed */ + uint8_t delta_intr_early; /**< Delta early time for RF PHY on */ + uint8_t delta_loss_timeout; /**< Delta timeout time for RF PHY off */ +#if MAC_SUPPORT_PMU_MODEM_STATE + uint8_t beacon_abort: 1, /**< Enable or disable beacon abort */ + broadcast_wakeup: 1, /**< Enable or disable TIM element multicast wakeup */ + reserved: 6; /**< Reserved */ + uint8_t tsf_time_sync_deviation; /**< Deviation range to sync with AP TSF timestamp */ + uint16_t modem_state_consecutive; /**< PMU MODEM state consecutive count limit */ + uint16_t rf_ctrl_wait_cycle; /**< RF on wait time (unit: Modem APB clock cycle) */ +#endif +} wifi_beacon_monitor_config_t; + #ifdef __cplusplus } #endif diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 194ce92651..302a414d89 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 194ce926518a254714850e9bd4f12469d89867c2 +Subproject commit 302a414d8912740b24708974a04f9075400e7c91 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 2e1d0db691..3118f7384c 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -9,6 +9,7 @@ #include "esp_log.h" #include "esp_private/wifi.h" #include "esp_private/adc_share_hw_ctrl.h" +#include "esp_private/sleep_modem.h" #include "esp_pm.h" #include "esp_sleep.h" #include "esp_private/pm_impl.h" @@ -55,6 +56,28 @@ uint64_t g_wifi_feature_caps = #endif 0; +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +# define WIFI_BEACON_MONITOR_CONFIG_DEFAULT(ena) { \ + .enable = (ena), \ + .loss_timeout = CONFIG_ESP_WIFI_SLP_BEACON_LOST_TIMEOUT, \ + .loss_threshold = CONFIG_ESP_WIFI_SLP_BEACON_LOST_THRESHOLD, \ + .delta_intr_early = 0, \ + .delta_loss_timeout = 0, \ + .beacon_abort = 1, \ + .broadcast_wakeup = 1, \ + .tsf_time_sync_deviation = 5, \ + .modem_state_consecutive = 10, \ + .rf_ctrl_wait_cycle = 20 \ +} +#else +# define WIFI_BEACON_MONITOR_CONFIG_DEFAULT(ena) { \ + .enable = (ena), \ + .loss_timeout = CONFIG_ESP_WIFI_SLP_BEACON_LOST_TIMEOUT, \ + .loss_threshold = CONFIG_ESP_WIFI_SLP_BEACON_LOST_THRESHOLD, \ + .delta_intr_early = CONFIG_ESP_WIFI_SLP_PHY_ON_DELTA_EARLY_TIME, \ + .delta_loss_timeout = CONFIG_ESP_WIFI_SLP_PHY_OFF_DELTA_TIMEOUT_TIME \ +} +#endif static const char* TAG = "wifi_init"; @@ -112,7 +135,8 @@ esp_err_t esp_wifi_deinit(void) } #if CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT - esp_wifi_beacon_monitor_configure(false, 0, 0, 0, 0); + wifi_beacon_monitor_config_t monitor_config = WIFI_BEACON_MONITOR_CONFIG_DEFAULT(false); + esp_wifi_beacon_monitor_configure(&monitor_config); #endif #if CONFIG_ESP_WIFI_SLP_IRAM_OPT @@ -123,8 +147,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_ENHANCED_LIGHT_SLEEP + 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 +263,14 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) return ret; } esp_sleep_enable_wifi_wakeup(); +# if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + 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(); @@ -269,9 +299,8 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) } } #if CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT - esp_wifi_beacon_monitor_configure(true, CONFIG_ESP_WIFI_SLP_BEACON_LOST_TIMEOUT, - CONFIG_ESP_WIFI_SLP_BEACON_LOST_THRESHOLD, CONFIG_ESP_WIFI_SLP_PHY_ON_DELTA_EARLY_TIME, - CONFIG_ESP_WIFI_SLP_PHY_OFF_DELTA_TIMEOUT_TIME); + wifi_beacon_monitor_config_t monitor_config = WIFI_BEACON_MONITOR_CONFIG_DEFAULT(true); + esp_wifi_beacon_monitor_configure(&monitor_config); #endif adc2_cal_include(); //This enables the ADC2 calibration constructor at start up. 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/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index ea0f1cf35a..4903749cec 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -803,14 +803,6 @@ config SOC_SDMMC_NUM_SLOTS int default 2 -config SOC_WIFI_FTM_SUPPORT - bool - default n - -config SOC_WIFI_GCMP_SUPPORT - bool - default n - config SOC_WIFI_WAPI_SUPPORT bool default y @@ -823,6 +815,10 @@ config SOC_WIFI_MESH_SUPPORT bool default y +config SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW + bool + default y + config SOC_BLE_SUPPORTED bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 353d3b8509..c8e68480e2 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -401,11 +401,10 @@ #define SOC_SDMMC_NUM_SLOTS 2 /*-------------------------- WI-FI HARDWARE CAPS -------------------------------*/ -#define SOC_WIFI_FTM_SUPPORT (0) /*!< FTM is not supported */ -#define SOC_WIFI_GCMP_SUPPORT (0) /*!< GCMP is not supported(GCMP128 and GCMP256) */ -#define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ -#define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ -#define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ +#define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ +#define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ +#define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ +#define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */ /*---------------------------------- Bluetooth CAPS ----------------------------------*/ #define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */ diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 73ed37fbcd..bd64d98a2c 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -647,25 +647,9 @@ config SOC_WIFI_HW_TSF bool default y -config SOC_WIFI_FTM_SUPPORT +config SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW bool - default n - -config SOC_WIFI_GCMP_SUPPORT - bool - default n - -config SOC_WIFI_WAPI_SUPPORT - bool - default n - -config SOC_WIFI_CSI_SUPPORT - bool - default n - -config SOC_WIFI_MESH_SUPPORT - bool - default n + default y config SOC_BLE_SUPPORTED bool diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index b29367d2f7..d9bb3e70f1 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -301,12 +301,8 @@ #define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< ESP32C2 only supports to connect an external oscillator, not a crystal */ /*------------------------------------ WI-FI CAPS ------------------------------------*/ -#define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ -#define SOC_WIFI_FTM_SUPPORT (0) /*!< FTM is not supported */ -#define SOC_WIFI_GCMP_SUPPORT (0) /*!< GCMP is not supported(GCMP128 and GCMP256) */ -#define SOC_WIFI_WAPI_SUPPORT (0) /*!< WAPI is not supported */ -#define SOC_WIFI_CSI_SUPPORT (0) /*!< CSI is not supported */ -#define SOC_WIFI_MESH_SUPPORT (0) /*!< WIFI MESH is not supported */ +#define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ +#define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */ /*---------------------------------- Bluetooth CAPS ----------------------------------*/ #define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */ diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 405056d2f8..a7665e4edd 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -887,10 +887,18 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_PM_SUPPORT_MAC_BB_PD + bool + default y + config SOC_PM_CPU_RETENTION_BY_RTCCNTL bool default y +config SOC_PM_MODEM_RETENTION_BY_BACKUPDMA + bool + default y + config SOC_CLK_RC_FAST_D256_SUPPORTED bool default y @@ -939,6 +947,10 @@ config SOC_WIFI_MESH_SUPPORT bool default y +config SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW + bool + default y + config SOC_BLE_SUPPORTED bool default y diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 20783cf3f3..fef9c410ca 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -389,8 +389,10 @@ #define SOC_PM_SUPPORT_BT_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) +#define SOC_PM_SUPPORT_MAC_BB_PD (1) -#define SOC_PM_CPU_RETENTION_BY_RTCCNTL (1) +#define SOC_PM_CPU_RETENTION_BY_RTCCNTL (1) +#define SOC_PM_MODEM_RETENTION_BY_BACKUPDMA (1) /*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */ #define SOC_CLK_RC_FAST_D256_SUPPORTED (1) @@ -404,12 +406,13 @@ #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) /*------------------------------------ WI-FI CAPS ------------------------------------*/ -#define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ -#define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ -#define SOC_WIFI_GCMP_SUPPORT (1) /*!< Support GCMP(GCMP128 and GCMP256) */ -#define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ -#define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ -#define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ +#define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ +#define SOC_WIFI_FTM_SUPPORT (1) /*!< Support FTM */ +#define SOC_WIFI_GCMP_SUPPORT (1) /*!< Support GCMP(GCMP128 and GCMP256) */ +#define SOC_WIFI_WAPI_SUPPORT (1) /*!< Support WAPI */ +#define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */ +#define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ +#define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */ /*---------------------------------- Bluetooth CAPS ----------------------------------*/ #define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 8ac11d0497..96615ff958 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1047,6 +1047,10 @@ config SOC_PM_SUPPORT_WIFI_WAKEUP bool default y +config SOC_PM_SUPPORT_BEACON_WAKEUP + bool + default y + config SOC_PM_SUPPORT_BT_WAKEUP bool default y @@ -1083,6 +1087,14 @@ config SOC_PM_SUPPORT_TOP_PD bool default y +config SOC_PM_SUPPORT_MAC_BB_PD + bool + default y + +config SOC_PM_SUPPORT_PMU_MODEM_STATE + bool + default y + config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y @@ -1091,6 +1103,10 @@ config SOC_PM_CPU_RETENTION_BY_SW bool default y +config SOC_PM_MODEM_RETENTION_BY_REGDMA + bool + default y + config SOC_PM_PAU_LINK_NUM int default 4 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/lp_timer_struct.h b/components/soc/esp32c6/include/soc/lp_timer_struct.h index 98961dc895..9efef9b169 100644 --- a/components/soc/esp32c6/include/soc/lp_timer_struct.h +++ b/components/soc/esp32c6/include/soc/lp_timer_struct.h @@ -80,29 +80,29 @@ typedef union { uint32_t val; } lp_timer_lp_intr_reg_t; -typedef volatile struct lp_timer_dev_t{ - lp_timer_target_reg_t target[2]; - lp_timer_update_reg_t update; - lp_timer_counter_reg_t counter[2]; - lp_timer_overflow_reg_t overflow; - lp_timer_intr_reg_t int_raw; - lp_timer_intr_reg_t int_st; - lp_timer_intr_reg_t int_en; - lp_timer_intr_reg_t int_clr; - lp_timer_lp_intr_reg_t lp_int_raw; - lp_timer_lp_intr_reg_t lp_int_st; - lp_timer_lp_intr_reg_t lp_int_en; - lp_timer_lp_intr_reg_t lp_int_clr; +typedef union { + struct { + uint32_t date : 31; + uint32_t clk_en: 1; + }; + uint32_t val; +} lp_timer_date_clken_reg_t; +typedef struct lp_timer_dev_t{ + volatile lp_timer_target_reg_t target[2]; + volatile lp_timer_update_reg_t update; + volatile lp_timer_counter_reg_t counter[2]; + volatile lp_timer_overflow_reg_t overflow; + volatile lp_timer_intr_reg_t int_raw; + volatile lp_timer_intr_reg_t int_st; + volatile lp_timer_intr_reg_t int_en; + volatile lp_timer_intr_reg_t int_clr; + volatile lp_timer_lp_intr_reg_t lp_int_raw; + volatile lp_timer_lp_intr_reg_t lp_int_st; + volatile lp_timer_lp_intr_reg_t lp_int_en; + volatile lp_timer_lp_intr_reg_t lp_int_clr; uint32_t reserved[237]; - - union { - struct { - uint32_t date : 31; - uint32_t clk_en: 1; - }; - uint32_t val; - } date; + volatile lp_timer_date_clken_reg_t date_clken; } lp_timer_dev_t; extern lp_timer_dev_t LP_TIMER; diff --git a/components/soc/esp32c6/include/soc/pmu_struct.h b/components/soc/esp32c6/include/soc/pmu_struct.h index db1c3869e0..4576758c22 100644 --- a/components/soc/esp32c6/include/soc/pmu_struct.h +++ b/components/soc/esp32c6/include/soc/pmu_struct.h @@ -175,7 +175,7 @@ typedef union { uint32_t val; } pmu_hp_xtal_reg_t; -typedef volatile struct pmu_hp_hw_regmap_t{ +typedef struct pmu_hp_hw_regmap_t{ pmu_hp_dig_power_reg_t dig_power; uint32_t icg_func; uint32_t icg_apb; @@ -250,7 +250,7 @@ typedef union { uint32_t val; } pmu_lp_bias_reg_t; -typedef volatile struct pmu_lp_hw_regmap_t{ +typedef struct pmu_lp_hw_regmap_t{ pmu_lp_regulator0_reg_t regulator0; pmu_lp_regulator1_reg_t regulator1; pmu_lp_xtal_reg_t xtal; /* Only LP_SLEEP mode under lp system is valid */ @@ -345,7 +345,7 @@ typedef union { uint32_t val; } pmu_imm_i2c_isolate_reg_t; -typedef volatile struct pmu_imm_hw_regmap_t{ +typedef struct pmu_imm_hw_regmap_t{ pmu_imm_hp_clk_power_reg_t clk_power; pmu_imm_sleep_sysclk_reg_t sleep_sysclk; pmu_imm_hp_func_icg_reg_t hp_func_icg; @@ -442,7 +442,7 @@ typedef union { uint32_t val; } pmu_power_clk_wait_cntl_reg_t; -typedef volatile struct pmu_power_hw_regmap_t{ +typedef struct pmu_power_hw_regmap_t{ pmu_power_wait_timer0_reg_t wait_timer0; pmu_power_wait_timer1_reg_t wait_timer1; pmu_power_domain_cntl_reg_t hp_pd[5]; @@ -514,7 +514,7 @@ typedef union { uint32_t val; } pmu_slp_wakeup_cntl7_reg_t; -typedef volatile struct pmu_wakeup_hw_regmap_t{ +typedef struct pmu_wakeup_hw_regmap_t{ pmu_slp_wakeup_cntl0_reg_t cntl0; pmu_slp_wakeup_cntl1_reg_t cntl1; uint32_t cntl2; @@ -585,7 +585,7 @@ typedef union { uint32_t val; } pmu_hp_intr_reg_t; -typedef volatile struct pmu_hp_ext_hw_regmap_t{ +typedef struct pmu_hp_ext_hw_regmap_t{ pmu_hp_clk_poweron_reg_t clk_poweron; pmu_hp_clk_cntl_reg_t clk_cntl; pmu_por_status_reg_t por_status; @@ -641,7 +641,7 @@ typedef union { uint32_t val; } pmu_lp_cpu_pwr1_reg_t; -typedef volatile struct pmu_lp_ext_hw_regmap_t{ +typedef struct pmu_lp_ext_hw_regmap_t{ pmu_lp_intr_reg_t int_raw; pmu_lp_intr_reg_t int_st; pmu_lp_intr_reg_t int_ena; @@ -650,93 +650,93 @@ typedef volatile struct pmu_lp_ext_hw_regmap_t{ pmu_lp_cpu_pwr1_reg_t pwr1; } pmu_lp_ext_hw_regmap_t; -typedef volatile struct pmu_dev_t{ - pmu_hp_hw_regmap_t hp_sys[3]; - pmu_lp_hw_regmap_t lp_sys[2]; - pmu_imm_hw_regmap_t imm; - pmu_power_hw_regmap_t power; - pmu_wakeup_hw_regmap_t wakeup; - pmu_hp_ext_hw_regmap_t hp_ext; - pmu_lp_ext_hw_regmap_t lp_ext; +typedef struct pmu_dev_t{ + volatile pmu_hp_hw_regmap_t hp_sys[3]; + volatile pmu_lp_hw_regmap_t lp_sys[2]; + volatile pmu_imm_hw_regmap_t imm; + volatile pmu_power_hw_regmap_t power; + volatile pmu_wakeup_hw_regmap_t wakeup; + volatile pmu_hp_ext_hw_regmap_t hp_ext; + volatile pmu_lp_ext_hw_regmap_t lp_ext; union { struct { uint32_t reserved0 : 30; - uint32_t lp_trigger_hp: 1; - uint32_t hp_trigger_lp: 1; + volatile uint32_t lp_trigger_hp: 1; + volatile uint32_t hp_trigger_lp: 1; }; - uint32_t val; + volatile uint32_t val; } hp_lp_cpu_comm; union { struct { uint32_t reserved0 : 31; - uint32_t dig_regulator_en_cal: 1; + volatile uint32_t dig_regulator_en_cal: 1; }; - uint32_t val; + volatile uint32_t val; } hp_regulator_cfg; union { struct { uint32_t reserved0 : 11; - uint32_t last_st : 7; - uint32_t target_st : 7; - uint32_t current_st: 7; + volatile uint32_t last_st : 7; + volatile uint32_t target_st : 7; + volatile uint32_t current_st: 7; }; - uint32_t val; + volatile uint32_t val; } main_state; union { struct { uint32_t reserved0: 13; - uint32_t backup_st: 5; - uint32_t lp_pwr_st: 5; - uint32_t hp_pwr_st: 9; + volatile uint32_t backup_st: 5; + volatile uint32_t lp_pwr_st: 5; + volatile uint32_t hp_pwr_st: 9; }; - uint32_t val; + volatile uint32_t val; } pwr_state; union { struct { - uint32_t stable_xpd_bbpll : 1; - uint32_t stable_xpd_xtal : 1; - uint32_t reserved0 : 13; - uint32_t sysclk_slp_sel : 1; - uint32_t sysclk_sel : 2; - uint32_t sysclk_nodiv : 1; - uint32_t icg_sysclk_en : 1; - uint32_t icg_modem_switch : 1; - uint32_t icg_modem_code : 2; - uint32_t icg_slp_sel : 1; - uint32_t icg_global_xtal : 1; - uint32_t icg_global_pll : 1; - uint32_t ana_i2c_iso_en : 1; - uint32_t ana_i2c_retention: 1; - uint32_t ana_xpd_bb_i2c : 1; - uint32_t ana_xpd_bbpll_i2c: 1; - uint32_t ana_xpd_bbpll : 1; - uint32_t ana_xpd_xtal : 1; + volatile uint32_t stable_xpd_bbpll : 1; + volatile uint32_t stable_xpd_xtal : 1; + volatile uint32_t reserved0 : 13; + volatile uint32_t sysclk_slp_sel : 1; + volatile uint32_t sysclk_sel : 2; + volatile uint32_t sysclk_nodiv : 1; + volatile uint32_t icg_sysclk_en : 1; + volatile uint32_t icg_modem_switch : 1; + volatile uint32_t icg_modem_code : 2; + volatile uint32_t icg_slp_sel : 1; + volatile uint32_t icg_global_xtal : 1; + volatile uint32_t icg_global_pll : 1; + volatile uint32_t ana_i2c_iso_en : 1; + volatile uint32_t ana_i2c_retention: 1; + volatile uint32_t ana_xpd_bb_i2c : 1; + volatile uint32_t ana_xpd_bbpll_i2c: 1; + volatile uint32_t ana_xpd_bbpll : 1; + volatile uint32_t ana_xpd_xtal : 1; }; - uint32_t val; + volatile uint32_t val; } clk_state0; - uint32_t clk_state1; - uint32_t clk_state2; + volatile uint32_t clk_state1; + volatile uint32_t clk_state2; union { struct { uint32_t reserved0 : 31; - uint32_t stable_vdd_spi_pwr_drv: 1; + volatile uint32_t stable_vdd_spi_pwr_drv: 1; }; - uint32_t val; + volatile uint32_t val; } vdd_spi_status; uint32_t reserved[150]; union { struct { - uint32_t pmu_date: 31; - uint32_t clk_en : 1; + volatile uint32_t pmu_date: 31; + volatile uint32_t clk_en : 1; }; uint32_t val; } date; 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. diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index a0270af63c..ee2cd1e40b 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -444,6 +444,7 @@ // TODO: IDF-5351 (Copy from esp32c3, need check) /*-------------------------- Power Management CAPS ----------------------------*/ #define SOC_PM_SUPPORT_WIFI_WAKEUP (1) +#define SOC_PM_SUPPORT_BEACON_WAKEUP (1) #define SOC_PM_SUPPORT_BT_WAKEUP (1) #define SOC_PM_SUPPORT_EXT1_WAKEUP (1) #define SOC_PM_SUPPORT_CPU_PD (1) @@ -453,10 +454,17 @@ #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_MAC_BB_PD (1) + +#define SOC_PM_SUPPORT_PMU_MODEM_STATE (1) +/* macro redefine for pass esp_wifi headers md5sum check */ +#define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE + #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!