diff --git a/components/esp_hw_support/include/esp_private/rtc_clk.h b/components/esp_hw_support/include/esp_private/rtc_clk.h index c71491d569..5c143b8396 100644 --- a/components/esp_hw_support/include/esp_private/rtc_clk.h +++ b/components/esp_hw_support/include/esp_private/rtc_clk.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,7 +32,7 @@ void rtc_clk_cpu_set_to_default_config(void); * Currently, this function is only used for tracking whether USB Serial/JTAG is using the 48MHz PHY clock * * Note: Calling this function only helps to not disable the BBPLL clock in `rtc_clk_cpu_freq_set_config`. - * For light and deep sleep, whether to disable the BBPLL in the interal call to `rtc_clk_cpu_freq_set_xtal` + * For light and deep sleep, whether to disable the BBPLL in the internal call to `rtc_clk_cpu_freq_set_xtal` * varies for targets. * On ESP32C3/S3, USB CDC device can not function properly during sleep due to the lack of APB clock. Therefore. * `rtc_clk_cpu_freq_set_xtal` will always disable BBPLL, no matter whether BBPLL has any consumer. @@ -65,6 +65,13 @@ void rtc_clk_mpll_disable(void); * @param[in] mpll_freq MPLL frequency */ void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq); + +/** + * Get the MPLL frequency + * @return the value of MPLL frequency in MHz + */ +uint32_t rtc_clk_mpll_get_freq(void); + #endif //#if SOC_CLK_MPLL_SUPPORTED /** diff --git a/components/esp_hw_support/port/esp32p4/rtc_clk.c b/components/esp_hw_support/port/esp32p4/rtc_clk.c index 24cf03972b..a5e45222cc 100644 --- a/components/esp_hw_support/port/esp32p4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32p4/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32p4/rom/rtc.h" #include "soc/rtc.h" #include "esp_private/rtc_clk.h" +#include "esp_attr.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" #include "hal/clk_tree_ll.h" @@ -26,6 +27,9 @@ static const char *TAG = "rtc_clk"; // CPLL frequency option, in 360/400MHz. Zero if CPLL is not enabled. static int s_cur_cpll_freq = 0; +// MPLL frequency option, 400MHz. Zero if MPLL is not enabled. +static DRAM_ATTR uint32_t s_cur_mpll_freq = 0; + void rtc_clk_32k_enable(bool enable) { if (enable) { @@ -483,6 +487,7 @@ bool rtc_dig_8m_enabled(void) void rtc_clk_mpll_disable(void) { clk_ll_mpll_disable(); + s_cur_mpll_freq = 0; } void rtc_clk_mpll_enable(void) @@ -500,4 +505,10 @@ void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq) while(!regi2c_ctrl_ll_mpll_calibration_is_done()); /* MPLL calibration stop */ regi2c_ctrl_ll_mpll_calibration_stop(); + s_cur_mpll_freq = mpll_freq; +} + +uint32_t rtc_clk_mpll_get_freq(void) +{ + return s_cur_mpll_freq; } diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index f627ad27cd..f0af1c3268 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -16,6 +16,7 @@ #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_timer_private.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/rtc_clk.h" #include "esp_private/sleep_event.h" #include "esp_private/system_internal.h" #include "esp_log.h" @@ -27,6 +28,7 @@ #include "soc/soc_caps.h" #include "driver/rtc_io.h" #include "hal/rtc_io_hal.h" +#include "hal/clk_tree_hal.h" #if SOC_PM_SUPPORT_PMU_MODEM_STATE #include "esp_private/pm_impl.h" @@ -924,6 +926,13 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m #endif #endif +#if SOC_CLK_MPLL_SUPPORTED + uint32_t mpll_freq_mhz = rtc_clk_mpll_get_freq(); + if (mpll_freq_mhz) { + rtc_clk_mpll_disable(); + } +#endif + #if SOC_DCDC_SUPPORTED uint64_t ldo_increased_us = rtc_time_slowclk_to_us(rtc_time_get() - s_config.rtc_ticks_at_ldo_prepare, s_config.rtc_clk_cal_period); if (ldo_increased_us < LDO_POWER_TAKEOVER_PREPARATION_TIME_US) { @@ -951,6 +960,13 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep); #endif +#if SOC_CLK_MPLL_SUPPORTED + if (mpll_freq_mhz) { + rtc_clk_mpll_enable(); + rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), mpll_freq_mhz); + } +#endif + /* Unhold the SPI CS pin */ #if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND) #if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index c77bfdb9f2..7da14280b5 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -78,7 +78,6 @@ TEST_CASE_MULTIPLE_STAGES("enter deep sleep on APP CPU and wake up using timer", #endif -#if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32P4) // TODO: IDF-9569 static void do_deep_sleep_timer(void) { esp_sleep_enable_timer_wakeup(2000000); @@ -111,7 +110,6 @@ TEST_CASE("wake up from light sleep using timer", "[deepsleep]") (tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f; TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt); } -#endif //NOTE: Explained in IDF-1445 | MR !14996 #if !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384) @@ -253,7 +251,6 @@ TEST_CASE("light sleep and frequency switching", "[deepsleep]") } } -#if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32P4) // TODO: IDF-9569 static void do_deep_sleep(void) { esp_sleep_enable_timer_wakeup(100000); @@ -289,7 +286,6 @@ TEST_CASE_MULTIPLE_STAGES("enter deep sleep after abort", "[deepsleep][reset=abo do_abort, check_abort_reset_and_sleep, check_sleep_reset); -#endif #if ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB static RTC_DATA_ATTR uint32_t s_wake_stub_var; @@ -331,7 +327,7 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub", "[deepsleep][reset=DEEPSLEE trigger a CRC calculation (done in hardware) for the entire RTC FAST memory before going to deep sleep and if it's invalid then the stub is not run. Also, while the CRC is being calculated the RTC FAST memory is not - accesible by the CPU (reads all zeros). + accessible by the CPU (reads all zeros). */ static void increment_rtc_memory_cb(void *arg) @@ -491,7 +487,7 @@ static void trigger_deepsleep(void) struct timeval start; // Use NVS instead of RTC mem to store the start time of deep sleep - // Beacuse not all esp chips support RTC mem(such as esp32c2) + // Because not all esp chips support RTC mem(such as esp32c2) // Initialize NVS esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { diff --git a/components/hal/linker.lf b/components/hal/linker.lf index b2d5f76a76..ed8d9f00f5 100644 --- a/components/hal/linker.lf +++ b/components/hal/linker.lf @@ -24,3 +24,5 @@ entries: spi_flash_hal_gpspi (noflash) if SOC_PMU_SUPPORTED = y: pmu_hal (noflash) + if SOC_CLK_MPLL_SUPPORTED = y: + clk_tree_hal: clk_hal_xtal_get_freq_mhz (noflash)