2021-04-15 09:13:48 +00:00
/*
* SPDX - FileCopyrightText : 2019 - 2021 Espressif Systems ( Shanghai ) CO LTD
*
* SPDX - License - Identifier : Apache - 2.0
*/
# pragma once
# include "esp_flash_partitions.h"
# include "esp32s3/rom/spi_flash.h"
# include "esp32s3/rom/opi_flash.h"
2021-03-19 07:54:30 +00:00
# include "mspi_timing_tuning_configs.h"
2022-10-13 04:01:27 +00:00
# include "esp_assert.h"
2021-04-15 09:13:48 +00:00
# ifdef __cplusplus
extern " C " {
# endif
# define SPI_TIMING_CONFIG_NUM_DEFAULT 20 //This should be larger than the max available timing config num
# define SPI_TIMING_TEST_DATA_LEN 64
# define SPI_TIMING_PSRAM_TEST_DATA_ADDR 0
# define SPI_TIMING_FLASH_TEST_DATA_ADDR ESP_BOOTLOADER_OFFSET
2021-08-13 03:30:54 +00:00
/**
* @ note BACKGOURND :
*
* The SPI FLASH module clock and SPI PSRAM module clock is divided from the SPI core clock , core clock is from system clock :
*
* PLL - - - - | | - - - - FLASH Module Clock
* XTAL - - - - | - - - - > Core Clock - - - - > |
* RTC8M - - - - | | - - - - PSRAM Module Clock
*
*
* DDR stands for double data rate , MSPI samples at both posedge and negedge . So the real spped will be doubled .
* Speed from high to low : 120 M DDR > 80 M DDR > 120 SDR > 80 M SDR > . . .
*
* Module with speed lower than 120 M SDR doesn ' t need to be tuned
*
* @ note LIMITATION :
* How to determine the core clock on 728. There are 2 limitations .
*
* 1. MSPI FLASH and PSRAM share the core clock register . Therefore :
* SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ = = SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ
*
* 2. DDR mode requires the core clock divider ( core_clk / div = module_clk ) to be power of 2.
*/
//--------------------------------------FLASH Sampling Mode --------------------------------------//
2021-09-09 07:34:42 +00:00
# define SPI_TIMING_FLASH_DTR_MODE CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
# define SPI_TIMING_FLASH_STR_MODE CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
2021-08-13 03:30:54 +00:00
//--------------------------------------FLASH Module Clock --------------------------------------//
# if CONFIG_ESPTOOLPY_FLASHFREQ_20M
# define SPI_TIMING_FLASH_MODULE_CLOCK 20
# elif CONFIG_ESPTOOLPY_FLASHFREQ_40M
# define SPI_TIMING_FLASH_MODULE_CLOCK 40
# elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
# define SPI_TIMING_FLASH_MODULE_CLOCK 80
# else //CONFIG_ESPTOOLPY_FLASHFREQ_120M
# define SPI_TIMING_FLASH_MODULE_CLOCK 120
# endif
//------------------------------------FLASH Needs Tuning or not-------------------------------------//
# if SPI_TIMING_FLASH_DTR_MODE
# define SPI_TIMING_FLASH_NEEDS_TUNING (SPI_TIMING_FLASH_MODULE_CLOCK > 40)
# elif SPI_TIMING_FLASH_STR_MODE
# define SPI_TIMING_FLASH_NEEDS_TUNING (SPI_TIMING_FLASH_MODULE_CLOCK > 80)
# endif
//--------------------------------------PSRAM Sampling Mode --------------------------------------//
# define SPI_TIMING_PSRAM_DTR_MODE CONFIG_SPIRAM_MODE_OCT
# define SPI_TIMING_PSRAM_STR_MODE !CONFIG_SPIRAM_MODE_OCT
//--------------------------------------PSRAM Module Clock --------------------------------------//
# if CONFIG_ESP32S3_SPIRAM_SUPPORT
# if CONFIG_SPIRAM_SPEED_40M
# define SPI_TIMING_PSRAM_MODULE_CLOCK 40
# elif CONFIG_SPIRAM_SPEED_80M
# define SPI_TIMING_PSRAM_MODULE_CLOCK 80
# else //CONFIG_SPIRAM_SPEED_120M
# define SPI_TIMING_PSRAM_MODULE_CLOCK 120
# endif
# else //Disable PSRAM
# define SPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz, because we rely on `SPI_TIMING_PSRAM_MODULE_CLOCK` macro for calculation and check below, see `Determine the Core Clock` chapter
# endif
//------------------------------------PSRAM Needs Tuning or not-------------------------------------//
# if SPI_TIMING_PSRAM_DTR_MODE
# define SPI_TIMING_PSRAM_NEEDS_TUNING (SPI_TIMING_PSRAM_MODULE_CLOCK > 40)
# elif SPI_TIMING_PSRAM_STR_MODE
# define SPI_TIMING_PSRAM_NEEDS_TUNING (SPI_TIMING_PSRAM_MODULE_CLOCK > 80)
# endif
2021-04-15 09:13:48 +00:00
2021-08-13 03:30:54 +00:00
/**
* @ note Define A feasible core clock below : SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ and SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ
*/
/**
* Due to MSPI core clock is used by both MSPI Flash and PSRAM clock ,
* define the STR / DTR mode here for selecting the core clock :
* @ note If either Flash or PSRAM , or both of them are set to DTR mode , then we use DIV 2
*/
# if (SPI_TIMING_FLASH_DTR_MODE || SPI_TIMING_PSRAM_DTR_MODE)
# define SPI_TIMING_CORE_CLOCK_DIV 2
# else //#if (SPI_TIMING_FLASH_STR_MODE && (SPI_TIMING_PSRAM_STR_MODE || !CONFIG_ESP32S3_SPIRAM_SUPPORT))
# define SPI_TIMING_CORE_CLOCK_DIV 1
# endif
2021-04-15 09:13:48 +00:00
2021-08-13 03:30:54 +00:00
///////////////////////////////////// FLASH CORE CLOCK /////////////////////////////////////
//FLASH 80M DTR
2021-04-15 09:13:48 +00:00
# if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M
2021-08-13 03:30:54 +00:00
# define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160
2021-04-15 09:13:48 +00:00
# endif
2021-08-13 03:30:54 +00:00
//FLASH 120M DTR
2021-04-15 09:13:48 +00:00
# if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M
2021-08-13 03:30:54 +00:00
# define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240
2021-04-15 09:13:48 +00:00
# endif
2021-08-13 03:30:54 +00:00
//FLASH 120M STR
2021-04-15 09:13:48 +00:00
# if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M
2021-08-13 03:30:54 +00:00
# if (SPI_TIMING_CORE_CLOCK_DIV == 2)
# define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240
# elif (SPI_TIMING_CORE_CLOCK_DIV == 1)
# define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 120
2021-04-15 09:13:48 +00:00
# endif
2021-08-13 03:30:54 +00:00
# endif //FLASH 120M STR
2021-04-15 09:13:48 +00:00
2021-08-13 03:30:54 +00:00
///////////////////////////////////// PSRAM CORE CLOCK /////////////////////////////////////
//PSRAM 80M DTR
2021-04-15 09:13:48 +00:00
# if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_80M
2021-08-13 03:30:54 +00:00
# define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 160
2021-04-15 09:13:48 +00:00
# endif
2021-08-13 03:30:54 +00:00
//PSRAM 120M STR
# if SPI_TIMING_PSRAM_STR_MODE && CONFIG_SPIRAM_SPEED_120M
# if (SPI_TIMING_CORE_CLOCK_DIV == 2)
# define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 240
# elif (SPI_TIMING_CORE_CLOCK_DIV == 1)
# define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 120
2021-04-15 09:13:48 +00:00
# endif
2021-08-13 03:30:54 +00:00
# endif //PSRAM 120M STR
2021-04-15 09:13:48 +00:00
2021-08-13 03:30:54 +00:00
//------------------------------------------Determine the Core Clock-----------------------------------------------//
/**
* @ note
* Limitation 1 :
* On 728 , MSPI FLASH and PSRAM share the core clock register . Therefore ,
* the expected CORE CLOCK frequencies should be the same .
*/
2021-04-15 09:13:48 +00:00
# if SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING
2022-10-13 04:01:27 +00:00
ESP_STATIC_ASSERT ( SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ = = SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ , " FLASH and PSRAM Mode configuration are not supported " ) ;
2021-08-13 03:30:54 +00:00
# define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ
2021-04-15 09:13:48 +00:00
2021-08-13 03:30:54 +00:00
//If only FLASH needs tuning, the core clock COULD be as FLASH expected
2021-04-15 09:13:48 +00:00
# elif SPI_TIMING_FLASH_NEEDS_TUNING && !SPI_TIMING_PSRAM_NEEDS_TUNING
2022-10-13 04:01:27 +00:00
ESP_STATIC_ASSERT ( SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ % SPI_TIMING_PSRAM_MODULE_CLOCK = = 0 , " FLASH and PSRAM Mode configuration are not supported " ) ;
2021-08-13 03:30:54 +00:00
# define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ
2021-04-15 09:13:48 +00:00
2021-08-13 03:30:54 +00:00
//If only PSRAM needs tuning, the core clock COULD be as PSRAM expected
2021-04-15 09:13:48 +00:00
# elif !SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING
2022-10-13 04:01:27 +00:00
ESP_STATIC_ASSERT ( SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ % SPI_TIMING_FLASH_MODULE_CLOCK = = 0 , " FLASH and PSRAM Mode configuration are not supported " ) ;
2021-08-13 03:30:54 +00:00
# define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ
2021-04-15 09:13:48 +00:00
# else
# define SPI_TIMING_CORE_CLOCK_MHZ 80
# endif
2021-08-13 03:30:54 +00:00
/**
* @ note
* Limitation 2 : DDR mode requires the core clock divider ( core_clk / div = module_clk ) to be power of 2.
*/
# define CHECK_POWER_OF_2(n) ((((n) & ((~(n)) + 1))) == (n))
# if SPI_TIMING_FLASH_DTR_MODE
2022-10-13 04:01:27 +00:00
ESP_STATIC_ASSERT ( CHECK_POWER_OF_2 ( SPI_TIMING_CORE_CLOCK_MHZ / SPI_TIMING_FLASH_MODULE_CLOCK ) , " FLASH and PSRAM Mode configuration are not supported " ) ;
2021-08-13 03:30:54 +00:00
# endif
# if SPI_TIMING_PSRAM_DTR_MODE
2022-10-13 04:01:27 +00:00
ESP_STATIC_ASSERT ( CHECK_POWER_OF_2 ( SPI_TIMING_CORE_CLOCK_MHZ / SPI_TIMING_PSRAM_MODULE_CLOCK ) , " FLASH and PSRAM Mode configuration are not supported " ) ;
2021-08-13 03:30:54 +00:00
# endif
2021-04-15 09:13:48 +00:00
//------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------//
# define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \
( spi_timing_config_t ) { . tuning_config_table = MSPI_TIMING_ # # type # # _CONFIG_TABLE_CORE_CLK_ # # core_clock # # M_MODULE_CLK_ # # module_clock # # M_ # # mode , \
. available_config_num = MSPI_TIMING_ # # type # # _CONFIG_NUM_CORE_CLK_ # # core_clock # # M_MODULE_CLK_ # # module_clock # # M_ # # mode , \
. default_config_id = MSPI_TIMING_ # # type # # _DEFAULT_CONFIG_ID_CORE_CLK_ # # core_clock # # M_MODULE_CLK_ # # module_clock # # M_ # # mode }
# define _GET_TUNING_CONFIG(type, core_clock, module_clock, mode) __GET_TUNING_CONFIG(type, core_clock, module_clock, mode)
# define SPI_TIMING_FLASH_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(FLASH, core_clock_mhz, module_clock_mhz, mode)
# define SPI_TIMING_PSRAM_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(PSRAM, core_clock_mhz, module_clock_mhz, mode)
/**
* SPI timing tuning registers . The macro ` SPI_TIMING_FLASH_CONFIG_TABLE ` below is the corresponding register value table .
* 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*/
} spi_timing_tuning_param_t ;
typedef struct {
spi_timing_tuning_param_t tuning_config_table [ SPI_TIMING_CONFIG_NUM_DEFAULT ] ; //available timing tuning configs
uint32_t available_config_num ;
uint32_t default_config_id ; //If tuning fails, we use this one as default
} spi_timing_config_t ;
/**
* The SPI FLASH module clock and SPI PSRAM module clock is divided from the SPI core clock , core clock is from system clock :
*
* PLL - - - - | | - - - - FLASH Module Clock
* XTAL - - - - | - - - - > Core Clock - - - - > |
* RTC8M - - - - | | - - - - PSRAM Module Clock
*
*/
typedef enum {
SPI_TIMING_CONFIG_CORE_CLOCK_80M ,
SPI_TIMING_CONFIG_CORE_CLOCK_120M ,
SPI_TIMING_CONFIG_CORE_CLOCK_160M ,
SPI_TIMING_CONFIG_CORE_CLOCK_240M
} spi_timing_config_core_clock_t ;
spi_timing_config_core_clock_t spi_timing_config_get_core_clock ( void ) ;
void spi_timing_config_set_core_clock ( uint8_t spi_num , spi_timing_config_core_clock_t core_clock ) ;
void spi_timing_config_set_flash_clock ( uint8_t spi_num , uint32_t freqdiv ) ;
void spi_timing_config_flash_set_din_mode_num ( uint8_t spi_num , uint8_t din_mode , uint8_t din_num ) ;
void spi_timing_config_flash_set_extra_dummy ( uint8_t spi_num , uint8_t extra_dummy ) ;
void spi_timing_config_flash_read_data ( uint8_t spi_num , uint8_t * buf , uint32_t addr , uint32_t len ) ;
void spi_timing_config_set_psram_clock ( uint8_t spi_num , uint32_t freqdiv ) ;
void spi_timing_config_psram_set_din_mode_num ( uint8_t spi_num , uint8_t din_mode , uint8_t din_num ) ;
void spi_timing_config_psram_set_extra_dummy ( uint8_t spi_num , uint8_t extra_dummy ) ;
void spi_timing_config_psram_write_data ( uint8_t spi_num , uint8_t * buf , uint32_t addr , uint32_t len ) ;
void spi_timing_config_psram_read_data ( uint8_t spi_num , uint8_t * buf , uint32_t addr , uint32_t len ) ;
2021-08-13 03:30:54 +00:00
/*-------------------------------------------------------------------------------------------------
* SPI1 Timing Tuning APIs
* These APIs are only used in ` spi_flash_timing_tuning . c / sweep_for_success_sample_points ( ) ` for
* configuring SPI1 timing tuning related registers to find best tuning parameter
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void spi_timing_config_flash_tune_din_num_mode ( uint8_t din_mode , uint8_t din_num ) ;
void spi_timing_config_flash_tune_dummy ( uint8_t extra_dummy ) ;
void spi_timing_config_psram_tune_din_num_mode ( uint8_t din_mode , uint8_t din_num ) ;
void spi_timing_config_psram_tune_dummy ( uint8_t extra_dummy ) ;
2021-09-01 07:58:15 +00:00
/**
* SPI1 register info get APIs . These APIs inform ` spi_flash_timing_tuning . c ` ( driver layer ) of the SPI1 flash settings .
2021-10-19 04:25:08 +00:00
* In this way , other components ( e . g . : esp_flash driver ) can get the info from it ( ` spi_flash_timing_tuning . c ` ) .
2021-09-01 07:58:15 +00:00
*/
void spi_timing_config_get_cs_timing ( uint8_t * setup_time , uint32_t * hold_time ) ;
uint32_t spi_timing_config_get_flash_clock_reg ( void ) ;
2021-04-15 09:13:48 +00:00
# ifdef __cplusplus
}
# endif