Merge branch 'feat/c5_flash_timing_tuning' into 'master'

flash: flash timing tuning support on c5

Closes IDF-8649

See merge request espressif/esp-idf!40763
This commit is contained in:
Armando (Dou Yiwen)
2025-07-29 06:09:22 +00:00
6 changed files with 129 additions and 15 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
---------------------------------------------------------------*/

View File

@@ -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

View File

@@ -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