From 65db12cfa66a274e8953331ec67aa93775bed85d Mon Sep 17 00:00:00 2001 From: armando Date: Wed, 23 Jul 2025 15:30:32 +0800 Subject: [PATCH] feat(flash): flash 80M timing tuning on c5 --- .../port/esp32c5/mspi_timing_config.c | 2 + .../port/esp32c5/mspi_timing_tuning_configs.h | 51 +++++++++++--- .../mspi_timing_by_mspi_delay.c | 69 +++++++++++++++++-- components/hal/esp32c5/include/hal/mspi_ll.h | 17 ++++- .../esp32c5/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32c5/include/soc/soc_caps.h | 1 + 6 files changed, 129 insertions(+), 15 deletions(-) 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 index 6dc5e63d44..0d1474060b 100644 --- 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 @@ -27,11 +27,13 @@ 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) { + ESP_EARLY_LOGV(TAG, "flash core clock: %d", 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) { + ESP_EARLY_LOGV(TAG, "psram core clock: %d", core_clock_mhz); mspi_timing_ll_set_core_clock(mspi_id, core_clock_mhz); } 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 index 488d69522e..a4a623e598 100644 --- 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 @@ -6,11 +6,14 @@ #pragma once #include "sdkconfig.h" +#include "esp_assert.h" +#include "esp_flash_partitions.h" -#define MSPI_TIMING_MSPI1_IS_INVOLVED CONFIG_ESPTOOLPY_FLASHFREQ_120M //This means esp flash driver needs to be notified +#define MSPI_TIMING_MSPI1_IS_INVOLVED (CONFIG_ESPTOOLPY_FLASHFREQ_80M || 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 +#define MSPI_TIMING_FLASH_TEST_DATA_ADDR ESP_BOOTLOADER_OFFSET //--------------------------------------FLASH Sampling Mode --------------------------------------// #define MSPI_TIMING_FLASH_STR_MODE 1 @@ -21,10 +24,12 @@ #define MSPI_TIMING_FLASH_MODULE_CLOCK 40 #elif CONFIG_ESPTOOLPY_FLASHFREQ_80M #define MSPI_TIMING_FLASH_MODULE_CLOCK 80 +#elif CONFIG_ESPTOOLPY_FLASHFREQ_120M +#define MSPI_TIMING_FLASH_MODULE_CLOCK 120 #endif //------------------------------------FLASH Needs Tuning or not-------------------------------------// #if MSPI_TIMING_FLASH_STR_MODE -#define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 80) +#define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 40) #endif //--------------------------------------PSRAM Sampling Mode --------------------------------------// @@ -44,12 +49,15 @@ #define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 40) #endif -///////////////////////////////////// FLASH CORE CLOCK ///////////////////////////////////// +///////////////////////////////////// FLASH/PSRAM CORE CLOCK ///////////////////////////////////// +#if ((CONFIG_ESPTOOLPY_FLASHFREQ_80M && !CONFIG_SPIRAM) || (CONFIG_ESPTOOLPY_FLASHFREQ_80M && CONFIG_SPIRAM_SPEED_80M)) #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 +#define MSPI_TIMING_FLASH_CONSECUTIVE_LEN_MAX 6 +#else +#define MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 +#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 240 +#define MSPI_TIMING_FLASH_CONSECUTIVE_LEN_MAX 4 #endif //------------------------------------------Determine the Core Clock-----------------------------------------------// @@ -93,7 +101,32 @@ ESP_STATIC_ASSERT(MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ % MSPI_TIMING_FLASH_MO /** * Timing Tuning Parameters */ +//FLASH: core clock 240M, module clock 120M, STR mode +#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {2, 1, 3}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {2, 1, 4}} +#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 12 +#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 4 + +//FLASH: core clock 240M, module clock 80M, STR mode +#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_240M_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, 2}, {0, 0, 1}, {3, 1, 3}, {2, 3, 3}, {2, 2, 3}, {2, 1, 3}} +#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_80M_STR_MODE 14 +#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_80M_STR_MODE 4 + +//FLASH: core clock 80M, module clock 80M, STR mode +#define MSPI_TIMING_FLASH_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, 2}, {0, 0, 1}, {3, 1, 3}, {2, 3, 3}, {2, 2, 3}, {2, 1, 3}} +#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_80M_MODULE_CLK_80M_STR_MODE 14 +#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_80M_MODULE_CLK_80M_STR_MODE 4 + +//PSRAM: core clock 240M, module clock 120M, STR mode +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {2, 1, 3}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {2, 1, 4}} +#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 12 +#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 4 + +//PSRAM: core clock 240M, module clock 80M, STR mode +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_240M_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, 2}, {0, 0, 1}, {3, 1, 3}, {2, 3, 3}, {2, 2, 3}, {2, 1, 3}} +#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_80M_STR_MODE 14 +#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_80M_STR_MODE 4 + //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, 2}, {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 +#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, 2}, {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 4 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 index 6b0c4f2b63..907a596fa6 100644 --- 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 @@ -25,6 +25,7 @@ #include "esp_private/mspi_timing_config.h" #include "esp_private/mspi_timing_by_mspi_delay.h" #include "mspi_timing_tuning_configs.h" +#include "bootloader_flash.h" #define QPI_PSRAM_FAST_READ 0XEB #define QPI_PSRAM_WRITE 0X38 @@ -33,6 +34,33 @@ const static char *TAG = "MSPI Timing"; //-------------------------------------FLASH timing tuning register config-------------------------------------// +void mspi_timing_get_flash_tuning_configs(mspi_timing_config_t *config) +{ +#if MSPI_TIMING_FLASH_DTR_MODE +#define FLASH_MODE DTR_MODE +#else //MSPI_TIMING_FLASH_STR_MODE +#define FLASH_MODE STR_MODE +#endif + +#if CONFIG_ESPTOOLPY_FLASHFREQ_80M + *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 80, FLASH_MODE); +#elif CONFIG_ESPTOOLPY_FLASHFREQ_120M + *config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(MSPI_TIMING_CORE_CLOCK_MHZ, 120, FLASH_MODE); +#else + assert(false && "should never reach here"); +#endif + +#undef FLASH_MODE +} + +void mspi_timing_flash_init(uint32_t flash_freq_mhz) +{ + mspi_timing_config_set_flash_clock(flash_freq_mhz, MSPI_TIMING_SPEED_MODE_NORMAL_PERF, true); + + //Power on HCLK + mspi_timinng_ll_enable_flash_timing_adjust_clk(MSPI_TIMING_LL_MSPI_ID_0); +} + 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); @@ -44,6 +72,33 @@ 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); } +void mspi_timing_config_flash_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_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless + * SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning + * 2. We use SPI1 to get the best Flash timing tuning (mode and num) config + */ + s_set_flash_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); +} + +//-------------------------------------------FLASH Read/Write------------------------------------------// +void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len) +{ + if (bootloader_flash_is_octal_mode_enabled()) { + // note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state. + // but after we change the timing settings, we might not read correct idle status via RDSR. + // so, here we should use a read API that won't check idle status. + mspi_timing_ll_clear_fifo(MSPI_TIMING_LL_MSPI_ID_1); + // to add opi read api here when octal flash is used + assert(false); + } else { + esp_rom_spiflash_read(addr, (uint32_t *)buf, len); + } +} + //-------------------------------------PSRAM timing tuning register config-------------------------------------// void mspi_timing_psram_init(uint32_t psram_freq_mhz) { @@ -218,7 +273,14 @@ static uint32_t s_select_best_tuning_config_str(const mspi_timing_config_t *conf //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 { + } +#if MSPI_TIMING_FLASH_CONSECUTIVE_LEN_MAX + else if (consecutive_length > MSPI_TIMING_FLASH_CONSECUTIVE_LEN_MAX) { + best_point = configs->default_config_id; + ESP_EARLY_LOGW(TAG, "tuning fail, best point is fallen back to index %"PRIu32"", best_point); + } +#endif + else { best_point = end - consecutive_length / 2; ESP_EARLY_LOGI(TAG, "tuning success, best point is index %"PRIu32"", best_point); } @@ -360,9 +422,6 @@ uint32_t mspi_timing_config_get_flash_clock_reg(void) 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 + //use hw extra dummy return 0; -#endif } diff --git a/components/hal/esp32c5/include/hal/mspi_ll.h b/components/hal/esp32c5/include/hal/mspi_ll.h index a5289dbb33..f99937641f 100644 --- a/components/hal/esp32c5/include/hal/mspi_ll.h +++ b/components/hal/esp32c5/include/hal/mspi_ll.h @@ -38,7 +38,6 @@ extern "C" { #define MSPI_LL_CORE_CLOCK_120_MHZ 120 #define MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT MSPI_LL_CORE_CLOCK_80_MHZ - /*--------------------------------------------------------------- MSPI ---------------------------------------------------------------*/ @@ -59,6 +58,9 @@ static inline __attribute__((always_inline)) void mspi_timing_ll_set_core_clock( case 120: divider = 4; break; + case 240: + divider = 2; + break; default: HAL_ASSERT(false); } @@ -109,6 +111,19 @@ static inline uint32_t mspi_timing_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Clear MSPI hw fifo + * + * @param mspi_id SPI0 / SPI1 + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_clear_fifo(uint8_t mspi_id) +{ + for (int i = 0; i < 16; i++) { + REG_WRITE(SPI_MEM_W0_REG(mspi_id) + i * 4, 0); + } +} + /*--------------------------------------------------------------- FLASH ---------------------------------------------------------------*/ diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 958cac01ec..7c744f80d8 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1251,6 +1251,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY bool default y +config SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED + 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 ab65b638d4..d56e50f321 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -491,6 +491,7 @@ #define SOC_SPI_MEM_SUPPORT_TSUS_TRES_SEPERATE_CTR (1) #define SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY (1) +#define SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1