mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 21:24:32 +02:00
mspi: support up-to-80MHz quad flash & up-to-80MHz octal psram on esp32s3
This commit is contained in:
@@ -205,10 +205,19 @@ static void IRAM_ATTR s_print_psram_info(opi_psram_mode_reg_t *reg_val)
|
||||
reg_val->mr0.drive_str == 0x02 ? 4 : 8);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR s_init_psram_pins(void)
|
||||
{
|
||||
//Set cs1 pin function
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1);
|
||||
//Set mspi cs1 drive strength
|
||||
PIN_SET_DRV(IO_MUX_GPIO26_REG, 3);
|
||||
//Set psram clock pin drive strength
|
||||
REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3);
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)
|
||||
{
|
||||
// enable CS signal
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1);
|
||||
s_init_psram_pins();
|
||||
|
||||
//enter MSPI slow mode to init PSRAM device registers
|
||||
spi_timing_enter_mspi_low_speed_mode();
|
||||
|
@@ -366,6 +366,7 @@ void IRAM_ATTR call_start_cpu0(void)
|
||||
Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||
|
||||
esp_mspi_pin_init();
|
||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
||||
bool efuse_opflash_en = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA3_REG, EFUSE_FLASH_TYPE);
|
||||
if (!efuse_opflash_en) {
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "esp32s3/rom/opi_flash.h"
|
||||
#include "spi_flash_private.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC
|
||||
#include "opi_flash_cmd_format_mxic.h"
|
||||
#endif
|
||||
@@ -21,40 +22,11 @@
|
||||
#define SPI_FLASH_SPI_CMD_RDCR 0x15
|
||||
#define SPI_FLASH_SPI_CMD_WRSRCR 0x01
|
||||
|
||||
#define SPI_FLASH_OCTCLK_IO 30
|
||||
#define SPI_FLASH_OCTDQS_IO 37
|
||||
#define SPI_FLASH_OCTD0_IO 32
|
||||
#define SPI_FLASH_OCTD1_IO 31
|
||||
#define SPI_FLASH_OCTD2_IO 28
|
||||
#define SPI_FLASH_OCTD3_IO 27
|
||||
#define SPI_FLASH_OCTD4_IO 33
|
||||
#define SPI_FLASH_OCTD5_IO 34
|
||||
#define SPI_FLASH_OCTD6_IO 35
|
||||
#define SPI_FLASH_OCTD7_IO 36
|
||||
#define SPI_FLASH_OCTCS_IO 29
|
||||
#define SPI_FLASH_OCTCS1_IO 26
|
||||
|
||||
|
||||
// default value is rom_default_spiflash_legacy_flash_func
|
||||
extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs;
|
||||
extern int SPI_write_enable(void *spi);
|
||||
DRAM_ATTR const esp_rom_opiflash_def_t opiflash_cmd_def = OPI_CMD_FORMAT();
|
||||
|
||||
void s_set_flash_pin_drive_capability(uint8_t drv)
|
||||
{
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCLK_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTDQS_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD0_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD1_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD2_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD3_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD4_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD5_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD6_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD7_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCS_IO, drv);
|
||||
esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCS1_IO, drv);
|
||||
}
|
||||
|
||||
static void s_register_rom_function(void)
|
||||
{
|
||||
@@ -145,6 +117,14 @@ static void s_set_flash_ouput_driver_strength(int spi_num, uint8_t strength)
|
||||
false);
|
||||
}
|
||||
|
||||
static void s_set_pin_drive_capability(uint8_t drv)
|
||||
{
|
||||
//flash clock
|
||||
REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3);
|
||||
//cs0
|
||||
PIN_SET_DRV(IO_MUX_GPIO29_REG, 3);
|
||||
}
|
||||
|
||||
static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode)
|
||||
{
|
||||
esp_rom_opiflash_legacy_driver_init(&opiflash_cmd_def);
|
||||
@@ -156,13 +136,13 @@ static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode)
|
||||
// STR/DTR specific setting
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR
|
||||
s_set_flash_pin_drive_capability(1);
|
||||
s_set_pin_drive_capability(3);
|
||||
s_set_flash_dtr_str_opi_mode(1, 0x1);
|
||||
esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd);
|
||||
esp_rom_spi_set_dtr_swap_mode(0, false, false);
|
||||
esp_rom_spi_set_dtr_swap_mode(1, false, false);
|
||||
#else //CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
|
||||
s_set_flash_pin_drive_capability(3);
|
||||
s_set_pin_drive_capability(3);
|
||||
s_set_flash_dtr_str_opi_mode(1, 0x2);
|
||||
esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd);
|
||||
esp_rom_spi_set_dtr_swap_mode(0, true, true);
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "esp32s3/rom/opi_flash.h"
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "esp32s3/clk.h"
|
||||
#include "esp32s3/clk.h"
|
||||
@@ -164,6 +165,17 @@ void IRAM_ATTR *spi_flash_malloc_internal(size_t size)
|
||||
}
|
||||
#endif
|
||||
|
||||
void IRAM_ATTR esp_mspi_pin_init(void)
|
||||
{
|
||||
#if CONFIG_ESPTOOLPY_OCT_FLASH || CONFIG_SPIRAM_MODE_OCT
|
||||
esp_rom_opiflash_pin_config();
|
||||
extern void spi_timing_set_pin_drive_strength(void);
|
||||
spi_timing_set_pin_drive_strength();
|
||||
#else
|
||||
//Set F4R4 board pin drive strength. TODO: IDF-3663
|
||||
#endif
|
||||
}
|
||||
|
||||
void spi_flash_init(void)
|
||||
{
|
||||
spi_flash_init_lock();
|
||||
|
@@ -56,6 +56,11 @@ void spi_timing_flash_tuning(void);
|
||||
*/
|
||||
void spi_timing_psram_tuning(void);
|
||||
|
||||
/**
|
||||
* @brief To initislize the MSPI pins
|
||||
*/
|
||||
void esp_mspi_pin_init(void);
|
||||
|
||||
/**
|
||||
* @brief Set SPI1 registers to make ROM functions work
|
||||
* @note This function is used for setting SPI1 registers to the state that ROM SPI functions work
|
||||
|
@@ -12,14 +12,42 @@
|
||||
#include "esp_types.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "spi_flash_private.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/spi_timing_config.h"
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Common settings
|
||||
*----------------------------------------------------------------------------*/
|
||||
void spi_timing_set_pin_drive_strength(void)
|
||||
{
|
||||
//For now, set them all to 3. Need to check after QVL test results are out. TODO: IDF-3663
|
||||
//Set default clk
|
||||
SET_PERI_REG_MASK(SPI_MEM_DATE_REG(0), SPI_MEM_SPICLK_PAD_DRV_CTL_EN);
|
||||
REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3);
|
||||
REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3);
|
||||
//Set default mspi d0 ~ d7, dqs pin drive strength
|
||||
uint32_t regs[] = {IO_MUX_GPIO27_REG, IO_MUX_GPIO28_REG,
|
||||
IO_MUX_GPIO31_REG, IO_MUX_GPIO32_REG,
|
||||
IO_MUX_GPIO33_REG, IO_MUX_GPIO34_REG,
|
||||
IO_MUX_GPIO35_REG, IO_MUX_GPIO36_REG,
|
||||
IO_MUX_GPIO37_REG};
|
||||
for (int i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
PIN_SET_DRV(regs[i], 3);
|
||||
}
|
||||
}
|
||||
|
||||
#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
static spi_timing_tuning_param_t s_flash_best_timing_tuning_config;
|
||||
static spi_timing_tuning_param_t s_psram_best_timing_tuning_config;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Static functions to get clock configs
|
||||
*----------------------------------------------------------------------------*/
|
||||
static spi_timing_config_core_clock_t get_mspi_core_clock(void)
|
||||
{
|
||||
return spi_timing_config_get_core_clock();
|
||||
@@ -52,7 +80,9 @@ static uint32_t get_psram_clock_divider(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
/*------------------------------------------------------------------------------
|
||||
* Static functions to do timing tuning
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Set timing tuning regs, in order to get successful sample points
|
||||
*/
|
||||
@@ -134,7 +164,6 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u
|
||||
while (i < size) {
|
||||
if (array[i]) {
|
||||
match_num++;
|
||||
|
||||
} else {
|
||||
if (match_num > max) {
|
||||
max = match_num;
|
||||
@@ -149,7 +178,7 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u
|
||||
*out_end_index = match_num == size ? size : end;
|
||||
}
|
||||
|
||||
static void select_best_tuning_config(spi_timing_config_t *config, uint32_t length, uint32_t end, bool is_flash)
|
||||
static void select_best_tuning_config(spi_timing_config_t *config, uint32_t consecutive_length, uint32_t end, bool is_flash)
|
||||
{
|
||||
uint32_t best_point;
|
||||
if (length >= 3) {
|
||||
@@ -185,7 +214,9 @@ static void do_tuning(uint8_t *reference_data, spi_timing_config_t *timing_confi
|
||||
#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
|
||||
|
||||
//------------------------------------------FLASH Timing Tuning----------------------------------------//
|
||||
/*------------------------------------------------------------------------------
|
||||
* FLASH Timing Tuning
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if SPI_TIMING_FLASH_NEEDS_TUNING
|
||||
static void get_flash_tuning_configs(spi_timing_config_t *config)
|
||||
{
|
||||
@@ -210,6 +241,7 @@ static void get_flash_tuning_configs(spi_timing_config_t *config)
|
||||
|
||||
void spi_timing_flash_tuning(void)
|
||||
{
|
||||
ESP_EARLY_LOGW("FLASH", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version.");
|
||||
/**
|
||||
* set SPI01 related regs to 20mhz configuration, to get reference data from FLASH
|
||||
* see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode)
|
||||
@@ -235,7 +267,9 @@ void spi_timing_flash_tuning(void)
|
||||
#endif //SPI_TIMING_FLASH_NEEDS_TUNING
|
||||
|
||||
|
||||
//------------------------------------------PSRAM Timing Tuning----------------------------------------//
|
||||
/*------------------------------------------------------------------------------
|
||||
* PSRAM Timing Tuning
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
static void get_psram_tuning_configs(spi_timing_config_t *config)
|
||||
{
|
||||
@@ -256,6 +290,7 @@ static void get_psram_tuning_configs(spi_timing_config_t *config)
|
||||
|
||||
void spi_timing_psram_tuning(void)
|
||||
{
|
||||
ESP_EARLY_LOGW("PSRAM", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version.");
|
||||
/**
|
||||
* set SPI01 related regs to 20mhz configuration, to write reference data to PSRAM
|
||||
* see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode)
|
||||
@@ -285,17 +320,21 @@ void spi_timing_psram_tuning(void)
|
||||
}
|
||||
#endif //SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
|
||||
|
||||
//---------------------------------------------APIs to make SPI0 and SPI1 FLASH work for high/low freq-------------------------------//
|
||||
/*------------------------------------------------------------------------------
|
||||
* APIs to make SPI0 and SPI1 FLASH work for high/low freq
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
static void clear_timing_tuning_regs(void)
|
||||
{
|
||||
spi_timing_config_flash_set_din_mode_num(0, 0, 0); //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg
|
||||
spi_timing_config_flash_set_extra_dummy(0, 0);
|
||||
spi_timing_config_flash_set_extra_dummy(1, 0);
|
||||
}
|
||||
#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
|
||||
void spi_timing_enter_mspi_low_speed_mode(void)
|
||||
{
|
||||
#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
/**
|
||||
* Here we are going to slow the SPI1 frequency to 20Mhz, so we need to set SPI1 din_num and din_mode regs.
|
||||
*
|
||||
@@ -311,8 +350,12 @@ void spi_timing_enter_mspi_low_speed_mode(void)
|
||||
spi_timing_config_set_flash_clock(0, 4);
|
||||
|
||||
clear_timing_tuning_regs();
|
||||
#else
|
||||
//Empty function for compatibility, therefore upper layer won't need to know that FLASH in which operation mode and frequency config needs to be tuned
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
static void set_timing_tuning_regs_as_required(void)
|
||||
{
|
||||
//SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg
|
||||
@@ -323,6 +366,7 @@ static void set_timing_tuning_regs_as_required(void)
|
||||
spi_timing_config_psram_set_din_mode_num(0, s_psram_best_timing_tuning_config.spi_din_mode, s_psram_best_timing_tuning_config.spi_din_num);
|
||||
spi_timing_config_psram_set_extra_dummy(0, s_psram_best_timing_tuning_config.extra_dummy_len);
|
||||
}
|
||||
#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
|
||||
/**
|
||||
* Set SPI0 and SPI1 flash module clock, din_num, din_mode and extra dummy,
|
||||
@@ -332,6 +376,7 @@ static void set_timing_tuning_regs_as_required(void)
|
||||
*/
|
||||
void spi_timing_enter_mspi_high_speed_mode(void)
|
||||
{
|
||||
#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
spi_timing_config_core_clock_t core_clock = get_mspi_core_clock();
|
||||
uint32_t flash_div = get_flash_clock_divider();
|
||||
uint32_t psram_div = get_psram_clock_divider();
|
||||
@@ -345,4 +390,7 @@ void spi_timing_enter_mspi_high_speed_mode(void)
|
||||
spi_timing_config_set_psram_clock(0, psram_div);
|
||||
|
||||
set_timing_tuning_regs_as_required();
|
||||
#else
|
||||
//Empty function for compatibility, therefore upper layer won't need to know that FLASH in which operation mode and frequency config needs to be tuned
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user