diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c index 78a53b4a6c..4101ef6ada 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c @@ -225,6 +225,12 @@ static void bootloader_spi_flash_resume(void) esp_err_t bootloader_init_spi_flash(void) { 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_flash_unlock(); diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 1e877313bd..5652bcf140 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -132,6 +132,9 @@ if(NOT non_os_build) if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS) list(APPEND srcs "mspi_timing_by_dqs.c") endif() + if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY) + list(APPEND srcs "mspi_timing_by_flash_delay.c") + endif() endif() if(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED AND CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB) diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index aaa5f1e280..f3848b85fc 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -42,6 +42,9 @@ entries: mspi_timing_config (noflash) if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y: 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) if SOC_ADC_SHARED_POWER = y: if ADC_ONESHOT_CTRL_FUNC_IN_IRAM = y: diff --git a/components/esp_hw_support/mspi_timing_by_dqs.c b/components/esp_hw_support/mspi_timing_by_dqs.c index 6b2be45283..988a82c434 100644 --- a/components/esp_hw_support/mspi_timing_by_dqs.c +++ b/components/esp_hw_support/mspi_timing_by_dqs.c @@ -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 -} diff --git a/components/esp_hw_support/mspi_timing_by_dqs.h b/components/esp_hw_support/mspi_timing_by_dqs.h index 45147c5be8..d895a15e3c 100644 --- a/components/esp_hw_support/mspi_timing_by_dqs.h +++ b/components/esp_hw_support/mspi_timing_by_dqs.h @@ -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 */ @@ -14,6 +14,7 @@ #include #include "soc/soc_caps.h" #if SOC_MEMSPI_TIMING_TUNING_BY_DQS +#include "mspi_timing_types.h" #include "mspi_timing_tuning_configs.h" #include "hal/mspi_timing_tuning_ll.h" #endif @@ -28,26 +29,6 @@ extern "C" { #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 *-------------------------------------------------------------------------------------------------*/ diff --git a/components/esp_hw_support/mspi_timing_by_flash_delay.c b/components/esp_hw_support/mspi_timing_by_flash_delay.c new file mode 100644 index 0000000000..2f66ecec6a --- /dev/null +++ b/components/esp_hw_support/mspi_timing_by_flash_delay.c @@ -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 +#include +#include +#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); +} diff --git a/components/esp_hw_support/mspi_timing_by_flash_delay.h b/components/esp_hw_support/mspi_timing_by_flash_delay.h new file mode 100644 index 0000000000..2457c7e857 --- /dev/null +++ b/components/esp_hw_support/mspi_timing_by_flash_delay.h @@ -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 +#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 diff --git a/components/esp_hw_support/mspi_timing_by_mspi_delay.c b/components/esp_hw_support/mspi_timing_by_mspi_delay.c index 19ca724b54..d1d903ad24 100644 --- a/components/esp_hw_support/mspi_timing_by_mspi_delay.c +++ b/components/esp_hw_support/mspi_timing_by_mspi_delay.c @@ -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); //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) @@ -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); //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) diff --git a/components/esp_hw_support/mspi_timing_by_mspi_delay.h b/components/esp_hw_support/mspi_timing_by_mspi_delay.h index 9e9e77029e..bb3e27d2af 100644 --- a/components/esp_hw_support/mspi_timing_by_mspi_delay.h +++ b/components/esp_hw_support/mspi_timing_by_mspi_delay.h @@ -14,6 +14,7 @@ #include #include "soc/soc_caps.h" #if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY +#include "mspi_timing_types.h" #include "mspi_timing_tuning_configs.h" #endif @@ -26,25 +27,6 @@ extern "C" { #define IS_DDR 1 #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 /*------------------------------------------------------------------------------------------------- diff --git a/components/esp_hw_support/mspi_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning.c index 5699b4837c..3374e2ab91 100644 --- a/components/esp_hw_support/mspi_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning.c @@ -20,7 +20,8 @@ #include "esp_private/mspi_timing_config.h" #include "mspi_timing_by_mspi_delay.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 "hal/mspi_timing_tuning_ll.h" #endif @@ -343,7 +344,7 @@ void mspi_timing_flash_tuning(void) */ 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 = { .flash_tuning_type = MSPI_TIMING_TUNING_MSPI_DIN_DUMMY, .sweep_test_nums = 1, @@ -365,7 +366,7 @@ void mspi_timing_flash_tuning(void) mspi_timing_config_t timing_configs = {0}; 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); @@ -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(); +#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. mspi_timing_config_get_cs_timing(&out_timing_config->cs_setup, &out_timing_config->cs_hold); } diff --git a/components/esp_hw_support/mspi_timing_types.h b/components/esp_hw_support/mspi_timing_types.h new file mode 100644 index 0000000000..c3792ac446 --- /dev/null +++ b/components/esp_hw_support/mspi_timing_types.h @@ -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 +#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 diff --git a/components/esp_hw_support/port/esp32p4/mspi_timing_config.c b/components/esp_hw_support/port/esp32p4/mspi_timing_config.c index ed209a88ad..230e2c072a 100644 --- a/components/esp_hw_support/port/esp32p4/mspi_timing_config.c +++ b/components/esp_hw_support/port/esp32p4/mspi_timing_config.c @@ -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 */ @@ -15,6 +15,8 @@ #include "esp_private/mspi_timing_config.h" #include "mspi_timing_tuning_configs.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"; @@ -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) { - //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 } diff --git a/components/esp_hw_support/port/esp32p4/mspi_timing_tuning_configs.h b/components/esp_hw_support/port/esp32p4/mspi_timing_tuning_configs.h index d8ffa101ea..ba41d8f782 100644 --- a/components/esp_hw_support/port/esp32p4/mspi_timing_tuning_configs.h +++ b/components/esp_hw_support/port/esp32p4/mspi_timing_tuning_configs.h @@ -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 */ @@ -7,10 +7,12 @@ #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_TEST_DATA_LEN 128 #define MSPI_TIMING_PSRAM_TEST_DATA_ADDR 0x80 #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 #if CONFIG_SPIRAM_SPEED_250M @@ -22,5 +24,42 @@ #else #define MSPI_TIMING_MPLL_FREQ_MHZ 400 #endif +#define MSPI_TIMING_SPLL_FREQ_MHZ 480 #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 diff --git a/components/esp_hw_support/test_apps/.build-test-rules.yml b/components/esp_hw_support/test_apps/.build-test-rules.yml index 0585429eba..1b086d9f03 100644 --- a/components/esp_hw_support/test_apps/.build-test-rules.yml +++ b/components/esp_hw_support/test_apps/.build-test-rules.yml @@ -20,7 +20,7 @@ components/esp_hw_support/test_apps/host_test_linux: components/esp_hw_support/test_apps/mspi: disable: - - if: IDF_TARGET != "esp32s3" + - if: IDF_TARGET not in ["esp32s3", "esp32p4"] components/esp_hw_support/test_apps/mspi_psram_with_dfs: disable: diff --git a/components/esp_hw_support/test_apps/mspi/README.md b/components/esp_hw_support/test_apps/mspi/README.md index 3677101481..3a9d77fcb9 100644 --- a/components/esp_hw_support/test_apps/mspi/README.md +++ b/components/esp_hw_support/test_apps/mspi/README.md @@ -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. To add new configuration, create one more sdkconfig.ci.NAME file in this directory. diff --git a/components/esp_hw_support/test_apps/mspi/main/test_mspi.c b/components/esp_hw_support/test_apps/mspi/main/test_mspi.c index 542f13798f..c6436535b6 100644 --- a/components/esp_hw_support/test_apps/mspi/main/test_mspi.c +++ b/components/esp_hw_support/test_apps/mspi/main/test_mspi.c @@ -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 */ @@ -22,9 +22,15 @@ static void sorted_array_insert(uint32_t *array, uint32_t *size, uint32_t item) (*size)++; } +#if CONFIG_IDF_TARGET_ESP32S3 #define TEST_TIME_CNT 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; uint32_t cost, index_1 = 0, index_2 = 0; diff --git a/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py b/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py index b0284ea421..6704041ebb 100644 --- a/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py +++ b/components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py @@ -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 - import os import pathlib import pytest 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 @@ -18,7 +17,7 @@ def test_flash8_psram8(dut: IdfDut) -> None: # 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 @@ -29,7 +28,7 @@ def test_flash4_psram8(dut: IdfDut) -> None: # 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 @@ -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) def test_flash4_psram4(dut: IdfDut) -> None: 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() diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32p4_120sdr_200ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32p4_120sdr_200ddr new file mode 100644 index 0000000000..53d90195c1 --- /dev/null +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32p4_120sdr_200ddr @@ -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 diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr similarity index 91% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr index 3ce4e3c454..43112d79f7 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr @@ -1,5 +1,7 @@ # Legacy, F4R4, Flash 120M SDR, PSRAM disable +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_120sdr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_120sdr similarity index 92% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_120sdr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_120sdr index c05d0bbab3..b3c8da70c5 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_120sdr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_120sdr @@ -1,5 +1,7 @@ # Legacy, F4R4, Flash 120M SDR, PSRAM 120M SDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_40sdr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_40sdr similarity index 92% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_40sdr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_40sdr index 60dacd89a4..0bfc80eb55 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_40sdr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_40sdr @@ -1,5 +1,7 @@ # Legacy, F4R4, Flash 120M SDR, PSRAM 40M SDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_os_silent b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_os_silent similarity index 94% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_os_silent rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_os_silent index da05ca4710..e7f2806be3 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_os_silent +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_120sdr_os_silent @@ -1,5 +1,7 @@ # Legacy, F4R4, Flash 120M SDR, PSRAM disable, compiler -Os and silent +CONFIG_IDF_TARGET="esp32s3" + CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_40sdr_120sdr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_40sdr_120sdr similarity index 90% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_40sdr_120sdr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_40sdr_120sdr index 7a1d6cb5c9..a2c2b3c7af 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_40sdr_120sdr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_40sdr_120sdr @@ -1,5 +1,7 @@ # Legacy, F4R4, Flash 40M SDR, PSRAM 120M SDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_80sdr_80sdr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_80sdr_80sdr similarity index 90% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_80sdr_80sdr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_80sdr_80sdr index 466aa5a33d..caa6d0d5f9 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_80sdr_80sdr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r4_80sdr_80sdr @@ -1,5 +1,7 @@ # Legacy, F4R4, Flash 80M SDR, PSRAM 80M SDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_120sdr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_120sdr similarity index 91% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_120sdr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_120sdr index 03b2c9106c..e97b11c2f5 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_120sdr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_120sdr @@ -1,5 +1,7 @@ # Legacy, F4R8, Flash 120M SDR, PSRAM disable +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_40ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_80sdr_40ddr similarity index 91% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_40ddr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_80sdr_40ddr index 72baf2d0e1..39fa591acd 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_40ddr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_80sdr_40ddr @@ -1,5 +1,7 @@ # Legacy, F4R8, Flash 80M SDR, PSRAM 40M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_80ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_80sdr_80ddr similarity index 91% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_80ddr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_80sdr_80ddr index 59434041a7..096f83be00 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_80ddr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f4r8_80sdr_80ddr @@ -1,5 +1,7 @@ # Legacy, F4R8, Flash 80M SDR, PSRAM 80M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_120sdr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_120sdr similarity index 92% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_120sdr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_120sdr index 774de2b9da..d8e2a43d36 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_120sdr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_120sdr @@ -1,5 +1,7 @@ # Legacy, F8R8, Flash 120M SDR, PSRAM disable +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_40ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_40ddr_40ddr similarity index 93% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_40ddr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_40ddr_40ddr index 0643c26397..95391e53b6 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_40ddr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_40ddr_40ddr @@ -1,5 +1,7 @@ # Legacy, F8R8, Flash 40M DDR, PSRAM 40M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_80ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_40ddr_80ddr similarity index 93% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_80ddr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_40ddr_80ddr index e208933fbb..5661b6e7a7 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_80ddr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_40ddr_80ddr @@ -1,5 +1,7 @@ # Legacy, F8R8, Flash 40M DDR, PSRAM 80M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_40ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_40ddr similarity index 93% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_40ddr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_40ddr index c56905ccb0..2ea74b405a 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_40ddr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_40ddr @@ -1,5 +1,7 @@ # Legacy, F8R8, Flash 80M DDR, PSRAM 40M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_80ddr similarity index 93% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_80ddr index 022bd0a12d..d174070fc6 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_80ddr @@ -1,5 +1,7 @@ # Legacy, F8R8, Flash 80M DDR, PSRAM 80M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr_ecc b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_80ddr_ecc similarity index 93% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr_ecc rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_80ddr_ecc index 7ab1d4bcfe..29d6f0ec20 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr_ecc +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80ddr_80ddr_ecc @@ -1,5 +1,7 @@ # Legacy, F8R8, Flash 80M DDR, PSRAM 80M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80sdr_80ddr b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80sdr_80ddr similarity index 93% rename from components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80sdr_80ddr rename to components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80sdr_80ddr index ffb1487d21..fa6e52f5f0 100644 --- a/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80sdr_80ddr +++ b/components/esp_hw_support/test_apps/mspi/sdkconfig.ci.esp32s3_f8r8_80sdr_80ddr @@ -1,5 +1,7 @@ # Legacy, F8R8, Flash 80M SDR, PSRAM 80M DDR +CONFIG_IDF_TARGET="esp32s3" + CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 6e1a0ceda7..3303dfaf65 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -561,7 +561,7 @@ 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 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 // some state of flash is modified. mspi_timing_flash_tuning(); diff --git a/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h b/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h index 6b84ef3c26..9d83a7ccb2 100644 --- a/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h +++ b/components/hal/esp32p4/include/hal/mspi_timing_tuning_ll.h @@ -15,15 +15,34 @@ #include #include #include "hal/assert.h" +#include "hal/misc.h" #include "soc/soc.h" #include "soc/iomux_mspi_pin_reg.h" #include "soc/iomux_mspi_pin_struct.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 extern "C" { #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 */ @@ -72,6 +91,19 @@ typedef enum { MSPI_LL_PIN_MAX, } 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 */ @@ -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 #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 * @@ -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); } +/*--------------------------------------------------------------- + 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 } #endif diff --git a/components/hal/esp32p4/include/hal/spimem_flash_ll.h b/components/hal/esp32p4/include/hal/spimem_flash_ll.h index c2c84cd29c..d76bef60e5 100644 --- a/components/hal/esp32p4/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32p4/include/hal/spimem_flash_ll.h @@ -643,6 +643,11 @@ static inline void spimem_flash_ll_set_extra_dummy(spi_mem_dev_t *dev, uint32_t //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 * the divider parameters. diff --git a/components/hal/esp32s3/include/hal/mspi_timing_tuning_ll.h b/components/hal/esp32s3/include/hal/mspi_timing_tuning_ll.h index 09232af277..a47e4ffae4 100644 --- a/components/hal/esp32s3/include/hal/mspi_timing_tuning_ll.h +++ b/components/hal/esp32s3/include/hal/mspi_timing_tuning_ll.h @@ -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 */ @@ -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 */ __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); } /** - * Enable PSRAM HCLK + * Enable PSRAM timing adjust clock * * @param spi_num SPI0 / SPI1 */ __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); } diff --git a/components/hal/esp32s3/include/hal/spimem_flash_ll.h b/components/hal/esp32s3/include/hal/spimem_flash_ll.h index e034092606..8646fde7ab 100644 --- a/components/hal/esp32s3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s3/include/hal/spimem_flash_ll.h @@ -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; } +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 * the divider parameters. diff --git a/components/hal/include/hal/spi_flash_hal.h b/components/hal/include/hal/spi_flash_hal.h index e4e2cd7e2e..eb1a19a6f5 100644 --- a/components/hal/include/hal/spi_flash_hal.h +++ b/components/hal/include/hal/spi_flash_hal.h @@ -42,9 +42,9 @@ typedef struct { int cs_num; ///< Which cs pin is used, 0-2. struct { 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_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 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`. typedef struct { uint32_t extra_dummy; + uint32_t fdummy_rin; uint32_t cs_hold; uint8_t cs_setup; spi_flash_ll_clock_reg_t clock_config; @@ -73,6 +74,7 @@ typedef struct { union { struct { 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 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. diff --git a/components/hal/spi_flash_hal.c b/components/hal/spi_flash_hal.c index 66c225f770..3403fbe183 100644 --- a/components/hal/spi_flash_hal.c +++ b/components/hal/spi_flash_hal.c @@ -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 (cfg->using_timing_tuning) { data_out->extra_dummy = extra_dummy_under_timing_tuning(cfg); + data_out->fdummy_rin = cfg->fdummy_rin; data_out->clock_conf = cfg->clock_config; } else #endif // SOC_SPI_MEM_SUPPORT_TIMING_TUNING diff --git a/components/hal/spi_flash_hal_common.inc b/components/hal/spi_flash_hal_common.inc index 4281105faa..05074cf618 100644 --- a/components/hal/spi_flash_hal_common.inc +++ b/components/hal/spi_flash_hal_common.inc @@ -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_mosi_bitlen(dev, 0); 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; } diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index dd2d715381..a3cf839e13 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1559,6 +1559,10 @@ config SOC_MEMSPI_TIMING_TUNING_BY_DQS bool default y +config SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY + bool + default y + config SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP bool default y @@ -1579,6 +1583,10 @@ config SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED bool default y +config SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED + bool + default y + config SOC_MEMSPI_FLASH_PSRAM_INDEPENDENT bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 89698d8e42..fe2bd1d2b5 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -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_TIMING_TUNING (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_PERIPH_SUPPORT_CONTROL_DUMMY_OUT (1) @@ -587,6 +588,7 @@ #define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_40M_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 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index c2f300189e..5a130f9596 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -919,7 +919,7 @@ config SOC_SPI_SCT_CONF_BITLEN_MAX hex default 0x3FFFA -config SOC_MEMSPI_SRC_FREQ_120M +config SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 29936d51c0..ccf1ba2500 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -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_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_40M_SUPPORTED 1 #define SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1 diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index fbabf81bd9..dab75fe876 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -36,7 +36,7 @@ menu "Main Flash configuration" choice SPI_FLASH_HPM prompt "High Performance Mode (READ DOCS FIRST, > 80MHz)" # 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 help 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 bool # 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) help This option is invisible, and will be selected automatically diff --git a/components/spi_flash/esp32p4/Kconfig.flash_freq b/components/spi_flash/esp32p4/Kconfig.flash_freq index 6e0296022f..78de9a398c 100644 --- a/components/spi_flash/esp32p4/Kconfig.flash_freq +++ b/components/spi_flash/esp32p4/Kconfig.flash_freq @@ -2,6 +2,10 @@ choice ESPTOOLPY_FLASHFREQ prompt "Flash SPI speed" default ESPTOOLPY_FLASHFREQ_40M if ESP32P4_REV_MIN_0 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 bool "80 MHz" depends on !ESP32P4_REV_MIN_0 diff --git a/tools/ci/idf_pytest/constants.py b/tools/ci/idf_pytest/constants.py index dadb57fd8d..1aa138b87b 100644 --- a/tools/ci/idf_pytest/constants.py +++ b/tools/ci/idf_pytest/constants.py @@ -94,6 +94,7 @@ ENV_MARKERS = { 'MSPI_F8R8': 'runner with Octal Flash and Octal PSRAM', 'MSPI_F4R8': 'runner with Quad Flash and Octal 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', 'usb_serial_jtag': 'runner where the chip is accessible through builtin JTAG as well', 'adc': 'ADC related tests should run on adc runners',