From b46cfd15a2ff483c01d84b9504336a513215f97d Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 5 Jan 2023 15:24:08 +0800 Subject: [PATCH] mspi: move timing tuning to esp_hw_support --- components/esp_hw_support/CMakeLists.txt | 5 ++ .../include/esp_private/mspi_timing_tuning.h | 60 +++++++++++++++++++ components/esp_hw_support/linker.lf | 3 + .../mspi_timing_tuning.c} | 39 ++++++------ .../port/esp32s3/mspi_timing_config.c} | 3 +- .../port/esp32s3/mspi_timing_config.h} | 0 .../esp32s3/mspi_timing_tuning_configs.h | 0 .../esp_hw_support/port/esp32s3/rtc_init.c | 7 ++- .../esp_psram/esp32s3/esp_psram_impl_octal.c | 7 ++- .../esp_psram/esp32s3/esp_psram_impl_quad.c | 9 +-- components/esp_system/port/cpu_start.c | 6 +- components/spi_flash/CMakeLists.txt | 2 - components/spi_flash/flash_ops.c | 4 +- .../include/esp_private/spi_flash_os.h | 41 ------------- components/spi_flash/linker.lf | 2 - 15 files changed, 107 insertions(+), 81 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/mspi_timing_tuning.h rename components/{spi_flash/spi_flash_timing_tuning.c => esp_hw_support/mspi_timing_tuning.c} (94%) rename components/{spi_flash/esp32s3/spi_timing_config.c => esp_hw_support/port/esp32s3/mspi_timing_config.c} (99%) rename components/{spi_flash/esp32s3/spi_timing_config.h => esp_hw_support/port/esp32s3/mspi_timing_config.h} (100%) rename components/{spi_flash => esp_hw_support/port}/esp32s3/mspi_timing_tuning_configs.h (100%) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 18de838132..169baff466 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -74,6 +74,11 @@ if(NOT BOOTLOADER_BUILD) if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT) list(APPEND srcs "modem_clock.c") endif() + + if(CONFIG_SOC_MEMSPI_SRC_FREQ_120M) + list(APPEND srcs "mspi_timing_tuning.c" "port/${target}/mspi_timing_config.c") + endif() + if(CONFIG_IDF_TARGET_ESP32H2) list(REMOVE_ITEM srcs "adc_share_hw_ctrl.c" # TODO: IDF-6215 diff --git a/components/esp_hw_support/include/esp_private/mspi_timing_tuning.h b/components/esp_hw_support/include/esp_private/mspi_timing_tuning.h new file mode 100644 index 0000000000..c1e999cc18 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/mspi_timing_tuning.h @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief + * This file is for MSPI timinig tuning private APIs + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Make MSPI work under 20Mhz, remove the timing tuning required delays. + * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 + */ +void mspi_timing_enter_low_speed_mode(bool control_spi1); + +/** + * @brief Make MSPI work under the frequency as users set, may add certain delays to MSPI RX direction to meet timing requirements. + * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 + */ +void mspi_timing_enter_high_speed_mode(bool control_spi1); + +/** + * @brief Switch MSPI into low speed mode / high speed mode. + * @note This API is cache safe, it will freeze both D$ and I$ and restore them after MSPI is switched + * @note For some of the MSPI high frequency settings (e.g. 80M DDR mode Flash or PSRAM), timing tuning is required. + * Certain delays will be added to the MSPI RX direction. When CPU clock switches from PLL to XTAL, should call + * this API first to enter MSPI low speed mode to remove the delays, and vice versa. + */ +void mspi_timing_change_speed_mode_cache_safe(bool switch_down); + +/** + * @brief Tune MSPI flash timing to make it work under high frequency + */ +void mspi_timing_flash_tuning(void); + +/** + * @brief Tune MSPI psram timing to make it work under high frequency + */ +void mspi_timing_psram_tuning(void); + +/** + * @brief Set MSPI pin default pin drive + */ +void mspi_timing_set_pin_drive_strength(void); + + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 010bdb0197..1c1a0bf464 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -32,3 +32,6 @@ entries: gdma: gdma_reset (noflash) if SOC_SYSTIMER_SUPPORTED = y: systimer (noflash) + if SOC_MEMSPI_SRC_FREQ_120M = y: + mspi_timing_tuning (noflash) + mspi_timing_config (noflash) diff --git a/components/spi_flash/spi_flash_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning.c similarity index 94% rename from components/spi_flash/spi_flash_timing_tuning.c rename to components/esp_hw_support/mspi_timing_tuning.c index aa192433ae..c86e764f23 100644 --- a/components/spi_flash/spi_flash_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning.c @@ -13,10 +13,11 @@ #include "esp_log.h" #include "soc/spi_mem_reg.h" #include "soc/io_mux_reg.h" -#include "esp_private/spi_flash_os.h" +#include "esp_private/mspi_timing_tuning.h" #include "soc/soc.h" +#include "hal/spi_flash_hal.h" #if CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/spi_timing_config.h" +#include "port/esp32s3/mspi_timing_config.h" #include "esp32s3/rom/cache.h" #endif @@ -31,7 +32,7 @@ static spi_timing_tuning_param_t s_psram_best_timing_tuning_config; /*------------------------------------------------------------------------------ * Common settings *----------------------------------------------------------------------------*/ -void spi_timing_set_pin_drive_strength(void) +void mspi_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 @@ -297,13 +298,13 @@ static void get_flash_tuning_configs(spi_timing_config_t *config) #undef FLASH_MODE } -void spi_timing_flash_tuning(void) +void mspi_timing_flash_tuning(void) { /** * 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`) + * see detailed comments in this function (`mspi_timing_enter_low_speed_mode`) */ - spi_timing_enter_mspi_low_speed_mode(true); + mspi_timing_enter_low_speed_mode(true); //Disable the variable dummy mode when doing timing tuning CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); //GD flash will read error in variable mode with 20MHz @@ -314,10 +315,10 @@ void spi_timing_flash_tuning(void) get_flash_tuning_configs(&timing_configs); do_tuning(reference_data, &timing_configs, true); - spi_timing_enter_mspi_high_speed_mode(true); + mspi_timing_enter_high_speed_mode(true); } #else -void spi_timing_flash_tuning(void) +void mspi_timing_flash_tuning(void) { //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 } @@ -347,13 +348,13 @@ static void get_psram_tuning_configs(spi_timing_config_t *config) #undef PSRAM_MODE } -void spi_timing_psram_tuning(void) +void mspi_timing_psram_tuning(void) { /** * 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`) + * see detailed comments in this function (`mspi_timing_enter_low_speed_mode`) */ - spi_timing_enter_mspi_low_speed_mode(true); + mspi_timing_enter_low_speed_mode(true); // write data into psram, used to do timing tuning test. uint8_t reference_data[SPI_TIMING_TEST_DATA_LEN]; @@ -368,11 +369,11 @@ void spi_timing_psram_tuning(void) CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); //Get required config, and set them to PSRAM related registers do_tuning(reference_data, &timing_configs, false); - spi_timing_enter_mspi_high_speed_mode(true); + mspi_timing_enter_high_speed_mode(true); } #else -void spi_timing_psram_tuning(void) +void mspi_timing_psram_tuning(void) { //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 } @@ -398,7 +399,7 @@ static void clear_timing_tuning_regs(bool control_spi1) } #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -void spi_timing_enter_mspi_low_speed_mode(bool control_spi1) +void mspi_timing_enter_low_speed_mode(bool control_spi1) { /** * Here we are going to slow the SPI1 frequency to 20Mhz, so we need to set SPI1 din_num and din_mode regs. @@ -445,9 +446,9 @@ static void set_timing_tuning_regs_as_required(bool control_spi1) * according to the configuration got from timing tuning function (`calculate_best_flash_tuning_config`). * iF control_spi1 == 1, will also update SPI1 timing registers. Should only be set to 1 when do tuning. * - * This function should always be called after `spi_timing_flash_tuning` or `calculate_best_flash_tuning_config` + * This function should always be called after `mspi_timing_flash_tuning` or `calculate_best_flash_tuning_config` */ -void spi_timing_enter_mspi_high_speed_mode(bool control_spi1) +void mspi_timing_enter_high_speed_mode(bool control_spi1) { spi_timing_config_core_clock_t core_clock = get_mspi_core_clock(); uint32_t flash_div = get_flash_clock_divider(); @@ -468,16 +469,16 @@ void spi_timing_enter_mspi_high_speed_mode(bool control_spi1) #endif } -void spi_timing_change_speed_mode_cache_safe(bool switch_down) +void mspi_timing_change_speed_mode_cache_safe(bool switch_down) { Cache_Freeze_ICache_Enable(1); Cache_Freeze_DCache_Enable(1); if (switch_down) { //enter MSPI low speed mode, extra delays should be removed - spi_timing_enter_mspi_low_speed_mode(false); + mspi_timing_enter_low_speed_mode(false); } else { //enter MSPI high speed mode, extra delays should be considered - spi_timing_enter_mspi_high_speed_mode(false); + mspi_timing_enter_high_speed_mode(false); } Cache_Freeze_DCache_Disable(); Cache_Freeze_ICache_Disable(); diff --git a/components/spi_flash/esp32s3/spi_timing_config.c b/components/esp_hw_support/port/esp32s3/mspi_timing_config.c similarity index 99% rename from components/spi_flash/esp32s3/spi_timing_config.c rename to components/esp_hw_support/port/esp32s3/mspi_timing_config.c index cdab930410..f48a868a78 100644 --- a/components/spi_flash/esp32s3/spi_timing_config.c +++ b/components/esp_hw_support/port/esp32s3/mspi_timing_config.c @@ -12,8 +12,7 @@ #include "esp_types.h" #include "esp_log.h" #include "soc/spi_mem_reg.h" -#include "spi_timing_config.h" -#include "esp_private/spi_flash_os.h" +#include "mspi_timing_config.h" #include "bootloader_flash.h" #define OPI_PSRAM_SYNC_READ 0x0000 diff --git a/components/spi_flash/esp32s3/spi_timing_config.h b/components/esp_hw_support/port/esp32s3/mspi_timing_config.h similarity index 100% rename from components/spi_flash/esp32s3/spi_timing_config.h rename to components/esp_hw_support/port/esp32s3/mspi_timing_config.h diff --git a/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h b/components/esp_hw_support/port/esp32s3/mspi_timing_tuning_configs.h similarity index 100% rename from components/spi_flash/esp32s3/mspi_timing_tuning_configs.h rename to components/esp_hw_support/port/esp32s3/mspi_timing_tuning_configs.h diff --git a/components/esp_hw_support/port/esp32s3/rtc_init.c b/components/esp_hw_support/port/esp32s3/rtc_init.c index 0840dcec95..18b7abd5a5 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_init.c +++ b/components/esp_hw_support/port/esp32s3/rtc_init.c @@ -5,6 +5,7 @@ */ #include +#include #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" @@ -21,7 +22,7 @@ #include "esp_hw_log.h" #include "esp_err.h" #include "esp_attr.h" -#include "esp_private/spi_flash_os.h" +#include "esp_private/mspi_timing_tuning.h" #include "hal/efuse_hal.h" #include "hal/efuse_ll.h" #ifndef BOOTLOADER_BUILD @@ -260,7 +261,7 @@ static void calibrate_ocode(void) * * When CPU clock switches down, the delay should be cleared. Therefore here we call this function to remove the delays. */ - spi_timing_change_speed_mode_cache_safe(true); + mspi_timing_change_speed_mode_cache_safe(true); #endif /* Bandgap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration (must turn off PLL). @@ -309,7 +310,7 @@ static void calibrate_ocode(void) rtc_clk_cpu_freq_set_config(&old_config); #ifndef BOOTLOADER_BUILD //System clock is switched back to PLL. Here we switch to the MSPI high speed mode, add the delays back - spi_timing_change_speed_mode_cache_safe(false); + mspi_timing_change_speed_mode_cache_safe(false); #endif } diff --git a/components/esp_psram/esp32s3/esp_psram_impl_octal.c b/components/esp_psram/esp32s3/esp_psram_impl_octal.c index ab472ddda9..6aa5f4ae1e 100644 --- a/components/esp_psram/esp32s3/esp_psram_impl_octal.c +++ b/components/esp_psram/esp32s3/esp_psram_impl_octal.c @@ -19,6 +19,7 @@ #include "soc/io_mux_reg.h" #include "soc/syscon_reg.h" #include "esp_private/spi_flash_os.h" +#include "esp_private/mspi_timing_tuning.h" #define OPI_PSRAM_SYNC_READ 0x0000 #define OPI_PSRAM_SYNC_WRITE 0x8080 @@ -295,7 +296,7 @@ esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode) s_configure_psram_ecc(); //enter MSPI slow mode to init PSRAM device registers - spi_timing_enter_mspi_low_speed_mode(true); + mspi_timing_enter_low_speed_mode(true); //set to variable dummy mode SET_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); @@ -322,9 +323,9 @@ esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode) mode_reg.mr2.density == 0x7 ? PSRAM_SIZE_32MB : 0; //Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly - spi_timing_psram_tuning(); + mspi_timing_psram_tuning(); //Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly - spi_timing_enter_mspi_high_speed_mode(true); + mspi_timing_enter_high_speed_mode(true); /** * Tuning may change SPI1 regs, whereas legacy spi_flash APIs rely on these regs. diff --git a/components/esp_psram/esp32s3/esp_psram_impl_quad.c b/components/esp_psram/esp32s3/esp_psram_impl_quad.c index 2b6416188d..626f1bfa4f 100644 --- a/components/esp_psram/esp32s3/esp_psram_impl_quad.c +++ b/components/esp_psram/esp32s3/esp_psram_impl_quad.c @@ -18,6 +18,7 @@ #include "esp_rom_efuse.h" #include "hal/gpio_hal.h" #include "esp_private/spi_flash_os.h" +#include "esp_private/mspi_timing_tuning.h" static const char* TAG = "quad_psram"; @@ -303,7 +304,7 @@ esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode) //psram init psram_set_cs_timing(); //enter MSPI slow mode to init PSRAM device registers - spi_timing_enter_mspi_low_speed_mode(true); + mspi_timing_enter_low_speed_mode(true); //We use SPI1 to init PSRAM psram_disable_qio_mode(SPI1_NUM); @@ -335,12 +336,12 @@ esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode) //psram init psram_enable_qio_mode(SPI1_NUM); //Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly - spi_timing_psram_tuning(); + mspi_timing_psram_tuning(); //Configure SPI0 PSRAM related SPI Phases config_psram_spi_phases(); //Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly - spi_timing_enter_mspi_high_speed_mode(true); + mspi_timing_enter_high_speed_mode(true); return ESP_OK; } @@ -364,7 +365,7 @@ static void config_psram_spi_phases(void) //Dummy /** * We set the PSRAM chip required dummy here. If timing tuning is needed, - * the dummy length will be updated in `spi_timing_enter_mspi_high_speed_mode()` + * the dummy length will be updated in `mspi_timing_enter_high_speed_mode()` */ SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_RD_SRAM_DUMMY_M); //enable cache read dummy SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_RDUMMY_CYCLELEN_V, (PSRAM_FAST_READ_QUAD_DUMMY - 1), SPI_MEM_SRAM_RDUMMY_CYCLELEN_S); //dummy diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index baee8e7190..ca11a60508 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -74,6 +74,7 @@ #endif #include "esp_private/spi_flash_os.h" +#include "esp_private/mspi_timing_tuning.h" #include "bootloader_flash_config.h" #include "bootloader_flash.h" #include "esp_private/crosscore_int.h" @@ -386,9 +387,8 @@ void IRAM_ATTR call_start_cpu0(void) * In this stage, we re-configure the Flash (and MSPI) to required configuration */ spi_flash_init_chip_state(); -#if CONFIG_IDF_TARGET_ESP32S3 - //On other chips, this feature is not provided by HW, or hasn't been tested yet. - spi_timing_flash_tuning(); +#if SOC_MEMSPI_SRC_FREQ_120M + mspi_timing_flash_tuning(); #endif bootloader_init_mem(); diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index 86860417bd..08129892d3 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/components/spi_flash/CMakeLists.txt @@ -22,8 +22,6 @@ else() if(CONFIG_IDF_TARGET_ESP32S3) list(APPEND srcs - "esp32s3/spi_timing_config.c" - "spi_flash_timing_tuning.c" "spi_flash_hpm_enable.c") endif() diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 5355c2b6d5..d7319b5243 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -45,6 +45,7 @@ #endif #include "esp_rom_spiflash.h" #include "esp_flash_partitions.h" +#include "esp_private/mspi_timing_tuning.h" #include "esp_private/cache_utils.h" #include "esp_flash.h" #include "esp_attr.h" @@ -163,8 +164,7 @@ void IRAM_ATTR esp_mspi_pin_init(void) if (octal_mspi_required) { esp_rom_opiflash_pin_config(); - extern void spi_timing_set_pin_drive_strength(void); - spi_timing_set_pin_drive_strength(); + mspi_timing_set_pin_drive_strength(); } //Set F4R4 board pin drive strength. TODO: IDF-3663 #endif diff --git a/components/spi_flash/include/esp_private/spi_flash_os.h b/components/spi_flash/include/esp_private/spi_flash_os.h index 34f9189ed3..55c906b9ad 100644 --- a/components/spi_flash/include/esp_private/spi_flash_os.h +++ b/components/spi_flash/include/esp_private/spi_flash_os.h @@ -7,16 +7,6 @@ /** * System level MSPI APIs (private) */ -/** - * Currently the MSPI timing tuning related APIs are designed to be private. - * Because: - * 1. now we don't split SPI0 and SPI1, we don't have a component for SPI0, including PSRAM, Cache, etc.. - * 2. SPI0 and SPI1 are strongly coupling. - * - * In the future, we may consider creating a component for SPI0, and spi_flash component will only work on SPI1 (and it - * can rely on SPI0). Therefore, we can put these APIs there. - * - */ #pragma once #include @@ -58,37 +48,6 @@ typedef enum { */ esp_err_t spi_flash_init_chip_state(void); -/** - * @brief Make MSPI work under 20Mhz, remove the timing tuning required delays. - * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 - */ -void spi_timing_enter_mspi_low_speed_mode(bool control_spi1); - -/** - * @brief Make MSPI work under the frequency as users set, may add certain delays to MSPI RX direction to meet timing requirements. - * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 - */ -void spi_timing_enter_mspi_high_speed_mode(bool control_spi1); - -/** - * @brief Switch MSPI into low speed mode / high speed mode. - * @note This API is cache safe, it will freeze both D$ and I$ and restore them after MSPI is switched - * @note For some of the MSPI high frequency settings (e.g. 80M DDR mode Flash or PSRAM), timing tuning is required. - * Certain delays will be added to the MSPI RX direction. When CPU clock switches from PLL to XTAL, should call - * this API first to enter MSPI low speed mode to remove the delays, and vice versa. - */ -void spi_timing_change_speed_mode_cache_safe(bool switch_down); - -/** - * @brief Tune MSPI flash timing to make it work under high frequency - */ -void spi_timing_flash_tuning(void); - -/** - * @brief Tune MSPI psram timing to make it work under high frequency - */ -void spi_timing_psram_tuning(void); - /** * @brief To initislize the MSPI pins */ diff --git a/components/spi_flash/linker.lf b/components/spi_flash/linker.lf index c3687109b0..62130ab71a 100644 --- a/components/spi_flash/linker.lf +++ b/components/spi_flash/linker.lf @@ -12,8 +12,6 @@ entries: flash_brownout_hook (noflash) if IDF_TARGET_ESP32S3 = y: - spi_flash_timing_tuning (noflash) - spi_timing_config (noflash) spi_flash_chip_mxic_opi (noflash) spi_flash_hpm_enable (noflash)