From a0cdaad4141676f8871916043cd2848550c828fd Mon Sep 17 00:00:00 2001 From: Xiao Xufeng Date: Tue, 25 Nov 2025 15:03:25 +0000 Subject: [PATCH] change(spi_flash): Flash frequency will not be decreased during DFS on ESP32-P4, when PSRAM is not enabled. --- components/esp_hw_support/clk_utils.c | 40 +++++++++---------- .../include/esp_private/mspi_timing_tuning.h | 7 +++- .../esp_hw_support/mspi_timing_tuning.c | 13 ++++-- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/components/esp_hw_support/clk_utils.c b/components/esp_hw_support/clk_utils.c index aa17d26ac64..f67d6b810ad 100644 --- a/components/esp_hw_support/clk_utils.c +++ b/components/esp_hw_support/clk_utils.c @@ -7,34 +7,38 @@ #include #include #include +#include #include "sdkconfig.h" #include "esp_check.h" #include "esp_log.h" -#include "soc/soc_caps.h" #include "soc/rtc.h" #include "hal/clk_tree_ll.h" #include "esp_private/mspi_timing_tuning.h" #include "esp_private/esp_clk_utils.h" +// Not directly divide to avoid truncation issue +// DIG-498 +#if CONFIG_IDF_TARGET_ESP32P4 +#define BELOW_FREQ_THRESHOLD(freq) ((freq) < CONFIG_SPIRAM_SPEED) +#endif + #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP void esp_clk_utils_mspi_speed_mode_sync_before_cpu_freq_switching(uint32_t target_cpu_src_freq, uint32_t target_cpu_freq) { #if CONFIG_IDF_TARGET_ESP32S3 (void) target_cpu_freq; + /* For ESP32S3, the clock source of MSPI is same as the CPU. When CPU use XTAL as clock source, we need to sync the + * MSPI speed mode. */ if (target_cpu_src_freq <= clk_ll_xtal_load_freq_mhz()) { mspi_timing_change_speed_mode_cache_safe(true); } -#elif CONFIG_IDF_TARGET_ESP32P4 - (void) target_cpu_src_freq; - /** - * Workaround for ESP32P4, - * f_cpu >= f_mspi +#elif CONFIG_IDF_TARGET_ESP32P4 && CONFIG_SPIRAM + /* On chips with AXI bus, currently there is a restriction that AXI frequency (usually equals to a portion of CPU + * frequency) needs to be greater than or equal to MSPI PSRAM frequency to avoid writing MSPI FIFO overflow. */ - if (((target_cpu_freq) < CONFIG_ESPTOOLPY_FLASHFREQ_VAL) -#if CONFIG_SPIRAM - || ((target_cpu_freq) < CONFIG_SPIRAM_SPEED) -#endif - ) { + if (BELOW_FREQ_THRESHOLD(target_cpu_freq)) { + // Before switching to low speed mode, verify CPU frequency meets the constraint + assert(target_cpu_freq >= mspi_timing_get_psram_low_speed_freq_mhz()); mspi_timing_change_speed_mode_cache_safe(true); } #else @@ -50,17 +54,11 @@ void esp_clk_utils_mspi_speed_mode_sync_after_cpu_freq_switching(uint32_t target if (target_cpu_src_freq > clk_ll_xtal_load_freq_mhz()) { mspi_timing_change_speed_mode_cache_safe(false); } -#elif CONFIG_IDF_TARGET_ESP32P4 - (void) target_cpu_src_freq; - /** - * Workaround for ESP32P4, - * f_cpu >= f_mspi +#elif CONFIG_IDF_TARGET_ESP32P4 && CONFIG_SPIRAM + /* On chips with AXI bus, currently there is a restriction that AXI frequency (usually equals to a portion of CPU + * frequency) needs to be greater than or equal to MSPI PSRAM frequency to avoid writing MSPI FIFO overflow. */ - if (((target_cpu_freq) >= CONFIG_ESPTOOLPY_FLASHFREQ_VAL) -#if CONFIG_SPIRAM - && ((target_cpu_freq) >= CONFIG_SPIRAM_SPEED) -#endif - ) { + if (!BELOW_FREQ_THRESHOLD(target_cpu_freq)) { mspi_timing_change_speed_mode_cache_safe(false); } #else diff --git a/components/esp_hw_support/include/esp_private/mspi_timing_tuning.h b/components/esp_hw_support/include/esp_private/mspi_timing_tuning.h index c1e999cc181..be59ef7dfb6 100644 --- a/components/esp_hw_support/include/esp_private/mspi_timing_tuning.h +++ b/components/esp_hw_support/include/esp_private/mspi_timing_tuning.h @@ -24,6 +24,12 @@ extern "C" { */ void mspi_timing_enter_low_speed_mode(bool control_spi1); +/** + * @brief Get PSRAM frequency in low speed mode (MHz) + * @return PSRAM frequency in MHz when in low speed mode + */ +uint32_t mspi_timing_get_psram_low_speed_freq_mhz(void); + /** * @brief Make MSPI work under the frequency as users set, may add certain delays to MSPI RX direction to meet timing requirements. * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 @@ -54,7 +60,6 @@ void mspi_timing_psram_tuning(void); */ void mspi_timing_set_pin_drive_strength(void); - #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/mspi_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning.c index 946d78f6ec6..2bff3eea155 100644 --- a/components/esp_hw_support/mspi_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning.c @@ -474,6 +474,11 @@ void mspi_timing_psram_tuning(void) /*------------------------------------------------------------------------------ * APIs to make SPI0 (and SPI1) FLASH work for high/low freq *----------------------------------------------------------------------------*/ +uint32_t mspi_timing_get_psram_low_speed_freq_mhz(void) +{ + return 20; +} + void mspi_timing_enter_low_speed_mode(bool control_spi1) { #if SOC_MEMSPI_FLASH_CLK_SRC_IS_INDEPENDENT @@ -497,14 +502,14 @@ void mspi_timing_enter_low_speed_mode(bool control_spi1) * Should be extended to other no-timing-tuning chips if needed. e.g.: * we still need to turn down Flash / PSRAM clock speed at a certain period of time */ - mspi_timing_config_set_flash_clock(20, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1); - mspi_timing_config_set_psram_clock(20, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1); -#endif //#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING - + uint32_t low_speed_freq_mhz = mspi_timing_get_psram_low_speed_freq_mhz(); + mspi_timing_config_set_flash_clock(low_speed_freq_mhz, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1); + mspi_timing_config_set_psram_clock(low_speed_freq_mhz, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1); #if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING mspi_timing_flash_config_clear_tuning_regs(control_spi1); mspi_timing_psram_config_clear_tuning_regs(control_spi1); #endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING +#endif //#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING } /**