Merge branch 'feat/120m_flash_p4' into 'master'

flash: 120MHz timing tuning support on ESP32P4 (no merge now)

Closes IDF-11678

See merge request espressif/esp-idf!34995
This commit is contained in:
Armando (Dou Yiwen)
2024-11-29 11:40:29 +08:00
49 changed files with 1029 additions and 81 deletions

View File

@@ -225,6 +225,12 @@ static void bootloader_spi_flash_resume(void)
esp_err_t bootloader_init_spi_flash(void) esp_err_t bootloader_init_spi_flash(void)
{ {
bootloader_init_flash_configure(); bootloader_init_flash_configure();
#if CONFIG_BOOTLOADER_FLASH_DC_AWARE
// Reset flash, clear volatile bits DC[0:1]. Make it work under default mode to boot.
bootloader_spi_flash_reset();
#endif
bootloader_spi_flash_resume(); bootloader_spi_flash_resume();
bootloader_flash_unlock(); bootloader_flash_unlock();

View File

@@ -132,6 +132,9 @@ if(NOT non_os_build)
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS) if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS)
list(APPEND srcs "mspi_timing_by_dqs.c") list(APPEND srcs "mspi_timing_by_dqs.c")
endif() endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY)
list(APPEND srcs "mspi_timing_by_flash_delay.c")
endif()
endif() endif()
if(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED AND CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB) if(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED AND CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB)

View File

@@ -42,6 +42,9 @@ entries:
mspi_timing_config (noflash) mspi_timing_config (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y: if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y:
mspi_timing_by_dqs (noflash) mspi_timing_by_dqs (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY = y:
mspi_timing_by_flash_delay (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY = y:
mspi_timing_config (noflash) mspi_timing_config (noflash)
if SOC_ADC_SHARED_POWER = y: if SOC_ADC_SHARED_POWER = y:
if ADC_ONESHOT_CTRL_FUNC_IN_IRAM = y: if ADC_ONESHOT_CTRL_FUNC_IN_IRAM = y:

View File

@@ -223,15 +223,3 @@ void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi)
} }
} }
} }
void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi)
{
//no need for now, may need set drvs
//keep for compatibility
}
void mspi_timing_flash_config_clear_tuning_regs(bool control_both_mspi)
{
//no need for now, may need clear drvs
//keep for compatibility
}

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -14,6 +14,7 @@
#include <stdint.h> #include <stdint.h>
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_DQS #if SOC_MEMSPI_TIMING_TUNING_BY_DQS
#include "mspi_timing_types.h"
#include "mspi_timing_tuning_configs.h" #include "mspi_timing_tuning_configs.h"
#include "hal/mspi_timing_tuning_ll.h" #include "hal/mspi_timing_tuning_ll.h"
#endif #endif
@@ -28,26 +29,6 @@ extern "C" {
#define IS_SDR (!IS_DDR) #define IS_SDR (!IS_DDR)
/**
* Delayline
*/
typedef struct {
uint8_t data_delayline;
uint8_t dqs_delayline;
} __attribute__((packed)) delayline_config_t;
/**
* MSPI timing tuning configurations
*/
typedef struct {
mspi_ll_dqs_phase_t phase[MSPI_LL_DQS_PHASE_MAX];
delayline_config_t delayline_table[MSPI_TIMING_CONFIG_NUM_MAX];
union {
uint32_t available_config_num;
uint32_t available_phase_num;
};
} mspi_timing_config_t;
/*------------------------------------------------------------------------------------------------- /*-------------------------------------------------------------------------------------------------
* Timing Required APIs * Timing Required APIs
*-------------------------------------------------------------------------------------------------*/ *-------------------------------------------------------------------------------------------------*/

View File

@@ -0,0 +1,231 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief
*
* This file contains configuration APIs doing MSPI timing tuning by Flash delay
* This file will only be built when `SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY == 1`
*/
#include <stdint.h>
#include <string.h>
#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_types.h"
#include "esp_log.h"
#include "mspi_timing_by_flash_delay.h"
#include "mspi_timing_tuning_configs.h"
#include "esp_private/mspi_timing_config.h"
#include "hal/mspi_timing_tuning_ll.h"
#include "rom/spi_flash.h"
const static char *TAG = "Flash Delay";
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);
ESP_EARLY_LOGD(TAG, "init rom dummy val: %d", g_rom_spiflash_dummy_len_plus[1]);
}
//-------------------------------------FLASH timing tuning register config-------------------------------------//
void mspi_timing_get_flash_tuning_configs(mspi_timing_config_t *config)
{
#if CONFIG_ESPTOOLPY_FLASHFREQ_120M
*config = MSPI_TIMING_FLASH_GET_TUNING_CONFIG(MSPI_TIMING_FLASH_CORE_CLOCK_MHZ, 120, STR_MODE);
#else
assert(false && "should never reach here");
#endif
}
static void s_set_flash_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
{
mspi_timing_ll_set_flash_din_mode(spi_num, din_mode);
mspi_timing_ll_set_flash_din_num(spi_num, din_num);
}
static void s_set_flash_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
{
mspi_timing_ll_set_flash_extra_dummy(spi_num, 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 CONFIG_ESPTOOLPY_FLASHMODE_QIO
g_rom_spiflash_dummy_len_plus[1] = 4;
#endif
esp_rom_spiflash_read(addr, (uint32_t *)buf, len);
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_LOGD(TAG, "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);
}
/*-------------------------------------------------------------------------------------------------
* 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;
if (consecutive_length < 3) {
//tuning fails, select default point, and generate a warning
best_point = configs->flash_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;
if (is_ddr) {
assert(false);
} else {
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;
}
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(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
}
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO
mspi_timing_ll_set_flash_user_dummy(MSPI_TIMING_LL_MSPI_ID_0, 7);
#endif
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_LOGD(TAG, "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);
}
/*-------------------------------------------------------------------------------------------------
* 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-P4, 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(MSPI_TIMING_LL_MSPI_ID_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)
{
//use hw extra dummy
return 0;
}
uint32_t mspi_timing_config_get_flash_fdummy_rin(void)
{
return mspi_timing_ll_get_invalid_dqs_mask(MSPI_TIMING_LL_MSPI_ID_1);
}

View File

@@ -0,0 +1,153 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief
*
* This file contains configuration APIs doing MSPI timing tuning by MSPI delay
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
#include "mspi_timing_types.h"
#include "mspi_timing_tuning_configs.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
#define IS_DDR 1
#define IS_SDR (!IS_DDR)
/*-------------------------------------------------------------------------------------------------
* Timing Required APIs
*-------------------------------------------------------------------------------------------------*/
/**
* @brief Get Flash tuning all configurations
*
* @param[out] config Pointer to Flash tuning configurations
*/
void mspi_timing_get_flash_tuning_configs(mspi_timing_config_t *config);
/**
* @brief Init MSPI for Flash timing tuning
*
* @param[in] flash_freq_mhz Flash frequency in MHz
*/
void mspi_timing_flash_init(uint32_t flash_freq_mhz);
/**
* @brief Tune Flash timing registers for SPI1 accessing Flash
*
* @param[in] configs Timing configs
* @param[in] id Config ID
*/
void mspi_timing_config_flash_set_tuning_regs(const void *configs, uint8_t id);
/**
* @brief Configure Flash to read data via SPI1
*
* @param[out] buf buffer
* @param[in] addr address
* @param[in] len length
*/
void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len);
/*-------------------------------------------------------------------------------------------------
* Best Timing Tuning Params Selection
*-------------------------------------------------------------------------------------------------*/
/**
* @brief Select Flash best tuning configuration
*
* @param[in] configs Timing tuning configuration table
* @param[in] consecutive_length Length of the consecutive successful sample results
* @param[in] end End of the consecutive successful sample results
* @param[in] reference_data Reference data
* @param[in] is_ddr DDR or SDR
*
* @return Best config ID
*/
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);
/**
* @brief Set best Flash tuning configs.
* After this, calling `mspi_timing_enter_high_speed_mode` will set these configs correctly
*
* @param[in] configs Timing tuning configs
* @param[in] best_id Best config ID
*/
void mspi_timing_flash_set_best_tuning_config(const void *configs, uint8_t best_id);
/*-------------------------------------------------------------------------------------------------
* Best Timing Tuning Params Clear / Set
*-------------------------------------------------------------------------------------------------*/
/**
* @brief Clear Flash timing tuning settings
*
* This is used when the system is going into low speed mode / MSPI doesn't need to be run in high speed
*
* @param[in] control_both_mspi Control SPI1 as well
*/
void mspi_timing_flash_config_clear_tuning_regs(bool control_both_mspi);
/**
* @brief Set Flash timing tuning settings
*
* This is used when the system is going to high speed mode / MSPI needs to be run in high speed
*
* @param[in] control_both_mspi Control SPI1 as well
*/
void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi);
/*-------------------------------------------------------------------------------------------------
* APIs for coordination with ESP Flash driver
*-------------------------------------------------------------------------------------------------*/
/**
* SPI1 register info get APIs. These APIs inform `spi_flash_timing_tuning.c` (driver layer) of the SPI1 flash settings.
* In this way, other components (e.g.: esp_flash driver) can get the info from it (`spi_flash_timing_tuning.c`).
*/
/**
* @brief Get CS timing
*
* @param[out] setup_time Setup time
* @param[out] hold_time Hold time
*/
void mspi_timing_config_get_cs_timing(uint8_t *setup_time, uint32_t *hold_time);
/**
* @brief Get Flash clock reg val
*
* @return Flash clock reg val
*/
uint32_t mspi_timing_config_get_flash_clock_reg(void);
/**
* @brief Get Flash extra dummy len
*
* @return Flash extra dummy
*/
uint8_t mspi_timing_config_get_flash_extra_dummy(void);
/**
* @brief Get Flash dummy rin_reg
*
* @return Flash dummy rin_reg
*/
uint32_t mspi_timing_config_get_flash_fdummy_rin(void);
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
#ifdef __cplusplus
}
#endif

View File

@@ -97,7 +97,7 @@ 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); mspi_timing_config_set_flash_clock(flash_freq_mhz, MSPI_TIMING_SPEED_MODE_NORMAL_PERF, true);
//Power on HCLK //Power on HCLK
mspi_timinng_ll_enable_flash_hclk(0); mspi_timinng_ll_enable_flash_timing_adjust_clk(0);
} }
static void s_set_flash_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num) static void s_set_flash_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)
@@ -227,7 +227,7 @@ 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); mspi_timing_config_set_flash_clock(psram_freq_mhz, MSPI_TIMING_SPEED_MODE_NORMAL_PERF, true);
//Power on HCLK //Power on HCLK
mspi_timinng_ll_enable_psram_hclk(0); mspi_timinng_ll_enable_psram_timing_adjust_clk(0);
} }
static void s_set_psram_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num) static void s_set_psram_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num)

View File

@@ -14,6 +14,7 @@
#include <stdint.h> #include <stdint.h>
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY #if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
#include "mspi_timing_types.h"
#include "mspi_timing_tuning_configs.h" #include "mspi_timing_tuning_configs.h"
#endif #endif
@@ -26,25 +27,6 @@ extern "C" {
#define IS_DDR 1 #define IS_DDR 1
#define IS_SDR (!IS_DDR) #define IS_SDR (!IS_DDR)
/**
* MSPI timing tuning registers.
* Upper layer rely on these 3 registers to tune the timing.
*/
typedef struct {
uint8_t spi_din_mode; // input signal delay mode
uint8_t spi_din_num; // input signal delay number
uint8_t extra_dummy_len; // extra dummy length
} mspi_timing_tuning_param_t;
/**
* MSPI timing tuning configurations
*/
typedef struct {
mspi_timing_tuning_param_t tuning_config_table[MSPI_TIMING_CONFIG_NUM_MAX]; // Available timing tuning configs
uint32_t available_config_num; // Available timing tuning config numbers
uint32_t default_config_id; // If tuning fails, we use this one as default
} mspi_timing_config_t;
#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING #if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
/*------------------------------------------------------------------------------------------------- /*-------------------------------------------------------------------------------------------------

View File

@@ -20,7 +20,8 @@
#include "esp_private/mspi_timing_config.h" #include "esp_private/mspi_timing_config.h"
#include "mspi_timing_by_mspi_delay.h" #include "mspi_timing_by_mspi_delay.h"
#include "mspi_timing_by_dqs.h" #include "mspi_timing_by_dqs.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY || SOC_MEMSPI_TIMING_TUNING_BY_DQS #include "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" #include "mspi_timing_tuning_configs.h"
#include "hal/mspi_timing_tuning_ll.h" #include "hal/mspi_timing_tuning_ll.h"
#endif #endif
@@ -343,7 +344,7 @@ void mspi_timing_flash_tuning(void)
*/ */
mspi_timing_enter_low_speed_mode(true); mspi_timing_enter_low_speed_mode(true);
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY #if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
mspi_tuning_cfg_drv_t drv = { mspi_tuning_cfg_drv_t drv = {
.flash_tuning_type = MSPI_TIMING_TUNING_MSPI_DIN_DUMMY, .flash_tuning_type = MSPI_TIMING_TUNING_MSPI_DIN_DUMMY,
.sweep_test_nums = 1, .sweep_test_nums = 1,
@@ -365,7 +366,7 @@ void mspi_timing_flash_tuning(void)
mspi_timing_config_t timing_configs = {0}; mspi_timing_config_t timing_configs = {0};
mspi_timing_get_flash_tuning_configs(&timing_configs); mspi_timing_get_flash_tuning_configs(&timing_configs);
#endif //SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY #endif //SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
s_do_tuning(reference_data, &timing_configs, true); s_do_tuning(reference_data, &timing_configs, true);
@@ -602,6 +603,10 @@ void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing
out_timing_config->extra_dummy = mspi_timing_config_get_flash_extra_dummy(); out_timing_config->extra_dummy = mspi_timing_config_get_flash_extra_dummy();
#if MSPI_TIMING_LL_FLASH_FDUMMY_RIN_SUPPORTED
out_timing_config->fdummy_rin = mspi_timing_config_get_flash_fdummy_rin();
#endif
// Get CS setup/hold value here. // Get CS setup/hold value here.
mspi_timing_config_get_cs_timing(&out_timing_config->cs_setup, &out_timing_config->cs_hold); mspi_timing_config_get_cs_timing(&out_timing_config->cs_setup, &out_timing_config->cs_hold);
} }

View File

@@ -0,0 +1,85 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief
*
* This file contains types for MSPI timing tuning
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_DQS || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY || SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
#include "hal/mspi_timing_tuning_ll.h"
#include "mspi_timing_tuning_configs.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_MEMSPI_TIMING_TUNING_BY_DQS || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
/**
* Delayline
*/
typedef struct {
uint8_t data_delayline;
uint8_t dqs_delayline;
} __attribute__((packed)) delayline_config_t;
/**
* MSPI timing tuning registers.
*/
typedef struct {
uint8_t spi_din_mode; // input signal delay mode
uint8_t spi_din_num; // input signal delay number
uint8_t extra_dummy_len; // extra dummy length
} mspi_timing_tuning_param_t;
/**
* MSPI timing tuning configurations
*/
typedef struct {
//for psram
mspi_ll_dqs_phase_t phase[MSPI_LL_DQS_PHASE_MAX];
delayline_config_t delayline_table[MSPI_TIMING_CONFIG_NUM_MAX];
//for flash
mspi_timing_tuning_param_t tuning_config_table[MSPI_TIMING_CONFIG_NUM_MAX];
uint32_t flash_default_config_id;
//common
union {
uint32_t available_config_num;
uint32_t available_phase_num;
};
} mspi_timing_config_t;
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_DQS || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
/**
* MSPI timing tuning registers.
* Upper layer rely on these 3 registers to tune the timing.
*/
typedef struct {
uint8_t spi_din_mode; // input signal delay mode
uint8_t spi_din_num; // input signal delay number
uint8_t extra_dummy_len; // extra dummy length
} mspi_timing_tuning_param_t;
/**
* MSPI timing tuning configurations
*/
typedef struct {
mspi_timing_tuning_param_t tuning_config_table[MSPI_TIMING_CONFIG_NUM_MAX]; // Available timing tuning configs
uint32_t available_config_num; // Available timing tuning config numbers
uint32_t default_config_id; // If tuning fails, we use this one as default
} mspi_timing_config_t;
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -15,6 +15,8 @@
#include "esp_private/mspi_timing_config.h" #include "esp_private/mspi_timing_config.h"
#include "mspi_timing_tuning_configs.h" #include "mspi_timing_tuning_configs.h"
#include "hal/psram_ctrlr_ll.h" #include "hal/psram_ctrlr_ll.h"
#include "hal/mspi_timing_tuning_ll.h"
#include "soc/hp_sys_clkrst_struct.h"
const static char *TAG = "MSPI Timing"; const static char *TAG = "MSPI Timing";
@@ -35,5 +37,24 @@ void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_spe
void mspi_timing_config_set_flash_clock(uint32_t flash_freq_mhz, mspi_timing_speed_mode_t speed_mode, bool control_both_mspi) void mspi_timing_config_set_flash_clock(uint32_t flash_freq_mhz, mspi_timing_speed_mode_t speed_mode, bool control_both_mspi)
{ {
//For compatibility #if MSPI_TIMING_FLASH_NEEDS_TUNING
assert(HP_SYS_CLKRST.peri_clk_ctrl00.reg_flash_clk_src_sel == 1);
uint32_t core_clock_mhz = MSPI_TIMING_SPLL_FREQ_MHZ / MSPI_TIMING_LL_FLASH_CORE_CLK_DIV;
assert(core_clock_mhz == 120);
uint32_t freqdiv = core_clock_mhz / flash_freq_mhz;
PERIPH_RCC_ATOMIC() {
//core clock shared among SPI0 / SPI1
mspi_timing_ll_set_flash_core_clock(MSPI_TIMING_LL_MSPI_ID_0, core_clock_mhz);
}
mspi_timing_ll_set_flash_clock(MSPI_TIMING_LL_MSPI_ID_0, freqdiv);
if (control_both_mspi) {
mspi_timing_ll_set_flash_clock(MSPI_TIMING_LL_MSPI_ID_1, freqdiv);
}
mspi_timing_ll_mask_invalid_dqs(MSPI_TIMING_LL_MSPI_ID_0, true);
mspi_timing_ll_mask_invalid_dqs(MSPI_TIMING_LL_MSPI_ID_1, true);
#endif
} }

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -7,10 +7,12 @@
#include "sdkconfig.h" #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_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_TEST_DATA_LEN 128
#define MSPI_TIMING_PSRAM_TEST_DATA_ADDR 0x80 #define MSPI_TIMING_PSRAM_TEST_DATA_ADDR 0x80
#define MSPI_TIMING_DELAYLINE_TEST_NUMS 100 #define MSPI_TIMING_DELAYLINE_TEST_NUMS 100
#define MSPI_TIMING_FLASH_TEST_DATA_ADDR CONFIG_BOOTLOADER_OFFSET_IN_FLASH
#define MSPI_TIMING_CORE_CLOCK_DIV 1 #define MSPI_TIMING_CORE_CLOCK_DIV 1
#if CONFIG_SPIRAM_SPEED_250M #if CONFIG_SPIRAM_SPEED_250M
@@ -22,5 +24,42 @@
#else #else
#define MSPI_TIMING_MPLL_FREQ_MHZ 400 #define MSPI_TIMING_MPLL_FREQ_MHZ 400
#endif #endif
#define MSPI_TIMING_SPLL_FREQ_MHZ 480
#define MSPI_TIMING_PSRAM_DTR_MODE CONFIG_SPIRAM_MODE_HEX #define MSPI_TIMING_PSRAM_DTR_MODE CONFIG_SPIRAM_MODE_HEX
#define MSPI_TIMING_FLASH_STR_MODE 1
#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
#else //CONFIG_ESPTOOLPY_FLASHFREQ_120M
#define MSPI_TIMING_FLASH_MODULE_CLOCK 120
#endif
#define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 80)
#if MSPI_TIMING_FLASH_NEEDS_TUNING
#define MSPI_TIMING_FLASH_CORE_CLOCK_MHZ 120
#else
#define MSPI_TIMING_FLASH_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, \
.flash_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)
/**
* Timing Tuning Parameters
*/
//FLASH: core clock 120M, module clock 120M, STR mode
#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_120M_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_120M_MODULE_CLK_120M_STR_MODE 12
#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 2

View File

@@ -20,7 +20,7 @@ components/esp_hw_support/test_apps/host_test_linux:
components/esp_hw_support/test_apps/mspi: components/esp_hw_support/test_apps/mspi:
disable: disable:
- if: IDF_TARGET != "esp32s3" - if: IDF_TARGET not in ["esp32s3", "esp32p4"]
components/esp_hw_support/test_apps/mspi_psram_with_dfs: components/esp_hw_support/test_apps/mspi_psram_with_dfs:
disable: disable:

View File

@@ -1,5 +1,5 @@
| Supported Targets | ESP32-S3 | | Supported Targets | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | | ----------------- | -------- | -------- |
This project tests if Flash and PSRAM can work under different configurations. This project tests if Flash and PSRAM can work under different configurations.
To add new configuration, create one more sdkconfig.ci.NAME file in this directory. To add new configuration, create one more sdkconfig.ci.NAME file in this directory.

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -22,9 +22,15 @@ static void sorted_array_insert(uint32_t *array, uint32_t *size, uint32_t item)
(*size)++; (*size)++;
} }
#if CONFIG_IDF_TARGET_ESP32S3
#define TEST_TIME_CNT 10 #define TEST_TIME_CNT 10
#define TEST_TIME_LIMIT_US 10 #define TEST_TIME_LIMIT_US 10
TEST_CASE("MSPI: Test mspi timing turning time cost", "[mspi]") #elif CONFIG_IDF_TARGET_ESP32P4
#define TEST_TIME_CNT 30
#define TEST_TIME_LIMIT_US 30
#endif
TEST_CASE("MSPI: Test mspi timing tuning time cost", "[mspi]")
{ {
uint64_t start, end; uint64_t start, end;
uint32_t cost, index_1 = 0, index_2 = 0; uint32_t cost, index_1 = 0, index_2 = 0;

View File

@@ -1,13 +1,12 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0 # SPDX-License-Identifier: CC0-1.0
import os import os
import pathlib import pathlib
import pytest import pytest
from pytest_embedded_idf import IdfDut from pytest_embedded_idf import IdfDut
MSPI_F8R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f8r8*')] MSPI_F8R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.esp32s3_f8r8*')]
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@@ -18,7 +17,7 @@ def test_flash8_psram8(dut: IdfDut) -> None:
# For F4R8 board (Quad Flash and Octal PSRAM) # For F4R8 board (Quad Flash and Octal PSRAM)
MSPI_F4R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r8*')] MSPI_F4R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.esp32s3_f4r8*')]
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@@ -29,7 +28,7 @@ def test_flash4_psram8(dut: IdfDut) -> None:
# For F4R4 board (Quad Flash and Quad PSRAM) # For F4R4 board (Quad Flash and Quad PSRAM)
MSPI_F4R4_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f4r4*')] MSPI_F4R4_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.esp32s3_f4r4*')]
@pytest.mark.esp32s3 @pytest.mark.esp32s3
@@ -37,3 +36,16 @@ MSPI_F4R4_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(o
@pytest.mark.parametrize('config', MSPI_F4R4_configs, indirect=True) @pytest.mark.parametrize('config', MSPI_F4R4_configs, indirect=True)
def test_flash4_psram4(dut: IdfDut) -> None: def test_flash4_psram4(dut: IdfDut) -> None:
dut.run_all_single_board_cases() dut.run_all_single_board_cases()
@pytest.mark.esp32p4
@pytest.mark.flash_120m
@pytest.mark.parametrize(
'config',
[
'esp32p4_120sdr_200ddr',
],
indirect=True,
)
def test_flash_psram_esp32p4(dut: IdfDut) -> None:
dut.run_all_single_board_cases()

View File

@@ -0,0 +1,8 @@
CONFIG_IDF_TARGET="esp32p4"
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_SPEED_200M=y
CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
CONFIG_SPI_FLASH_HPM_ENA=y
CONFIG_BOOTLOADER_FLASH_DC_AWARE=y

View File

@@ -1,5 +1,7 @@
# Legacy, F4R4, Flash 120M SDR, PSRAM disable # Legacy, F4R4, Flash 120M SDR, PSRAM disable
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F4R4, Flash 120M SDR, PSRAM 120M SDR # Legacy, F4R4, Flash 120M SDR, PSRAM 120M SDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F4R4, Flash 120M SDR, PSRAM 40M SDR # Legacy, F4R4, Flash 120M SDR, PSRAM 40M SDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F4R4, Flash 120M SDR, PSRAM disable, compiler -Os and silent # Legacy, F4R4, Flash 120M SDR, PSRAM disable, compiler -Os and silent
CONFIG_IDF_TARGET="esp32s3"
CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

View File

@@ -1,5 +1,7 @@
# Legacy, F4R4, Flash 40M SDR, PSRAM 120M SDR # Legacy, F4R4, Flash 40M SDR, PSRAM 120M SDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F4R4, Flash 80M SDR, PSRAM 80M SDR # Legacy, F4R4, Flash 80M SDR, PSRAM 80M SDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F4R8, Flash 120M SDR, PSRAM disable # Legacy, F4R8, Flash 120M SDR, PSRAM disable
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F4R8, Flash 80M SDR, PSRAM 40M DDR # Legacy, F4R8, Flash 80M SDR, PSRAM 40M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F4R8, Flash 80M SDR, PSRAM 80M DDR # Legacy, F4R8, Flash 80M SDR, PSRAM 80M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F8R8, Flash 120M SDR, PSRAM disable # Legacy, F8R8, Flash 120M SDR, PSRAM disable
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F8R8, Flash 40M DDR, PSRAM 40M DDR # Legacy, F8R8, Flash 40M DDR, PSRAM 40M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F8R8, Flash 40M DDR, PSRAM 80M DDR # Legacy, F8R8, Flash 40M DDR, PSRAM 80M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F8R8, Flash 80M DDR, PSRAM 40M DDR # Legacy, F8R8, Flash 80M DDR, PSRAM 40M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F8R8, Flash 80M DDR, PSRAM 80M DDR # Legacy, F8R8, Flash 80M DDR, PSRAM 80M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F8R8, Flash 80M DDR, PSRAM 80M DDR # Legacy, F8R8, Flash 80M DDR, PSRAM 80M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -1,5 +1,7 @@
# Legacy, F8R8, Flash 80M SDR, PSRAM 80M DDR # Legacy, F8R8, Flash 80M SDR, PSRAM 80M DDR
CONFIG_IDF_TARGET="esp32s3"
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@@ -561,7 +561,7 @@ void IRAM_ATTR call_start_cpu0(void)
* In this stage, we re-configure the Flash (and MSPI) to required configuration * In this stage, we re-configure the Flash (and MSPI) to required configuration
*/ */
spi_flash_init_chip_state(); spi_flash_init_chip_state();
#if SOC_MEMSPI_SRC_FREQ_120M #if SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED
// This function needs to be called when PLL is enabled. Needs to be called after spi_flash_init_chip_state in case // This function needs to be called when PLL is enabled. Needs to be called after spi_flash_init_chip_state in case
// some state of flash is modified. // some state of flash is modified.
mspi_timing_flash_tuning(); mspi_timing_flash_tuning();

View File

@@ -15,15 +15,34 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "hal/assert.h" #include "hal/assert.h"
#include "hal/misc.h"
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/iomux_mspi_pin_reg.h" #include "soc/iomux_mspi_pin_reg.h"
#include "soc/iomux_mspi_pin_struct.h" #include "soc/iomux_mspi_pin_struct.h"
#include "soc/hp_sys_clkrst_reg.h" #include "soc/hp_sys_clkrst_reg.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/spi_mem_c_reg.h"
#include "soc/spi1_mem_c_reg.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define MSPI_TIMING_LL_MSPI_ID_0 0
#define MSPI_TIMING_LL_MSPI_ID_1 1
#define MSPI_TIMING_LL_FLASH_CORE_CLK_DIV 4
#define MSPI_TIMING_LL_FLASH_FDUMMY_RIN_SUPPORTED 1
#define MSPI_TIMING_LL_FLASH_OCT_MASK (SPI_MEM_C_FCMD_OCT | SPI_MEM_C_FADDR_OCT | SPI_MEM_C_FDIN_OCT | SPI_MEM_C_FDOUT_OCT)
#define MSPI_TIMING_LL_FLASH_QUAD_MASK (SPI_MEM_C_FASTRD_MODE | SPI_MEM_C_FREAD_DUAL | SPI_MEM_C_FREAD_DIO | SPI_MEM_C_FREAD_QUAD | SPI_MEM_C_FREAD_QIO)
#define MSPI_TIMING_LL_FLASH_QIO_MODE_MASK (SPI_MEM_C_FREAD_QIO | SPI_MEM_C_FASTRD_MODE)
#define MSPI_TIMING_LL_FLASH_QUAD_MODE_MASK (SPI_MEM_C_FREAD_QUAD | SPI_MEM_C_FASTRD_MODE)
#define MSPI_TIMING_LL_FLASH_DIO_MODE_MASK (SPI_MEM_C_FREAD_DIO | SPI_MEM_C_FASTRD_MODE)
#define MSPI_TIMING_LL_FLASH_DUAL_MODE_MASK (SPI_MEM_C_FREAD_DUAL | SPI_MEM_C_FASTRD_MODE)
#define MSPI_TIMING_LL_FLASH_FAST_MODE_MASK (SPI_MEM_C_FASTRD_MODE)
#define MSPI_TIMING_LL_FLASH_SLOW_MODE_MASK 0
/** /**
* MSPI DQS ID * MSPI DQS ID
*/ */
@@ -72,6 +91,19 @@ typedef enum {
MSPI_LL_PIN_MAX, MSPI_LL_PIN_MAX,
} mspi_ll_pin_t; } mspi_ll_pin_t;
/**
* MSPI flash mode
*/
typedef enum {
MSPI_TIMING_LL_FLASH_OPI_MODE = BIT(0),
MSPI_TIMING_LL_FLASH_QIO_MODE = BIT(1),
MSPI_TIMING_LL_FLASH_QUAD_MODE = BIT(2),
MSPI_TIMING_LL_FLASH_DIO_MODE = BIT(3),
MSPI_TIMING_LL_FLASH_DUAL_MODE = BIT(4),
MSPI_TIMING_LL_FLASH_FAST_MODE = BIT(5),
MSPI_TIMING_LL_FLASH_SLOW_MODE = BIT(6),
} mspi_timing_ll_flash_mode_t;
/** /**
* Reset the MSPI clock * Reset the MSPI clock
*/ */
@@ -86,6 +118,9 @@ static inline void _mspi_timing_ll_reset_mspi(void)
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define mspi_timing_ll_reset_mspi(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _mspi_timing_ll_reset_mspi(__VA_ARGS__) #define mspi_timing_ll_reset_mspi(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _mspi_timing_ll_reset_mspi(__VA_ARGS__)
/*---------------------------------------------------------------
PSRAM tuning
---------------------------------------------------------------*/
/** /**
* Set all MSPI DQS phase * Set all MSPI DQS phase
* *
@@ -200,6 +235,330 @@ static inline void mspi_timing_ll_pin_drv_set(uint8_t drv)
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_CS_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_CS_DRV, drv); REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_CS_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_CS_DRV, drv);
} }
/*---------------------------------------------------------------
Flash tuning
---------------------------------------------------------------*/
/**
* Set MSPI Flash core clock
*
* @param spi_num SPI0 / SPI1
* @param core_clk_mhz core clock mhz
*/
__attribute__((always_inline))
static inline void _mspi_timing_ll_set_flash_core_clock(int spi_num, uint32_t core_clk_mhz)
{
(void)spi_num;
if (core_clk_mhz == 120) {
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl00, reg_flash_core_clk_div_num, (MSPI_TIMING_LL_FLASH_CORE_CLK_DIV - 1));
HP_SYS_CLKRST.peri_clk_ctrl00.reg_flash_core_clk_en = 1;
} else {
//ESP32P4 flash timing tuning is based on SPLL==480MHz, flash_core_clock==120MHz. We add assertion here to ensure this
HAL_ASSERT(false);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define mspi_timing_ll_set_flash_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _mspi_timing_ll_set_flash_core_clock(__VA_ARGS__)
/**
* Set MSPI Flash clock
*
* @param spi_num SPI0 / SPI1
* @param freqdiv Divider value
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_flash_clock(uint8_t spi_num, uint32_t freqdiv)
{
if (spi_num == MSPI_TIMING_LL_MSPI_ID_0) {
if (freqdiv == 1) {
WRITE_PERI_REG(SPI_MEM_C_CLOCK_REG, SPI_MEM_C_CLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI_MEM_C_CLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI_MEM_C_CLKCNT_H_S)) | ((freqdiv - 1) << SPI_MEM_C_CLKCNT_L_S);
WRITE_PERI_REG(SPI_MEM_C_CLOCK_REG, freqbits);
}
} else if (spi_num == MSPI_TIMING_LL_MSPI_ID_1) {
if (freqdiv == 1) {
WRITE_PERI_REG(SPI1_MEM_C_CLOCK_REG, SPI1_MEM_C_CLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI1_MEM_C_CLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI1_MEM_C_CLKCNT_H_S)) | ((freqdiv - 1) << SPI1_MEM_C_CLKCNT_L_S);
WRITE_PERI_REG(SPI1_MEM_C_CLOCK_REG, freqbits);
}
} else {
HAL_ASSERT(false);
}
}
/**
* Enable Flash timing adjust clock
*
* @param spi_num SPI0 / SPI1
*/
__attribute__((always_inline))
static inline void mspi_timinng_ll_enable_flash_timing_adjust_clk(uint8_t spi_num)
{
(void)spi_num;
REG_GET_BIT(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CLK_ENA);
}
/**
* Set MSPI Flash din mode
*
* @param spi_num SPI0 / SPI1
* @param din_mode Din mode value
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_flash_din_mode(uint8_t spi_num, uint8_t din_mode)
{
(void)spi_num;
uint32_t reg_val = (REG_READ(SPI_MEM_C_DIN_MODE_REG) & (~(SPI_MEM_C_DIN0_MODE_M | SPI_MEM_C_DIN1_MODE_M | SPI_MEM_C_DIN2_MODE_M | SPI_MEM_C_DIN3_MODE_M | SPI_MEM_C_DIN4_MODE_M | SPI_MEM_C_DIN5_MODE_M | SPI_MEM_C_DIN6_MODE_M | SPI_MEM_C_DIN7_MODE_M | SPI_MEM_C_DINS_MODE_M)))
| (din_mode << SPI_MEM_C_DIN0_MODE_S) | (din_mode << SPI_MEM_C_DIN1_MODE_S) | (din_mode << SPI_MEM_C_DIN2_MODE_S) | (din_mode << SPI_MEM_C_DIN3_MODE_S)
| (din_mode << SPI_MEM_C_DIN4_MODE_S) | (din_mode << SPI_MEM_C_DIN5_MODE_S) | (din_mode << SPI_MEM_C_DIN6_MODE_S) | (din_mode << SPI_MEM_C_DIN7_MODE_S) | (din_mode << SPI_MEM_C_DINS_MODE_S);
REG_WRITE(SPI_MEM_C_DIN_MODE_REG, reg_val);
REG_SET_BIT(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE);
}
/**
* Set MSPI Flash din num
*
* @param spi_num SPI0 / SPI1
* @param din_num Din num value
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_flash_din_num(uint8_t spi_num, uint8_t din_num)
{
(void)spi_num;
uint32_t reg_val = (REG_READ(SPI_MEM_C_DIN_NUM_REG) & (~(SPI_MEM_C_DIN0_NUM_M | SPI_MEM_C_DIN1_NUM_M | SPI_MEM_C_DIN2_NUM_M | SPI_MEM_C_DIN3_NUM_M | SPI_MEM_C_DIN4_NUM_M | SPI_MEM_C_DIN5_NUM_M | SPI_MEM_C_DIN6_NUM_M | SPI_MEM_C_DIN7_NUM_M | SPI_MEM_C_DINS_NUM_M)))
| (din_num << SPI_MEM_C_DIN0_NUM_S) | (din_num << SPI_MEM_C_DIN1_NUM_S) | (din_num << SPI_MEM_C_DIN2_NUM_S) | (din_num << SPI_MEM_C_DIN3_NUM_S)
| (din_num << SPI_MEM_C_DIN4_NUM_S) | (din_num << SPI_MEM_C_DIN5_NUM_S) | (din_num << SPI_MEM_C_DIN6_NUM_S) | (din_num << SPI_MEM_C_DIN7_NUM_S) | (din_num << SPI_MEM_C_DINS_NUM_S);
REG_WRITE(SPI_MEM_C_DIN_NUM_REG, reg_val);
REG_SET_BIT(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE);
}
/**
* Set MSPI Flash extra dummy
*
* @param spi_num SPI0 / SPI1
* @param extra_dummy Extra dummy
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_flash_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
{
if (spi_num == MSPI_TIMING_LL_MSPI_ID_0) {
if (extra_dummy > 0) {
SET_PERI_REG_MASK(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_M);
SET_PERI_REG_BITS(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, SPI_MEM_C_EXTRA_DUMMY_CYCLELEN_S);
} else {
CLEAR_PERI_REG_MASK(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_M);
SET_PERI_REG_BITS(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_EXTRA_DUMMY_CYCLELEN_V, 0, SPI_MEM_C_EXTRA_DUMMY_CYCLELEN_S);
}
REG_SET_BIT(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE);
} else if (spi_num == MSPI_TIMING_LL_MSPI_ID_1) {
if (extra_dummy > 0) {
SET_PERI_REG_MASK(SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI);
SET_PERI_REG_BITS(SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, SPI1_MEM_C_EXTRA_DUMMY_CYCLELEN_S);
} else {
CLEAR_PERI_REG_MASK(SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI);
SET_PERI_REG_BITS(SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_EXTRA_DUMMY_CYCLELEN_V, 0, SPI1_MEM_C_EXTRA_DUMMY_CYCLELEN_S);
}
REG_SET_BIT(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE);
} else {
HAL_ASSERT(false);
}
}
/**
* Set MSPI Flash user dummy
*
* @param spi_num SPI0 / SPI1
* @param user_dummy user dummy
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_flash_user_dummy(uint8_t spi_num, uint8_t user_dummy)
{
if (spi_num == MSPI_TIMING_LL_MSPI_ID_0) {
REG_SET_FIELD(SPI_MEM_C_USER1_REG, SPI_MEM_C_USR_DUMMY_CYCLELEN, user_dummy);
} else if (spi_num == MSPI_TIMING_LL_MSPI_ID_1) {
REG_SET_FIELD(SPI1_MEM_C_USER1_REG, SPI1_MEM_C_USR_DUMMY_CYCLELEN, user_dummy);
} else {
HAL_ASSERT(false);
}
}
/**
* Enable/Disable Flash variable dummy
*
* @param spi_num SPI0 / SPI1
* @param enable Enable / Disable
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_enable_flash_variable_dummy(uint8_t spi_num, bool enable)
{
(void)spi_num;
REG_SET_FIELD(SPI1_MEM_C_DDR_REG, SPI1_MEM_C_FMEM_VAR_DUMMY, enable);
}
/**
* Mask invalid DQS
*
* @param spi_num SPI0 / SPI1
* @param enable Enable / Disable
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_mask_invalid_dqs(uint8_t spi_num, bool enable)
{
if (spi_num == MSPI_TIMING_LL_MSPI_ID_0) {
REG_SET_FIELD(SPI_MEM_C_CTRL_REG, SPI_MEM_C_FDUMMY_RIN, enable);
} else if (spi_num == MSPI_TIMING_LL_MSPI_ID_1) {
REG_SET_FIELD(SPI1_MEM_C_CTRL_REG, SPI1_MEM_C_FDUMMY_RIN, enable);
} else {
HAL_ASSERT(false);
}
}
/**
* Get if cs setup is enabled or not
*
* @param spi_num SPI0 / SPI1
*
* @return
* true: enabled; false: disabled
*/
__attribute__((always_inline))
static inline bool mspi_timing_ll_is_cs_setup_enabled(uint8_t spi_num)
{
(void)spi_num;
return REG_GET_BIT(SPI_MEM_C_USER_REG, SPI_MEM_C_CS_SETUP);
}
/**
* Get cs setup val
*
* @param spi_num SPI0 / SPI1
*
* @return
* cs setup reg val
*/
static inline uint32_t mspi_timing_ll_get_cs_setup_val(uint8_t spi_num)
{
(void)spi_num;
return REG_GET_FIELD(SPI_MEM_C_CTRL2_REG, SPI_MEM_C_CS_SETUP_TIME);
}
/**
* Get if cs hold is enabled or not
*
* @param spi_num SPI0 / SPI1
*
* @return
* true: enabled; false: disabled
*/
__attribute__((always_inline))
static inline bool mspi_timing_ll_is_cs_hold_enabled(uint8_t spi_num)
{
(void)spi_num;
return REG_GET_FIELD(SPI_MEM_C_USER_REG, SPI_MEM_C_CS_HOLD);
}
/**
* Get cs hold val
*
* @param spi_num SPI0 / SPI1
*
* @return
* cs hold reg val
*/
static inline uint32_t mspi_timing_ll_get_cs_hold_val(uint8_t spi_num)
{
(void)spi_num;
return REG_GET_FIELD(SPI_MEM_C_CTRL2_REG, SPI_MEM_C_CS_HOLD_TIME);
}
/**
* Get clock reg val
*
* @param spi_num SPI0 / SPI1
*
* @return
* clock reg val
*/
__attribute__((always_inline))
static inline uint32_t mspi_timing_ll_get_clock_reg(uint8_t spi_num)
{
(void)spi_num;
return READ_PERI_REG(SPI1_MEM_C_CLOCK_REG);
}
/**
* Get MSPI Flash mode
*
* @param spi_num SPI0 / SPI1
*
* @return Flash mode
*/
__attribute__((always_inline))
static inline mspi_timing_ll_flash_mode_t mspi_timing_ll_get_flash_mode(uint8_t spi_num)
{
uint32_t ctrl_reg = READ_PERI_REG(SPI_MEM_C_CTRL_REG);
if (ctrl_reg & MSPI_TIMING_LL_FLASH_OCT_MASK) {
return MSPI_TIMING_LL_FLASH_OPI_MODE;
}
switch (ctrl_reg & MSPI_TIMING_LL_FLASH_QUAD_MASK) {
case MSPI_TIMING_LL_FLASH_QIO_MODE_MASK:
return MSPI_TIMING_LL_FLASH_QIO_MODE;
case MSPI_TIMING_LL_FLASH_QUAD_MODE_MASK:
return MSPI_TIMING_LL_FLASH_QUAD_MODE;
case MSPI_TIMING_LL_FLASH_DIO_MODE_MASK:
return MSPI_TIMING_LL_FLASH_DIO_MODE;
case MSPI_TIMING_LL_FLASH_DUAL_MODE_MASK:
return MSPI_TIMING_LL_FLASH_DUAL_MODE;
case MSPI_TIMING_LL_FLASH_FAST_MODE_MASK:
return MSPI_TIMING_LL_FLASH_FAST_MODE;
case MSPI_TIMING_LL_FLASH_SLOW_MODE_MASK:
return MSPI_TIMING_LL_FLASH_SLOW_MODE;
default:
HAL_ASSERT(false);
return (mspi_timing_ll_flash_mode_t)0;
}
}
/**
* Get MSPI flash dummy info
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_get_flash_dummy(uint8_t spi_num, int *usr_dummy, int *extra_dummy)
{
if (spi_num == MSPI_TIMING_LL_MSPI_ID_0) {
*usr_dummy = REG_GET_FIELD(SPI_MEM_C_USER1_REG, SPI_MEM_C_USR_DUMMY_CYCLELEN);
*extra_dummy = REG_GET_FIELD(SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_EXTRA_DUMMY_CYCLELEN);
} else if (spi_num == MSPI_TIMING_LL_MSPI_ID_1) {
*usr_dummy = REG_GET_FIELD(SPI1_MEM_C_USER1_REG, SPI1_MEM_C_USR_DUMMY_CYCLELEN);
*extra_dummy = REG_GET_FIELD(SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_EXTRA_DUMMY_CYCLELEN);
} else {
HAL_ASSERT(false);
}
}
/**
* Mask invalid DQS
*
* @param spi_num SPI0 / SPI1
* @param enable Enable / Disable
*/
__attribute__((always_inline))
static inline uint32_t mspi_timing_ll_get_invalid_dqs_mask(uint8_t spi_num)
{
if (spi_num == MSPI_TIMING_LL_MSPI_ID_0) {
return REG_GET_FIELD(SPI_MEM_C_CTRL_REG, SPI_MEM_C_FDUMMY_RIN);
} else if (spi_num == MSPI_TIMING_LL_MSPI_ID_1) {
return REG_GET_FIELD(SPI1_MEM_C_CTRL_REG, SPI1_MEM_C_FDUMMY_RIN);
} else {
HAL_ASSERT(false);
}
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -643,6 +643,11 @@ static inline void spimem_flash_ll_set_extra_dummy(spi_mem_dev_t *dev, uint32_t
//for compatibility //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 * Get the spi flash source clock frequency. Used for calculating
* the divider parameters. * the divider parameters.

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -101,23 +101,23 @@ static inline void mspi_timing_ll_set_psram_clock_pin_drive(uint8_t spi_num, uin
} }
/** /**
* Enable Flash HCLK * Enable Flash timing adjust clock
* *
* @param spi_num SPI0 / SPI1 * @param spi_num SPI0 / SPI1
*/ */
__attribute__((always_inline)) __attribute__((always_inline))
static inline void mspi_timinng_ll_enable_flash_hclk(uint8_t spi_num) static inline void mspi_timinng_ll_enable_flash_timing_adjust_clk(uint8_t spi_num)
{ {
REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CLK_ENA); REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CLK_ENA);
} }
/** /**
* Enable PSRAM HCLK * Enable PSRAM timing adjust clock
* *
* @param spi_num SPI0 / SPI1 * @param spi_num SPI0 / SPI1
*/ */
__attribute__((always_inline)) __attribute__((always_inline))
static inline void mspi_timinng_ll_enable_psram_hclk(uint8_t spi_num) static inline void mspi_timinng_ll_enable_psram_timing_adjust_clk(uint8_t spi_num)
{ {
REG_SET_BIT(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CLK_ENA); REG_SET_BIT(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CLK_ENA);
} }

View File

@@ -640,6 +640,11 @@ static inline void spimem_flash_ll_set_extra_dummy(spi_mem_dev_t *dev, uint32_t
dev->timing_cali.extra_dummy_cyclelen = extra_dummy; dev->timing_cali.extra_dummy_cyclelen = extra_dummy;
} }
static inline void spimem_flash_ll_set_fdummy_rin(spi_mem_dev_t *dev, uint32_t fdummy_rin)
{
//for compatibility
}
/** /**
* Get the spi flash source clock frequency. Used for calculating * Get the spi flash source clock frequency. Used for calculating
* the divider parameters. * the divider parameters.

View File

@@ -42,9 +42,9 @@ typedef struct {
int cs_num; ///< Which cs pin is used, 0-2. int cs_num; ///< Which cs pin is used, 0-2.
struct { struct {
uint8_t extra_dummy; ///< Pre-calculated extra dummy used for compensation uint8_t extra_dummy; ///< Pre-calculated extra dummy used for compensation
uint8_t fdummy_rin; ///< Mask invalid dqs or not
uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock. uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock.
uint8_t cs_hold; ///< CS hold time config used by the host uint8_t cs_hold; ///< CS hold time config used by the host
uint8_t reserved2; ///< Reserved, set to 0.
}; };
spi_flash_ll_clock_reg_t clock_conf; ///< Pre-calculated clock configuration value spi_flash_ll_clock_reg_t clock_conf; ///< Pre-calculated clock configuration value
esp_flash_io_mode_t base_io_mode; ///< Default IO mode mask for common commands esp_flash_io_mode_t base_io_mode; ///< Default IO mode mask for common commands
@@ -63,6 +63,7 @@ ESP_STATIC_ASSERT(sizeof(spi_flash_hal_context_t) == 48, "size of spi_flash_hal_
/// This struct provide MSPI Flash necessary timing related config, should be consistent with that in union in `spi_flash_hal_config_t`. /// This struct provide MSPI Flash necessary timing related config, should be consistent with that in union in `spi_flash_hal_config_t`.
typedef struct { typedef struct {
uint32_t extra_dummy; uint32_t extra_dummy;
uint32_t fdummy_rin;
uint32_t cs_hold; uint32_t cs_hold;
uint8_t cs_setup; uint8_t cs_setup;
spi_flash_ll_clock_reg_t clock_config; spi_flash_ll_clock_reg_t clock_config;
@@ -73,6 +74,7 @@ typedef struct {
union { union {
struct { struct {
uint32_t extra_dummy; ///< extra dummy for timing compensation. uint32_t extra_dummy; ///< extra dummy for timing compensation.
uint32_t fdummy_rin; ///< Mask invalid dqs or not
uint32_t cs_hold; ///< CS hold time config used by the host uint32_t cs_hold; ///< CS hold time config used by the host
uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock
spi_flash_ll_clock_reg_t clock_config; ///< (optional) Clock configuration for Octal flash. spi_flash_ll_clock_reg_t clock_config; ///< (optional) Clock configuration for Octal flash.

View File

@@ -117,6 +117,7 @@ esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_
#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING #if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
if (cfg->using_timing_tuning) { if (cfg->using_timing_tuning) {
data_out->extra_dummy = extra_dummy_under_timing_tuning(cfg); data_out->extra_dummy = extra_dummy_under_timing_tuning(cfg);
data_out->fdummy_rin = cfg->fdummy_rin;
data_out->clock_conf = cfg->clock_config; data_out->clock_conf = cfg->clock_config;
} else } else
#endif // SOC_SPI_MEM_SUPPORT_TIMING_TUNING #endif // SOC_SPI_MEM_SUPPORT_TIMING_TUNING

View File

@@ -161,6 +161,12 @@ esp_err_t spi_flash_hal_configure_host_io_mode(
spi_flash_ll_set_miso_bitlen(dev, 0); spi_flash_ll_set_miso_bitlen(dev, 0);
spi_flash_ll_set_mosi_bitlen(dev, 0); spi_flash_ll_set_mosi_bitlen(dev, 0);
spi_flash_ll_set_read_mode(dev, io_mode); spi_flash_ll_set_read_mode(dev, io_mode);
#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)host;
if (ctx->fdummy_rin) {
spimem_flash_ll_set_fdummy_rin((spi_mem_dev_t*)dev, ctx->fdummy_rin);
}
#endif
return ESP_OK; return ESP_OK;
} }

View File

@@ -1559,6 +1559,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_DQS
bool bool
default y default y
config SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
bool
default y
config SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP config SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP
bool bool
default y default y
@@ -1579,6 +1583,10 @@ config SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED
bool bool
default y default y
config SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED
bool
default y
config SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT config SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT
bool bool
default y default y

View File

@@ -580,6 +580,7 @@
// #define SOC_SPI_MEM_SUPPORT_WRAP (1) // IDFCI-2073 The feature cannot be treated as supported on P4 // #define SOC_SPI_MEM_SUPPORT_WRAP (1) // IDFCI-2073 The feature cannot be treated as supported on P4
#define SOC_SPI_MEM_SUPPORT_TIMING_TUNING (1) #define SOC_SPI_MEM_SUPPORT_TIMING_TUNING (1)
#define SOC_MEMSPI_TIMING_TUNING_BY_DQS (1) #define SOC_MEMSPI_TIMING_TUNING_BY_DQS (1)
#define SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY (1)
#define SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP (1) #define SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP (1)
#define SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT (1) #define SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT (1)
@@ -587,6 +588,7 @@
#define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED 1
#define SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT 1 #define SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT 1

View File

@@ -919,7 +919,7 @@ config SOC_SPI_SCT_CONF_BITLEN_MAX
hex hex
default 0x3FFFA default 0x3FFFA
config SOC_MEMSPI_SRC_FREQ_120M config SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED
bool bool
default y default y

View File

@@ -360,7 +360,7 @@
#define SOC_SPI_SCT_BUFFER_NUM_MAX (1 + SOC_SPI_SCT_REG_NUM) //1-word-bitmap + 14-word-regs #define SOC_SPI_SCT_BUFFER_NUM_MAX (1 + SOC_SPI_SCT_REG_NUM) //1-word-bitmap + 14-word-regs
#define SOC_SPI_SCT_CONF_BITLEN_MAX 0x3FFFA //18 bits wide reg #define SOC_SPI_SCT_CONF_BITLEN_MAX 0x3FFFA //18 bits wide reg
#define SOC_MEMSPI_SRC_FREQ_120M 1 #define SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1

View File

@@ -36,7 +36,7 @@ menu "Main Flash configuration"
choice SPI_FLASH_HPM choice SPI_FLASH_HPM
prompt "High Performance Mode (READ DOCS FIRST, > 80MHz)" prompt "High Performance Mode (READ DOCS FIRST, > 80MHz)"
# Currently, only esp32s3 allows high performance mode. # Currently, only esp32s3 allows high performance mode.
depends on IDF_TARGET_ESP32S3 && !ESPTOOLPY_OCT_FLASH depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && !ESPTOOLPY_OCT_FLASH
default SPI_FLASH_HPM_AUTO default SPI_FLASH_HPM_AUTO
help help
Whether the High Performance Mode of Flash is enabled. As an optional feature, user needs to manually Whether the High Performance Mode of Flash is enabled. As an optional feature, user needs to manually
@@ -56,7 +56,7 @@ menu "Main Flash configuration"
config SPI_FLASH_HPM_ON config SPI_FLASH_HPM_ON
bool bool
# For ESP32-S3, it's enabled by default. For later chips it should be disabled by default # For ESP32-S3, it's enabled by default. For later chips it should be disabled by default
default y if IDF_TARGET_ESP32S3 && ((SPI_FLASH_HPM_ENA || SPI_FLASH_HPM_AUTO)) || \ default y if (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && ((SPI_FLASH_HPM_ENA || SPI_FLASH_HPM_AUTO)) || \
(!IDF_TARGET_ESP32S3 && SPI_FLASH_HPM_ENA) (!IDF_TARGET_ESP32S3 && SPI_FLASH_HPM_ENA)
help help
This option is invisible, and will be selected automatically This option is invisible, and will be selected automatically

View File

@@ -2,6 +2,10 @@ choice ESPTOOLPY_FLASHFREQ
prompt "Flash SPI speed" prompt "Flash SPI speed"
default ESPTOOLPY_FLASHFREQ_40M if ESP32P4_REV_MIN_0 default ESPTOOLPY_FLASHFREQ_40M if ESP32P4_REV_MIN_0
default ESPTOOLPY_FLASHFREQ_80M default ESPTOOLPY_FLASHFREQ_80M
config ESPTOOLPY_FLASHFREQ_120M
bool "120 MHz"
depends on IDF_EXPERIMENTAL_FEATURES
depends on !ESP32P4_REV_MIN_0
config ESPTOOLPY_FLASHFREQ_80M config ESPTOOLPY_FLASHFREQ_80M
bool "80 MHz" bool "80 MHz"
depends on !ESP32P4_REV_MIN_0 depends on !ESP32P4_REV_MIN_0

View File

@@ -94,6 +94,7 @@ ENV_MARKERS = {
'MSPI_F8R8': 'runner with Octal Flash and Octal PSRAM', 'MSPI_F8R8': 'runner with Octal Flash and Octal PSRAM',
'MSPI_F4R8': 'runner with Quad Flash and Octal PSRAM', 'MSPI_F4R8': 'runner with Quad Flash and Octal PSRAM',
'MSPI_F4R4': 'runner with Quad Flash and Quad PSRAM', 'MSPI_F4R4': 'runner with Quad Flash and Quad PSRAM',
'flash_120m': 'runner with 120M supported Flash',
'jtag': 'runner where the chip is accessible through JTAG as well', 'jtag': 'runner where the chip is accessible through JTAG as well',
'usb_serial_jtag': 'runner where the chip is accessible through builtin JTAG as well', 'usb_serial_jtag': 'runner where the chip is accessible through builtin JTAG as well',
'adc': 'ADC related tests should run on adc runners', 'adc': 'ADC related tests should run on adc runners',