diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c index 53632ccffd..7a4e36f9cc 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c @@ -55,7 +55,7 @@ void IRAM_ATTR bootloader_init_mspi_clock(void) // SPLL clock on C5 is 480MHz , and mspi_pll needs 80MHz // in this stage, set divider as 6 _mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_SPLL); - mspi_ll_fast_set_hs_divider(6); + mspi_timing_ll_set_core_clock(MSPI_TIMING_LL_MSPI_ID_0, MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT); } void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c index a1fb72f94e..c12f5aad1b 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c @@ -52,7 +52,7 @@ void IRAM_ATTR bootloader_init_mspi_clock(void) // SPLL clock on C61 is 480MHz , and mspi_pll needs 80MHz // in this stage, set divider as 6 _mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_DEFAULT); - mspi_ll_fast_set_hs_divider(6); + mspi_timing_ll_set_core_clock(MSPI_TIMING_LL_MSPI_ID_0, MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT); } void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 4fe375d1bf..328ffd7fab 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -134,14 +134,17 @@ if(NOT non_os_build) if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) list(APPEND srcs "mspi_timing_tuning/mspi_timing_tuning.c") - if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY) - list(APPEND srcs "mspi_timing_tuning/mspi_timing_by_mspi_delay.c") + if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY AND NOT CONFIG_IDF_TARGET_ESP32S3) + if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c") + list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c") + endif() endif() + if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS) - list(APPEND srcs "mspi_timing_tuning/mspi_timing_by_dqs.c") + list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c") endif() if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY) - list(APPEND srcs "mspi_timing_tuning/mspi_timing_by_flash_delay.c") + list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c") endif() endif() @@ -171,7 +174,8 @@ endif() set(public_include_dirs "include" "include/soc" "include/soc/${target}" "dma/include" "ldo/include" "debug_probe/include" - "mspi_timing_tuning/include" "power_supply/include") + "mspi_timing_tuning/include" "mspi_timing_tuning/tuning_scheme_impl/include" + "power_supply/include") if(CONFIG_IDF_TARGET_ESP32H4) list(REMOVE_ITEM srcs diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c index e86694dcd2..f6b2c39651 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning/mspi_timing_tuning.c @@ -18,9 +18,9 @@ #include "esp_private/esp_cache_private.h" #include "esp_private/mspi_timing_tuning.h" #include "esp_private/mspi_timing_config.h" -#include "mspi_timing_by_mspi_delay.h" -#include "mspi_timing_by_dqs.h" -#include "mspi_timing_by_flash_delay.h" +#include "esp_private/mspi_timing_by_mspi_delay.h" +#include "esp_private/mspi_timing_by_dqs.h" +#include "esp_private/mspi_timing_by_flash_delay.h" #if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY || SOC_MEMSPI_TIMING_TUNING_BY_DQS || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY #include "mspi_timing_tuning_configs.h" #endif @@ -233,6 +233,9 @@ static void s_sweep_for_success_sample_points(uint8_t *reference_data, void *con #endif if (memcmp(reference_data, read_data, sizeof(read_data)) == 0) { out_array[config_idx] += 1; + ESP_EARLY_LOGV(TAG, "config_idx: %d, good", config_idx); + } else { + ESP_EARLY_LOGV(TAG, "config_idx: %d, bad", config_idx); } } } @@ -619,9 +622,8 @@ void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing *----------------------------------------------------------------------------*/ void mspi_timing_set_pin_drive_strength(void) { -#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY - //For now, set them all to 3. Need to check after QVL test results are out. TODO: IDF-3663 +#if CONFIG_IDF_TARGET_ESP32S3 //Set default pin drive mspi_timing_ll_set_all_pin_drive(0, 3); -#endif // #if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY +#endif } diff --git a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/CMakeLists.txt b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/CMakeLists.txt new file mode 100644 index 0000000000..b8b6e61170 --- /dev/null +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/CMakeLists.txt @@ -0,0 +1,11 @@ +target_include_directories(${COMPONENT_LIB} PUBLIC . include) + +set(srcs) + +if(NOT BOOTLOADER_BUILD) + if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) + list(APPEND srcs "mspi_timing_config.c") + endif() +endif() + +target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) diff --git a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_config.c b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_config.c new file mode 100644 index 0000000000..6dc5e63d44 --- /dev/null +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_config.c @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_types.h" +#include "esp_log.h" +#include "soc/soc_caps.h" +#include "esp_private/periph_ctrl.h" +#include "esp_private/mspi_timing_config.h" +#include "mspi_timing_tuning_configs.h" +#include "hal/psram_ctrlr_ll.h" +#include "hal/mspi_ll.h" + +#define FLASH_LOW_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT +#define FLASH_HIGH_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_CORE_CLOCK_MHZ +#define PSRAM_LOW_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT +#define PSRAM_HIGH_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_CORE_CLOCK_MHZ + +const static char *TAG = "MSPI Timing"; + +//-------------------------------------MSPI Clock Setting-------------------------------------// +static void s_mspi_flash_set_core_clock(uint8_t mspi_id, uint32_t core_clock_mhz) +{ + mspi_timing_ll_set_core_clock(mspi_id, core_clock_mhz); +} + +static void s_mspi_psram_set_core_clock(uint8_t mspi_id, uint32_t core_clock_mhz) +{ + mspi_timing_ll_set_core_clock(mspi_id, core_clock_mhz); +} + +void mspi_timing_config_set_flash_clock(uint32_t flash_freq_mhz, mspi_timing_speed_mode_t speed_mode, bool control_both_mspi) +{ + uint32_t core_clock_mhz = 0; + if (speed_mode == MSPI_TIMING_SPEED_MODE_LOW_PERF) { + core_clock_mhz = FLASH_LOW_SPEED_CORE_CLOCK_MHZ; + } else { + core_clock_mhz = FLASH_HIGH_SPEED_CORE_CLOCK_MHZ; + } + //SPI0 and SPI1 share the register for core clock. So we only set SPI0 here. + s_mspi_flash_set_core_clock(MSPI_TIMING_LL_MSPI_ID_0, core_clock_mhz); + + uint32_t freqdiv = core_clock_mhz / flash_freq_mhz; + ESP_EARLY_LOGV(TAG, "flash freqdiv: %d", freqdiv); + assert(freqdiv > 0); + uint32_t reg_val = mspi_timing_ll_calculate_clock_reg(freqdiv); + mspi_timing_ll_set_flash_clock(MSPI_TIMING_LL_MSPI_ID_0, reg_val); + if (control_both_mspi) { + mspi_timing_ll_set_flash_clock(MSPI_TIMING_LL_MSPI_ID_1, reg_val); + } +} + +void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_speed_mode_t speed_mode, bool control_both_mspi) +{ + (void)control_both_mspi; // for compatibility + uint32_t core_clock_mhz = 0; + if (speed_mode == MSPI_TIMING_SPEED_MODE_LOW_PERF) { + core_clock_mhz = PSRAM_LOW_SPEED_CORE_CLOCK_MHZ; + } else { + core_clock_mhz = PSRAM_HIGH_SPEED_CORE_CLOCK_MHZ; + } + //SPI0 and SPI1 share the register for core clock. So we only set SPI0 here. + s_mspi_psram_set_core_clock(MSPI_TIMING_LL_MSPI_ID_0, core_clock_mhz); + + uint32_t freqdiv = core_clock_mhz / psram_freq_mhz; + ESP_EARLY_LOGV(TAG, "psram freqdiv: %d", freqdiv); + assert(freqdiv > 0); + uint32_t reg_val = mspi_timing_ll_calculate_clock_reg(freqdiv); + mspi_timing_ll_set_psram_clock(MSPI_TIMING_LL_MSPI_ID_0, reg_val); +} diff --git a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h new file mode 100644 index 0000000000..f0fe12421f --- /dev/null +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "sdkconfig.h" + +#define MSPI_TIMING_MSPI1_IS_INVOLVED CONFIG_ESPTOOLPY_FLASHFREQ_120M //This means esp flash driver needs to be notified +#define MSPI_TIMING_CONFIG_NUM_MAX 32 //This should be larger than the max available timing config num +#define MSPI_TIMING_TEST_DATA_LEN 128 +#define MSPI_TIMING_PSRAM_TEST_DATA_ADDR 0x100000 + +//--------------------------------------FLASH Sampling Mode --------------------------------------// +#define MSPI_TIMING_FLASH_STR_MODE 1 +//--------------------------------------FLASH Module Clock --------------------------------------// +#if CONFIG_ESPTOOLPY_FLASHFREQ_20M +#define MSPI_TIMING_FLASH_MODULE_CLOCK 20 +#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M +#define MSPI_TIMING_FLASH_MODULE_CLOCK 40 +#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M +#define MSPI_TIMING_FLASH_MODULE_CLOCK 80 +#endif +//------------------------------------FLASH Needs Tuning or not-------------------------------------// +#if MSPI_TIMING_FLASH_STR_MODE +#define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 80) +#endif + +//--------------------------------------PSRAM Sampling Mode --------------------------------------// +#define MSPI_TIMING_PSRAM_STR_MODE 1 +//--------------------------------------PSRAM Module Clock --------------------------------------// +#if CONFIG_SPIRAM +#if CONFIG_SPIRAM_SPEED_40M +#define MSPI_TIMING_PSRAM_MODULE_CLOCK 40 +#elif CONFIG_SPIRAM_SPEED_80M +#define MSPI_TIMING_PSRAM_MODULE_CLOCK 80 +#endif +#else //Disable PSRAM +#define MSPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz +#endif +//------------------------------------PSRAM Needs Tuning or not-------------------------------------// +#if MSPI_TIMING_PSRAM_STR_MODE +#define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 40) +#endif + +///////////////////////////////////// FLASH CORE CLOCK ///////////////////////////////////// +#define MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 80 + +///////////////////////////////////// PSRAM CORE CLOCK ///////////////////////////////////// +#if CONFIG_SPIRAM_SPEED_80M +#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 80 +#endif + +//------------------------------------------Determine the Core Clock-----------------------------------------------// +/** + * @note + * Limitation 1: + * MSPI FLASH and PSRAM share the core clock register. Therefore, + * the expected CORE CLOCK frequencies should be the same. + */ +#if MSPI_TIMING_FLASH_NEEDS_TUNING && MSPI_TIMING_PSRAM_NEEDS_TUNING +ESP_STATIC_ASSERT(MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ == MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ, "FLASH and PSRAM Mode configuration are not supported"); +#define MSPI_TIMING_CORE_CLOCK_MHZ MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ + +//If only FLASH needs tuning, the core clock COULD be as FLASH expected +#elif MSPI_TIMING_FLASH_NEEDS_TUNING && !MSPI_TIMING_PSRAM_NEEDS_TUNING +ESP_STATIC_ASSERT(MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ % MSPI_TIMING_PSRAM_MODULE_CLOCK == 0, "FLASH and PSRAM Mode configuration are not supported"); +#define MSPI_TIMING_CORE_CLOCK_MHZ MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ + +//If only PSRAM needs tuning, the core clock COULD be as PSRAM expected +#elif !MSPI_TIMING_FLASH_NEEDS_TUNING && MSPI_TIMING_PSRAM_NEEDS_TUNING +ESP_STATIC_ASSERT(MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ % MSPI_TIMING_FLASH_MODULE_CLOCK == 0, "FLASH and PSRAM Mode configuration are not supported"); +#define MSPI_TIMING_CORE_CLOCK_MHZ MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ + +#else +#define MSPI_TIMING_CORE_CLOCK_MHZ 80 +#endif + + +//------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------// +#define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \ + (mspi_timing_config_t) { .tuning_config_table = MSPI_TIMING_##type##_CONFIG_TABLE_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \ + .available_config_num = MSPI_TIMING_##type##_CONFIG_NUM_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \ + .default_config_id = MSPI_TIMING_##type##_DEFAULT_CONFIG_ID_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode } + +#define _GET_TUNING_CONFIG(type, core_clock, module_clock, mode) __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) + +#define MSPI_TIMING_FLASH_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(FLASH, core_clock_mhz, module_clock_mhz, mode) +#define MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(PSRAM, core_clock_mhz, module_clock_mhz, mode) + + +/** + * Timing Tuning Parameters + */ +//PSRAM: core clock 80M, module clock 80M, STR mode +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_80M_MODULE_CLK_80M_STR_MODE {{2, 2, 1}, {2, 1, 1}, {2, 0, 1}, {0, 0, 0}, {3, 1, 2}, {2, 3, 2}, {2, 2, 2}, {2, 1, 2}, {2, 0, 1}, {0, 0, 1}, {3, 1, 3}, {2, 3, 3}, {2, 2, 3}, {2, 1, 3}} +#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_80M_MODULE_CLK_80M_STR_MODE 14 +#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_80M_MODULE_CLK_80M_STR_MODE 5 diff --git a/components/esp_hw_support/mspi_timing_tuning/port/esp32s3/CMakeLists.txt b/components/esp_hw_support/mspi_timing_tuning/port/esp32s3/CMakeLists.txt index 73aac5814e..e39412535c 100644 --- a/components/esp_hw_support/mspi_timing_tuning/port/esp32s3/CMakeLists.txt +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32s3/CMakeLists.txt @@ -4,8 +4,8 @@ set(srcs) if(NOT BOOTLOADER_BUILD) if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) - list(APPEND srcs "mspi_timing_config.c") + list(APPEND srcs "mspi_timing_config.c" "mspi_timing_by_mspi_delay.c") endif() endif() -target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") +target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_mspi_delay.c b/components/esp_hw_support/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c similarity index 99% rename from components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_mspi_delay.c rename to components/esp_hw_support/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c index d48b856d73..cde0bafafa 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_mspi_delay.c +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c @@ -23,7 +23,7 @@ #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" #include "esp_private/mspi_timing_config.h" -#include "mspi_timing_by_mspi_delay.h" +#include "esp_private/mspi_timing_by_mspi_delay.h" #include "bootloader_flash.h" #include "esp32s3/rom/spi_flash.h" #include "esp32s3/rom/opi_flash.h" diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_dqs.h b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_dqs.h similarity index 99% rename from components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_dqs.h rename to components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_dqs.h index 935d78f575..aa73031da9 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_dqs.h +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_dqs.h @@ -14,7 +14,7 @@ #include #include "soc/soc_caps.h" #if SOC_MEMSPI_TIMING_TUNING_BY_DQS -#include "mspi_timing_types.h" +#include "esp_private/mspi_timing_impl_types.h" #include "mspi_timing_tuning_configs.h" #include "hal/mspi_ll.h" #endif diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_flash_delay.h b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_flash_delay.h similarity index 98% rename from components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_flash_delay.h rename to components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_flash_delay.h index 2457c7e857..e8ea3d9f97 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_flash_delay.h +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_flash_delay.h @@ -14,7 +14,7 @@ #include #include "soc/soc_caps.h" #if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY -#include "mspi_timing_types.h" +#include "esp_private/mspi_timing_impl_types.h" #include "mspi_timing_tuning_configs.h" #endif diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_mspi_delay.h b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_mspi_delay.h similarity index 99% rename from components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_mspi_delay.h rename to components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_mspi_delay.h index bb3e27d2af..938266924e 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_mspi_delay.h +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_by_mspi_delay.h @@ -12,9 +12,10 @@ #pragma once #include +#include "sdkconfig.h" #include "soc/soc_caps.h" #if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY -#include "mspi_timing_types.h" +#include "esp_private/mspi_timing_impl_types.h" #include "mspi_timing_tuning_configs.h" #endif diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_types.h b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_impl_types.h similarity index 100% rename from components/esp_hw_support/mspi_timing_tuning/mspi_timing_types.h rename to components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/include/esp_private/mspi_timing_impl_types.h diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_dqs.c b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c similarity index 99% rename from components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_dqs.c rename to components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c index 703d955777..78a09d422f 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_dqs.c +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c @@ -19,7 +19,7 @@ #include "esp_err.h" #include "esp_types.h" #include "esp_log.h" -#include "mspi_timing_by_dqs.h" +#include "esp_private/mspi_timing_by_dqs.h" #include "mspi_timing_tuning_configs.h" #include "esp_private/mspi_timing_config.h" #include "esp_private/rtc_clk.h" diff --git a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_flash_delay.c b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c similarity index 97% rename from components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_flash_delay.c rename to components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c index bce343255b..e99ada255d 100644 --- a/components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_flash_delay.c +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,7 @@ #include "esp_err.h" #include "esp_types.h" #include "esp_log.h" -#include "mspi_timing_by_flash_delay.h" +#include "esp_private/mspi_timing_by_flash_delay.h" #include "mspi_timing_tuning_configs.h" #include "esp_private/mspi_timing_config.h" #include "hal/mspi_ll.h" @@ -110,11 +110,8 @@ static uint32_t s_select_best_tuning_config_str(const mspi_timing_config_t *conf static uint32_t s_select_best_tuning_config(const mspi_timing_config_t *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr, bool is_flash) { uint32_t best_point = 0; - if (is_ddr) { - assert(false); - } else { - best_point = s_select_best_tuning_config_str(configs, consecutive_length, end); - } + assert(!is_ddr); + best_point = s_select_best_tuning_config_str(configs, consecutive_length, end); return best_point; } diff --git a/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c new file mode 100644 index 0000000000..6b0c4f2b63 --- /dev/null +++ b/components/esp_hw_support/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c @@ -0,0 +1,368 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief + * + * This file contains configuration APIs doing MSPI timing tuning by MSPI delay + * This file will only be built, when `SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY == 1` + */ + +#include +#include "sdkconfig.h" +#include "string.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_types.h" +#include "esp_log.h" +#include "rom/spi_flash.h" +#include "hal/mspi_ll.h" +#include "hal/psram_types.h" +#include "hal/psram_ctrlr_ll.h" +#include "esp_private/mspi_timing_config.h" +#include "esp_private/mspi_timing_by_mspi_delay.h" +#include "mspi_timing_tuning_configs.h" + +#define QPI_PSRAM_FAST_READ 0XEB +#define QPI_PSRAM_WRITE 0X38 +#define QPI_PSRAM_FAST_READ_DUMMY 6 + +const static char *TAG = "MSPI Timing"; + +//-------------------------------------FLASH timing tuning register config-------------------------------------// +static void s_set_flash_din_mode_num(uint8_t mspi_id, uint8_t din_mode, uint8_t din_num) +{ + mspi_timing_ll_set_flash_din_mode(mspi_id, din_mode); + mspi_timing_ll_set_flash_din_num(mspi_id, din_num); +} + +static void s_set_flash_extra_dummy(uint8_t mspi_id, uint8_t extra_dummy) +{ + mspi_timing_ll_set_flash_extra_dummy(mspi_id, extra_dummy); +} + +//-------------------------------------PSRAM timing tuning register config-------------------------------------// +void mspi_timing_psram_init(uint32_t psram_freq_mhz) +{ + mspi_timing_config_set_flash_clock(psram_freq_mhz, MSPI_TIMING_SPEED_MODE_NORMAL_PERF, true); + + //Power on HCLK + mspi_timinng_ll_enable_psram_timing_adjust_clk(MSPI_TIMING_LL_MSPI_ID_0); +} + +void mspi_timing_get_psram_tuning_configs(mspi_timing_config_t *config) +{ +#if MSPI_TIMING_PSRAM_DTR_MODE +#define PSRAM_MODE DTR_MODE +#else //MSPI_TIMING_PSRAM_STR_MODE +#define PSRAM_MODE STR_MODE +#endif + +#if CONFIG_SPIRAM_SPEED_80M + *config = MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 80, STR_MODE); +#elif CONFIG_SPIRAM_SPEED_120M + *config = MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 120, PSRAM_MODE); +#else + assert(false && "should never reach here"); +#endif + +#undef PSRAM_MODE +} + +static void s_set_psram_din_mode_num(uint8_t mspi_id, uint8_t din_mode, uint8_t din_num) +{ + mspi_timing_ll_set_psram_din_mode(mspi_id, din_mode); + mspi_timing_ll_set_psram_din_num(mspi_id, din_num); +} + +static void s_set_psram_extra_dummy(uint8_t mspi_id, uint8_t extra_dummy) +{ + mspi_timing_ll_set_psram_extra_dummy(mspi_id, extra_dummy); +} + +void mspi_timing_config_psram_set_tuning_regs(const void *configs, uint8_t id) +{ + const mspi_timing_tuning_param_t *params = &((mspi_timing_config_t *)configs)->tuning_config_table[id]; + /** + * 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless + * SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning + * 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config + */ + s_set_psram_din_mode_num(MSPI_TIMING_LL_MSPI_ID_0, params->spi_din_mode, params->spi_din_num); + + s_set_flash_extra_dummy(MSPI_TIMING_LL_MSPI_ID_1, params->extra_dummy_len); +} + +//-------------------------------------------PSRAM Read/Write------------------------------------------// +static void psram_exec_cmd(int mspi_id, psram_cmd_mode_t mode, + uint32_t cmd, int cmd_bit_len, + uint32_t addr, int addr_bit_len, + int dummy_bits, + uint8_t* mosi_data, int mosi_bit_len, + uint8_t* miso_data, int miso_bit_len, + uint32_t cs_mask, + bool is_write_erase_operation) +{ + esp_rom_spiflash_read_mode_t rd_mode = (mode == PSRAM_HAL_CMD_QPI) ? ESP_ROM_SPIFLASH_QIO_MODE : ESP_ROM_SPIFLASH_SLOWRD_MODE; + + esp_rom_spi_set_op_mode(mspi_id, rd_mode); + if (mode == PSRAM_HAL_CMD_QPI) { + psram_ctrlr_ll_enable_quad_command(PSRAM_CTRLR_LL_MSPI_ID_1, true); + } + psram_ctrlr_ll_common_transaction_base(mspi_id, rd_mode, + cmd, cmd_bit_len, + addr, addr_bit_len, + dummy_bits, + mosi_data, mosi_bit_len, + miso_data, miso_bit_len, + cs_mask, + is_write_erase_operation); +} + +#define FIFO_SIZE_BYTE 32 +static void s_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len) +{ + if (len % FIFO_SIZE_BYTE != 0) { + ESP_EARLY_LOGE(TAG, "wrong length %d", len); + assert(false); + } + + uint8_t mspi_id = MSPI_TIMING_LL_MSPI_ID_1; + uint8_t cmd = QPI_PSRAM_WRITE; + uint8_t cmd_len = 8; + uint8_t dummy_len = 0; + uint8_t addr_len = 24; + psram_cmd_mode_t spi_mode = PSRAM_HAL_CMD_QPI; + for (uint32_t idx= 0; idx < len / FIFO_SIZE_BYTE; idx++) { + psram_exec_cmd(mspi_id, spi_mode, + cmd, cmd_len, + addr + idx * FIFO_SIZE_BYTE, addr_len, + dummy_len, + buf + idx * FIFO_SIZE_BYTE, FIFO_SIZE_BYTE * 8, + NULL, 0, + PSRAM_LL_CS_SEL, + false); + } +} + +static void s_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len) +{ + if (len % FIFO_SIZE_BYTE != 0) { + ESP_EARLY_LOGE(TAG, "wrong length %d", len); + assert(false); + } + + uint8_t mspi_id = MSPI_TIMING_LL_MSPI_ID_1; + uint8_t cmd = QPI_PSRAM_FAST_READ; + uint8_t cmd_len = 8; + uint8_t dummy_len = QPI_PSRAM_FAST_READ_DUMMY; + uint8_t addr_len = 24; + psram_cmd_mode_t spi_mode = PSRAM_HAL_CMD_QPI; + for (uint32_t idx = 0; idx < len/FIFO_SIZE_BYTE; idx++) { + psram_exec_cmd(mspi_id, spi_mode, + cmd, cmd_len, + addr + idx*FIFO_SIZE_BYTE, addr_len, + dummy_len, + NULL, 0, + buf + idx*FIFO_SIZE_BYTE, FIFO_SIZE_BYTE * 8, + PSRAM_LL_CS_SEL, + false); + } +} + +static void s_psram_execution(uint8_t *buf, uint32_t addr, uint32_t len, bool is_read) +{ + while (len) { + uint32_t length = MIN(len, 32); + if (is_read) { + s_psram_read_data(buf, addr, length); + } else { + s_psram_write_data(buf, addr, length); + } + addr += length; + buf += length; + len -= length; + } +} + +void mspi_timing_config_psram_prepare_reference_data(uint8_t *buf, uint32_t len) +{ + assert((len == MSPI_TIMING_TEST_DATA_LEN) && (len % 4 == 0)); + for (int i = 0; i < len / 4; i++) { + ((uint32_t *)buf)[i] = 0xa5ff005a; + } +} + +void mspi_timing_config_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len) +{ + s_psram_execution(buf, addr, len, false); +} + +void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len) +{ + s_psram_execution(buf, addr, len, true); +} + +/*------------------------------------------------------------------------------------------------- + * Best Timing Tuning Params Selection + *-------------------------------------------------------------------------------------------------*/ +static uint32_t s_select_best_tuning_config_str(const mspi_timing_config_t *configs, uint32_t consecutive_length, uint32_t end) +{ + //STR best point scheme + uint32_t best_point = 0; + + if (consecutive_length < 3) { + //tuning is FAIL, select default point, and generate a warning + best_point = configs->default_config_id; + ESP_EARLY_LOGW(TAG, "tuning fail, best point is fallen back to index %"PRIu32"", best_point); + } else { + best_point = end - consecutive_length / 2; + ESP_EARLY_LOGI(TAG, "tuning success, best point is index %"PRIu32"", best_point); + } + + return best_point; +} + +static uint32_t s_select_best_tuning_config(const mspi_timing_config_t *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr, bool is_flash) +{ + uint32_t best_point = 0; + assert(!is_ddr); + best_point = s_select_best_tuning_config_str(configs, consecutive_length, end); + + return best_point; +} + +uint32_t mspi_timing_flash_select_best_tuning_config(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr) +{ + const mspi_timing_config_t *timing_configs = (const mspi_timing_config_t *)configs; + uint32_t best_point = s_select_best_tuning_config(timing_configs, consecutive_length, end, reference_data, is_ddr, true); + ESP_EARLY_LOGI(TAG, "Flash timing tuning index: %"PRIu32"", best_point); + + return best_point; +} + +uint32_t mspi_timing_psram_select_best_tuning_config(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr) +{ + const mspi_timing_config_t *timing_configs = (const mspi_timing_config_t *)configs; + uint32_t best_point = s_select_best_tuning_config(timing_configs, consecutive_length, end, reference_data, is_ddr, false); + ESP_EARLY_LOGI(TAG, "PSRAM timing tuning index: %"PRIu32"", best_point); + + return best_point; +} + +static mspi_timing_tuning_param_t s_flash_best_timing_tuning_config; +static mspi_timing_tuning_param_t s_psram_best_timing_tuning_config; + +void mspi_timing_flash_set_best_tuning_config(const void *configs, uint8_t best_id) +{ + s_flash_best_timing_tuning_config = ((const mspi_timing_config_t *)configs)->tuning_config_table[best_id]; +} + +void mspi_timing_psram_set_best_tuning_config(const void *configs, uint8_t best_id) +{ + s_psram_best_timing_tuning_config = ((const mspi_timing_config_t *)configs)->tuning_config_table[best_id]; +} + +/*------------------------------------------------------------------------------------------------- + * Best Timing Tuning Params Clear / Set + *-------------------------------------------------------------------------------------------------*/ +void mspi_timing_flash_config_clear_tuning_regs(bool control_both_mspi) +{ + s_set_flash_din_mode_num(MSPI_TIMING_LL_MSPI_ID_0, 0, 0); //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg + s_set_flash_extra_dummy(MSPI_TIMING_LL_MSPI_ID_0, 0); + + //Won't touch SPI1 registers if not control_both_mspi + if (control_both_mspi) { + s_set_flash_extra_dummy(MSPI_TIMING_LL_MSPI_ID_1, 0); + } +} + +void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi) +{ + //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg + s_set_flash_din_mode_num(MSPI_TIMING_LL_MSPI_ID_0, s_flash_best_timing_tuning_config.spi_din_mode, s_flash_best_timing_tuning_config.spi_din_num); + s_set_flash_extra_dummy(MSPI_TIMING_LL_MSPI_ID_0, s_flash_best_timing_tuning_config.extra_dummy_len); + if (control_both_mspi) { + s_set_flash_extra_dummy(MSPI_TIMING_LL_MSPI_ID_1, s_flash_best_timing_tuning_config.extra_dummy_len); + } else { + //Won't touch SPI1 registers + } + + int spi1_usr_dummy = 0; + int spi1_extra_dummy = 0; + int spi0_usr_dummy = 0; + int spi0_extra_dummy = 0; + mspi_timing_ll_get_flash_dummy(MSPI_TIMING_LL_MSPI_ID_0, &spi0_usr_dummy, &spi0_extra_dummy); + mspi_timing_ll_get_flash_dummy(MSPI_TIMING_LL_MSPI_ID_1, &spi1_usr_dummy, &spi1_extra_dummy); + ESP_EARLY_LOGV(TAG, "flash, spi0_usr_dummy: %d, spi0_extra_dummy: %d, spi1_usr_dummy: %d, spi1_extra_dummy: %d", spi0_usr_dummy, spi0_extra_dummy, spi1_usr_dummy, spi1_extra_dummy); +} + +void mspi_timing_psram_config_clear_tuning_regs(bool control_both_mspi) +{ + (void)control_both_mspi; //for compatibility + s_set_psram_din_mode_num(MSPI_TIMING_LL_MSPI_ID_0, 0, 0); + s_set_psram_extra_dummy(MSPI_TIMING_LL_MSPI_ID_0, 0); +} + +void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi) +{ + (void)control_both_mspi; //for compatibility + s_set_psram_din_mode_num(MSPI_TIMING_LL_MSPI_ID_0, s_psram_best_timing_tuning_config.spi_din_mode, s_psram_best_timing_tuning_config.spi_din_num); + s_set_psram_extra_dummy(MSPI_TIMING_LL_MSPI_ID_0, s_psram_best_timing_tuning_config.extra_dummy_len); + + int spi0_usr_rdummy = 0; + int spi0_extra_dummy = 0; + mspi_timing_ll_get_psram_dummy(MSPI_TIMING_LL_MSPI_ID_0, &spi0_usr_rdummy, &spi0_extra_dummy); + ESP_EARLY_LOGV(TAG, "psram, spi0_usr_rdummy: %d, spi0_extra_dummy: %d", spi0_usr_rdummy, spi0_extra_dummy); +} + +/*------------------------------------------------------------------------------------------------- + * To let upper lay (spi_flash_timing_tuning.c) to know the necessary timing registers + *-------------------------------------------------------------------------------------------------*/ +/** + * Get the SPI1 Flash CS timing setting. The setup time and hold time are both realistic cycles. + * @note On ESP32-S3, SPI0/1 share the Flash CS timing registers. Therefore, we should not change these values. + * @note This function inform `spi_flash_timing_tuning.c` (driver layer) of the cycle, + * and other component (esp_flash driver) should get these cycle and configure the registers accordingly. + */ +void mspi_timing_config_get_cs_timing(uint8_t *setup_time, uint32_t *hold_time) +{ + *setup_time = mspi_timing_ll_get_cs_setup_val(MSPI_TIMING_LL_MSPI_ID_0); + *hold_time = mspi_timing_ll_get_cs_hold_val(0); + /** + * The logic here is, if setup_en / hold_en is false, then we return the realistic cycle number, + * which is 0. If true, then the realistic cycle number is (reg_value + 1) + */ + if (mspi_timing_ll_is_cs_setup_enabled(MSPI_TIMING_LL_MSPI_ID_0)) { + *setup_time += 1; + } else { + *setup_time = 0; + } + if (mspi_timing_ll_is_cs_hold_enabled(MSPI_TIMING_LL_MSPI_ID_0)) { + *hold_time += 1; + } else { + *hold_time = 0; + } +} + +/** + * Get the SPI1 Flash clock setting. + * @note Similarly, this function inform `spi_flash_timing_tuning.c` (driver layer) of the clock setting, + * and other component (esp_flash driver) should get these and configure the registers accordingly. + */ +uint32_t mspi_timing_config_get_flash_clock_reg(void) +{ + return mspi_timing_ll_get_clock_reg(MSPI_TIMING_LL_MSPI_ID_1); +} + +uint8_t mspi_timing_config_get_flash_extra_dummy(void) +{ +#if MSPI_TIMING_FLASH_NEEDS_TUNING + return s_flash_best_timing_tuning_config.extra_dummy_len; +#else + return 0; +#endif +} diff --git a/components/esp_hw_support/test_apps/dma/sdkconfig.defaults.esp32c5 b/components/esp_hw_support/test_apps/dma/sdkconfig.defaults.esp32c5 index 5bfc98dcc7..728fbe8889 100644 --- a/components/esp_hw_support/test_apps/dma/sdkconfig.defaults.esp32c5 +++ b/components/esp_hw_support/test_apps/dma/sdkconfig.defaults.esp32c5 @@ -1,2 +1,2 @@ CONFIG_SPIRAM=y -CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM_SPEED_80M=y diff --git a/components/esp_psram/test_apps/.build-test-rules.yml b/components/esp_psram/test_apps/.build-test-rules.yml index 14b2fd4070..9cd9816206 100644 --- a/components/esp_psram/test_apps/.build-test-rules.yml +++ b/components/esp_psram/test_apps/.build-test-rules.yml @@ -1,8 +1,6 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps components/esp_psram/test_apps/psram: - enable: - - if: CONFIG_NAME == "psram_no_boot_init" and SOC_SPIRAM_SUPPORTED == 1 disable: - if: SOC_SPIRAM_SUPPORTED != 1 - if: CONFIG_NAME == "xip_psram_no_boot_init" and SOC_SPIRAM_XIP_SUPPORTED != 1 diff --git a/components/esp_psram/test_apps/psram/pytest_psram.py b/components/esp_psram/test_apps/psram/pytest_psram.py index 38b56d77fd..2cf712373d 100644 --- a/components/esp_psram/test_apps/psram/pytest_psram.py +++ b/components/esp_psram/test_apps/psram/pytest_psram.py @@ -3,6 +3,7 @@ import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @@ -135,6 +136,6 @@ def test_xip_psram_no_boot_init(dut: Dut) -> None: ], indirect=True, ) -@idf_parametrize('target', ['supported_targets'], indirect=['target']) +@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_SUPPORTED == 1'), indirect=['target']) def test_psram_no_boot_init(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 5f2a9ad79b..7f4b2d06fd 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -120,7 +120,7 @@ SECONDARY: 230: usb_serial_jtag_conn_status_init in components/esp_driver_usb_se # psram adjust timing point need a separate task which should be created at startup. # Valid only `CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR` is enabled. -SECONDARY: 240: psram_adjust_timing_point_via_temperature in components/esp_hw_support/mspi_timing_tuning/mspi_timing_by_mspi_delay.c on BIT(0) +SECONDARY: 240: psram_adjust_timing_point_via_temperature in components/esp_hw_support/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c on BIT(0) # Has to be the last step! # Now that the application is about to start, disable boot watchdog diff --git a/components/hal/esp32c5/include/hal/mspi_ll.h b/components/hal/esp32c5/include/hal/mspi_ll.h index bf02992cf5..a5289dbb33 100644 --- a/components/hal/esp32c5/include/hal/mspi_ll.h +++ b/components/hal/esp32c5/include/hal/mspi_ll.h @@ -23,6 +23,8 @@ #include "soc/soc.h" #include "soc/clk_tree_defs.h" #include "soc/pcr_struct.h" +#include "soc/spi_mem_struct.h" +#include "soc/spi_mem_reg.h" #include "hal/misc.h" #include "hal/assert.h" @@ -30,9 +32,86 @@ extern "C" { #endif +#define MSPI_TIMING_LL_MSPI_ID_0 0 +#define MSPI_TIMING_LL_MSPI_ID_1 1 +#define MSPI_LL_CORE_CLOCK_80_MHZ 80 +#define MSPI_LL_CORE_CLOCK_120_MHZ 120 +#define MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT MSPI_LL_CORE_CLOCK_80_MHZ -/************************** MSPI pll clock configurations **************************/ +/*--------------------------------------------------------------- + MSPI +---------------------------------------------------------------*/ +/** + * @brief Set MSPI_FAST_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL) + * + * @param mspi_id SPI0 / SPI1 + * @param core_clk_mhz core clock mhz + */ +static inline __attribute__((always_inline)) void mspi_timing_ll_set_core_clock(uint32_t mspi_id, uint32_t core_clk_mhz) +{ + HAL_ASSERT(mspi_id == 0); + uint32_t divider = 0; + switch (core_clk_mhz) { + case 80: + divider = 6; + break; + case 120: + divider = 4; + break; + default: + HAL_ASSERT(false); + } + + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.mspi_clk_conf, mspi_fast_div_num, divider - 1); +} + +/** + * @brief Enable the mspi core clock + * + * @param mspi_id SPI0 / SPI1 + * @param enable enable the core clock + */ +static inline __attribute__((always_inline)) void mspi_timing_ll_enable_core_clock(uint32_t mspi_id, bool enable) +{ + PCR.mspi_conf.mspi_clk_en = enable; +} + +/** + * Reset the MSPI clock + */ +static inline __attribute__((always_inline)) void _mspi_timing_ll_reset_mspi(void) +{ + PCR.mspi_clk_conf.mspi_axi_rst_en = 1; + PCR.mspi_clk_conf.mspi_axi_rst_en = 0; + // Wait for mspi to be ready + while (!PCR.mspi_conf.mspi_ready) { + ; + }; +} + +/** + * Calculate spi_flash clock frequency division parameters for register. + * + * @param clkdiv frequency division factor + * + * @return Register setting for the given clock division factor. + */ +static inline uint32_t mspi_timing_ll_calculate_clock_reg(uint8_t clkdiv) +{ + uint32_t div_parameter; + // See comments of `clock` in `spi_mem_struct.h` + if (clkdiv == 1) { + div_parameter = (1 << 31); + } else { + div_parameter = ((clkdiv - 1) | (((clkdiv - 1) / 2 & 0xff) << 8 ) | (((clkdiv - 1) & 0xff) << 16)); + } + return div_parameter; +} + +/*--------------------------------------------------------------- + FLASH +---------------------------------------------------------------*/ /* * @brief Select FLASH clock source * @@ -59,35 +138,281 @@ static inline void _mspi_timing_ll_set_flash_clk_src(uint32_t mspi_id, soc_perip } /** - * @brief Set MSPI_FAST_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL) + * @brief Set Flash clock * - * @param divider Divider. + * @param mspi_id mspi_id + * @param clock_conf Configuration value for flash clock */ -static inline __attribute__((always_inline)) void mspi_ll_fast_set_hs_divider(uint32_t divider) +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_flash_clock(uint32_t mspi_id, uint32_t clock_conf) { - HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.mspi_clk_conf, mspi_fast_div_num, divider - 1); + if (mspi_id == MSPI_TIMING_LL_MSPI_ID_0) { + SPIMEM0.clock.val = clock_conf; + } else if (mspi_id == MSPI_TIMING_LL_MSPI_ID_1) { + SPIMEM1.clock.val = clock_conf; + } } /** - * @brief Enable the mspi bus clock + * Enable Flash timing adjust clock * - * @param enable enable the bus clock + * @param mspi_id SPI0 / SPI1 */ -static inline __attribute__((always_inline)) void mspi_ll_enable_bus_clock(bool enable) +__attribute__((always_inline)) +static inline void mspi_timinng_ll_enable_flash_timing_adjust_clk(uint8_t mspi_id) { - PCR.mspi_conf.mspi_clk_en = enable; + SPIMEM0.mem_timing_cali.mem_timing_clk_ena = true; } /** - * Reset the MSPI clock + * Set MSPI Flash din mode + * + * @param mspi_id SPI0 / SPI1 + * @param din_mode Din mode value */ -static inline __attribute__((always_inline)) void _mspi_timing_ll_reset_mspi(void) +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_flash_din_mode(uint8_t mspi_id, uint8_t din_mode) { - PCR.mspi_clk_conf.mspi_axi_rst_en = 1; - PCR.mspi_clk_conf.mspi_axi_rst_en = 0; - // Wait for mspi to be ready - while (!PCR.mspi_conf.mspi_ready) { - }; + uint32_t reg_val = (REG_READ(SPI_MEM_DIN_MODE_REG(mspi_id)) & (~(SPI_MEM_DIN0_MODE_M | SPI_MEM_DIN1_MODE_M | SPI_MEM_DIN2_MODE_M | SPI_MEM_DIN3_MODE_M | SPI_MEM_DIN4_MODE_M | SPI_MEM_DIN5_MODE_M | SPI_MEM_DIN6_MODE_M | SPI_MEM_DIN7_MODE_M | SPI_MEM_DINS_MODE_M))) + | (din_mode << SPI_MEM_DIN0_MODE_S) | (din_mode << SPI_MEM_DIN1_MODE_S) | (din_mode << SPI_MEM_DIN2_MODE_S) | (din_mode << SPI_MEM_DIN3_MODE_S) + | (din_mode << SPI_MEM_DIN4_MODE_S) | (din_mode << SPI_MEM_DIN5_MODE_S) | (din_mode << SPI_MEM_DIN6_MODE_S) | (din_mode << SPI_MEM_DIN7_MODE_S) | (din_mode << SPI_MEM_DINS_MODE_S); + REG_WRITE(SPI_MEM_DIN_MODE_REG(mspi_id), reg_val); + REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(MSPI_TIMING_LL_MSPI_ID_0), SPI_MEM_TIMING_CALI_UPDATE); +} + +/** + * Set MSPI Flash din num + * + * @param mspi_id SPI0 / SPI1 + * @param din_num Din num value + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_flash_din_num(uint8_t mspi_id, uint8_t din_num) +{ + uint32_t reg_val = (REG_READ(SPI_MEM_DIN_NUM_REG(mspi_id)) & (~(SPI_MEM_DIN0_NUM_M | SPI_MEM_DIN1_NUM_M | SPI_MEM_DIN2_NUM_M | SPI_MEM_DIN3_NUM_M | SPI_MEM_DIN4_NUM_M | SPI_MEM_DIN5_NUM_M | SPI_MEM_DIN6_NUM_M | SPI_MEM_DIN7_NUM_M | SPI_MEM_DINS_NUM_M))) + | (din_num << SPI_MEM_DIN0_NUM_S) | (din_num << SPI_MEM_DIN1_NUM_S) | (din_num << SPI_MEM_DIN2_NUM_S) | (din_num << SPI_MEM_DIN3_NUM_S) + | (din_num << SPI_MEM_DIN4_NUM_S) | (din_num << SPI_MEM_DIN5_NUM_S) | (din_num << SPI_MEM_DIN6_NUM_S) | (din_num << SPI_MEM_DIN7_NUM_S) | (din_num << SPI_MEM_DINS_NUM_S); + REG_WRITE(SPI_MEM_DIN_NUM_REG(mspi_id), reg_val); + REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(MSPI_TIMING_LL_MSPI_ID_0), SPI_MEM_TIMING_CALI_UPDATE); +} + +/** + * Set MSPI Flash extra dummy + * + * @param mspi_id SPI0 / SPI1 + * @param extra_dummy Extra dummy + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_flash_extra_dummy(uint8_t mspi_id, uint8_t extra_dummy) +{ + if (extra_dummy > 0) { + SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(mspi_id), SPI_MEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(mspi_id), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); + } else { + CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(mspi_id), SPI_MEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(mspi_id), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0, SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); + } + REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(MSPI_TIMING_LL_MSPI_ID_0), SPI_MEM_TIMING_CALI_UPDATE); +} + +/** + * Get MSPI flash dummy info + * + * @param mspi_id SPI0 / SPI1 + * @param usr_dummy User dummy + * @param extra_dummy Extra dummy + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_get_flash_dummy(uint8_t mspi_id, int *usr_dummy, int *extra_dummy) +{ + *usr_dummy = REG_GET_FIELD(SPI_MEM_USER1_REG(mspi_id), SPI_MEM_USR_DUMMY_CYCLELEN); + *extra_dummy = REG_GET_FIELD(SPI_MEM_TIMING_CALI_REG(mspi_id), SPI_MEM_EXTRA_DUMMY_CYCLELEN); +} + +/** + * Enable/Disable Flash variable dummy + * + * @param mspi_id SPI0 / SPI1 + * @param enable Enable / Disable + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_enable_flash_variable_dummy(uint8_t mspi_id, bool enable) +{ + REG_SET_FIELD(SPI_MEM_DDR_REG(mspi_id), SPI_FMEM_VAR_DUMMY, enable); +} + +/** + * Get if cs setup is enabled or not + * + * @param mspi_id SPI0 / SPI1 + * + * @return + * true: enabled; false: disabled + */ +__attribute__((always_inline)) +static inline bool mspi_timing_ll_is_cs_setup_enabled(uint8_t mspi_id) +{ + return REG_GET_BIT(SPI_MEM_USER_REG(mspi_id), SPI_MEM_CS_SETUP); +} + +/** + * Get cs setup val + * + * @param mspi_id SPI0 / SPI1 + * + * @return + * cs setup reg val + */ +static inline uint32_t mspi_timing_ll_get_cs_setup_val(uint8_t mspi_id) +{ + return REG_GET_FIELD(SPI_MEM_CTRL2_REG(mspi_id), SPI_MEM_CS_SETUP_TIME); +} + +/** + * Get if cs hold is enabled or not + * + * @param mspi_id SPI0 / SPI1 + * + * @return + * true: enabled; false: disabled + */ +__attribute__((always_inline)) +static inline bool mspi_timing_ll_is_cs_hold_enabled(uint8_t mspi_id) +{ + return REG_GET_FIELD(SPI_MEM_USER_REG(mspi_id), SPI_MEM_CS_HOLD); +} + +/** + * Get cs hold val + * + * @param mspi_id SPI0 / SPI1 + * + * @return + * cs hold reg val + */ +static inline uint32_t mspi_timing_ll_get_cs_hold_val(uint8_t mspi_id) +{ + return REG_GET_FIELD(SPI_MEM_CTRL2_REG(mspi_id), SPI_MEM_CS_HOLD_TIME); +} + +/** + * Get clock reg val + * + * @param mspi_id SPI0 / SPI1 + * + * @return + * clock reg val + */ +__attribute__((always_inline)) +static inline uint32_t mspi_timing_ll_get_clock_reg(uint8_t mspi_id) +{ + return READ_PERI_REG(SPI_MEM_CLOCK_REG(mspi_id)); +} + +/*--------------------------------------------------------------- + PSRAM +---------------------------------------------------------------*/ +/** + * @brief Set PSRAM clock + * + * @param mspi_id mspi_id + * @param clock_conf Configuration value for psram clock + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_clock(uint32_t mspi_id, uint32_t clock_conf) +{ + SPIMEM0.mem_sram_clk.val = clock_conf; +} + +/** + * @brief Set SPI1 bus clock to initialise PSRAM + * + * @param mspi_id mspi_id + * @param clock_conf Configuration value for psram clock + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_spi1_bus_clock(uint32_t mspi_id, uint32_t clock_conf) +{ + HAL_ASSERT(mspi_id == MSPI_TIMING_LL_MSPI_ID_1); + SPIMEM1.clock.val = clock_conf; +} + +/** + * Enable PSRAM timing adjust clock + * + * @param mspi_id SPI0 / SPI1 + */ +__attribute__((always_inline)) +static inline void mspi_timinng_ll_enable_psram_timing_adjust_clk(uint8_t mspi_id) +{ + SPIMEM0.smem_timing_cali.smem_timing_clk_ena = true; +} + +/** + * Set MSPI PSRAM din mode + * + * @param mspi_id SPI0 / SPI1 + * @param din_mode Din mode value + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_din_mode(uint8_t mspi_id, uint8_t din_mode) +{ + uint32_t reg_val = (REG_READ(SPI_SMEM_DIN_MODE_REG(mspi_id)) & (~(SPI_SMEM_DIN0_MODE_M | SPI_SMEM_DIN1_MODE_M | SPI_SMEM_DIN2_MODE_M | SPI_SMEM_DIN3_MODE_M | SPI_SMEM_DIN4_MODE_M | SPI_SMEM_DIN5_MODE_M | SPI_SMEM_DIN6_MODE_M | SPI_SMEM_DIN7_MODE_M | SPI_SMEM_DINS_MODE_M))) + | (din_mode << SPI_SMEM_DIN0_MODE_S) | (din_mode << SPI_SMEM_DIN1_MODE_S) | (din_mode << SPI_SMEM_DIN2_MODE_S) | (din_mode << SPI_SMEM_DIN3_MODE_S) + | (din_mode << SPI_SMEM_DIN4_MODE_S) | (din_mode << SPI_SMEM_DIN5_MODE_S) | (din_mode << SPI_SMEM_DIN6_MODE_S) | (din_mode << SPI_SMEM_DIN7_MODE_S) | (din_mode << SPI_SMEM_DINS_MODE_S); + REG_WRITE(SPI_SMEM_DIN_MODE_REG(mspi_id), reg_val); + REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(MSPI_TIMING_LL_MSPI_ID_0), SPI_MEM_TIMING_CALI_UPDATE); +} + +/** + * Set MSPI PSRAM din num + * + * @param mspi_id SPI0 / SPI1 + * @param din_num Din num value + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_din_num(uint8_t mspi_id, uint8_t din_num) +{ + uint32_t reg_val = (REG_READ(SPI_SMEM_DIN_NUM_REG(mspi_id)) & (~(SPI_SMEM_DIN0_NUM_M | SPI_SMEM_DIN1_NUM_M | SPI_SMEM_DIN2_NUM_M | SPI_SMEM_DIN3_NUM_M | SPI_SMEM_DIN4_NUM_M | SPI_SMEM_DIN5_NUM_M | SPI_SMEM_DIN6_NUM_M | SPI_SMEM_DIN7_NUM_M | SPI_SMEM_DINS_NUM_M))) + | (din_num << SPI_SMEM_DIN0_NUM_S) | (din_num << SPI_SMEM_DIN1_NUM_S) | (din_num << SPI_SMEM_DIN2_NUM_S) | (din_num << SPI_SMEM_DIN3_NUM_S) + | (din_num << SPI_SMEM_DIN4_NUM_S) | (din_num << SPI_SMEM_DIN5_NUM_S) | (din_num << SPI_SMEM_DIN6_NUM_S) | (din_num << SPI_SMEM_DIN7_NUM_S) | (din_num << SPI_SMEM_DINS_NUM_S); + REG_WRITE(SPI_SMEM_DIN_NUM_REG(mspi_id), reg_val); + REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(MSPI_TIMING_LL_MSPI_ID_0), SPI_MEM_TIMING_CALI_UPDATE); +} + +/** + * Set MSPI Octal PSRAM extra dummy + * + * @param mspi_id SPI0 / SPI1 + * @param extra_dummy Extra dummy + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_extra_dummy(uint8_t mspi_id, uint8_t extra_dummy) +{ + if (extra_dummy > 0) { + SET_PERI_REG_MASK(SPI_SMEM_TIMING_CALI_REG(mspi_id), SPI_SMEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_SMEM_TIMING_CALI_REG(mspi_id), SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, + SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); + } else { + CLEAR_PERI_REG_MASK(SPI_SMEM_TIMING_CALI_REG(mspi_id), SPI_SMEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_SMEM_TIMING_CALI_REG(mspi_id), SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0, + SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); + } + REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(MSPI_TIMING_LL_MSPI_ID_0), SPI_MEM_TIMING_CALI_UPDATE); +} + +/** + * Get MSPI PSRAM dummy info + * + * @param mspi_id SPI0 / SPI1 + * @param usr_rdummy User read dummy + * @param extra_dummy Extra dummy + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_get_psram_dummy(uint8_t mspi_id, int *usr_rdummy, int *extra_dummy) +{ + *usr_rdummy = REG_GET_FIELD(SPI_MEM_CACHE_SCTRL_REG(mspi_id), SPI_MEM_SRAM_RDUMMY_CYCLELEN); + *extra_dummy = REG_GET_FIELD(SPI_SMEM_TIMING_CALI_REG(mspi_id), SPI_SMEM_EXTRA_DUMMY_CYCLELEN); } #ifdef __cplusplus diff --git a/components/hal/esp32c5/include/hal/spimem_flash_ll.h b/components/hal/esp32c5/include/hal/spimem_flash_ll.h index af832f9b26..f6f1b4e1fa 100644 --- a/components/hal/esp32c5/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c5/include/hal/spimem_flash_ll.h @@ -649,6 +649,11 @@ static inline void spimem_flash_ll_set_extra_dummy(spi_mem_dev_t *dev, uint32_t //for compatibility } +static inline void spimem_flash_ll_set_fdummy_rin(spi_mem_dev_t *dev, uint32_t fdummy_rin) +{ + dev->ctrl.fdummy_rin = fdummy_rin; +} + /** * Get the spi flash source clock frequency. Used for calculating * the divider parameters. diff --git a/components/hal/esp32c61/include/hal/mspi_ll.h b/components/hal/esp32c61/include/hal/mspi_ll.h index dfe51d8abd..855d5cf3fa 100644 --- a/components/hal/esp32c61/include/hal/mspi_ll.h +++ b/components/hal/esp32c61/include/hal/mspi_ll.h @@ -30,6 +30,11 @@ extern "C" { #endif +#define MSPI_TIMING_LL_MSPI_ID_0 0 +#define MSPI_TIMING_LL_MSPI_ID_1 1 +#define MSPI_LL_CORE_CLOCK_80_MHZ 80 +#define MSPI_LL_CORE_CLOCK_120_MHZ 120 +#define MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT MSPI_LL_CORE_CLOCK_80_MHZ /************************** MSPI pll clock configurations **************************/ @@ -61,19 +66,34 @@ static inline void _mspi_timing_ll_set_flash_clk_src(uint32_t mspi_id, soc_perip /** * @brief Set MSPI_FAST_CLK's high-speed divider (valid when SOC_ROOT clock source is PLL) * - * @param divider Divider. + * @param mspi_id SPI0 / SPI1 + * @param core_clk_mhz core clock mhz */ -static inline __attribute__((always_inline)) void mspi_ll_fast_set_hs_divider(uint32_t divider) +static inline __attribute__((always_inline)) void mspi_timing_ll_set_core_clock(uint8_t mspi_id, uint32_t core_clk_mhz) { + HAL_ASSERT(mspi_id == 0); + uint32_t divider = 0; + switch (core_clk_mhz) { + case 80: + divider = 6; + break; + case 120: + divider = 4; + break; + default: + HAL_ASSERT(false); + } + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.mspi_clk_conf, mspi_fast_div_num, divider - 1); } /** - * @brief Enable the mspi bus clock + * @brief Enable the mspi core clock * - * @param enable enable the bus clock + * @param mspi_id SPI0 / SPI1 + * @param enable enable the core clock */ -static inline __attribute__((always_inline)) void mspi_ll_enable_bus_clock(bool enable) +static inline __attribute__((always_inline)) void mspi_timing_ll_enable_core_clock(uint8_t mspi_id, bool enable) { PCR.mspi_conf.mspi_clk_en = enable; } diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index abd3d54ea9..ffacb5385f 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1195,6 +1195,14 @@ config SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP bool default y +config SOC_SPI_MEM_SUPPORT_TIMING_TUNING + bool + default y + +config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY + bool + default y + config SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 74e44e1c22..1b59fb4924 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -472,6 +472,8 @@ #define SOC_SPI_MEM_SUPPORT_WRAP (1) #define SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL (1) #define SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP (1) +#define SOC_SPI_MEM_SUPPORT_TIMING_TUNING (1) +#define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1) #define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1