Эх сурвалжийг харах

Merge branch 'refactor/move_mspi_timing_tuning_to_esp_hw_support' into 'master'

mspi: move timing tuning to esp_hw_support

Closes IDF-6470

See merge request espressif/esp-idf!21912
Armando (Dou Yiwen) 3 жил өмнө
parent
commit
30a535db18

+ 5 - 0
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

+ 60 - 0
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 <stdint.h>
+#include <stdbool.h>
+
+#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

+ 3 - 0
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)

+ 20 - 19
components/spi_flash/spi_flash_timing_tuning.c → 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();

+ 1 - 2
components/spi_flash/esp32s3/spi_timing_config.c → 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

+ 0 - 0
components/spi_flash/esp32s3/spi_timing_config.h → components/esp_hw_support/port/esp32s3/mspi_timing_config.h


+ 0 - 0
components/spi_flash/esp32s3/mspi_timing_tuning_configs.h → components/esp_hw_support/port/esp32s3/mspi_timing_tuning_configs.h


+ 4 - 3
components/esp_hw_support/port/esp32s3/rtc_init.c

@@ -5,6 +5,7 @@
  */
 
 #include <stdint.h>
+#include <sys/param.h>
 #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
 }
 

+ 4 - 3
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.

+ 5 - 4
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

+ 3 - 3
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();

+ 0 - 2
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()
 

+ 2 - 2
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

+ 0 - 41
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 <stdint.h>
@@ -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
  */

+ 0 - 2
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)