diff --git a/components/esp_hw_support/mspi_timing_tuning.c b/components/esp_hw_support/mspi_timing_tuning.c index c86e764f23..f7ec76d348 100644 --- a/components/esp_hw_support/mspi_timing_tuning.c +++ b/components/esp_hw_support/mspi_timing_tuning.c @@ -16,13 +16,12 @@ #include "esp_private/mspi_timing_tuning.h" #include "soc/soc.h" #include "hal/spi_flash_hal.h" +#include "hal/mspi_timing_tuning_ll.h" #if CONFIG_IDF_TARGET_ESP32S3 #include "port/esp32s3/mspi_timing_config.h" #include "esp32s3/rom/cache.h" #endif -#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr))) - #if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING const static char *TAG = "MSPI Timing"; static spi_timing_tuning_param_t s_flash_best_timing_tuning_config; @@ -36,18 +35,7 @@ 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 - SET_PERI_REG_MASK(SPI_MEM_DATE_REG(0), SPI_MEM_SPICLK_PAD_DRV_CTL_EN); - REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3); - REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3); - //Set default mspi d0 ~ d7, dqs pin drive strength - uint32_t regs[] = {IO_MUX_GPIO27_REG, IO_MUX_GPIO28_REG, - IO_MUX_GPIO31_REG, IO_MUX_GPIO32_REG, - IO_MUX_GPIO33_REG, IO_MUX_GPIO34_REG, - IO_MUX_GPIO35_REG, IO_MUX_GPIO36_REG, - IO_MUX_GPIO37_REG}; - for (int i = 0; i < ARRAY_SIZE(regs); i++) { - PIN_SET_DRV(regs[i], 3); - } + mspi_timing_ll_set_all_pin_drive(0, 3); } /*------------------------------------------------------------------------------ @@ -105,13 +93,13 @@ static void init_spi1_for_tuning(bool is_flash) uint32_t flash_div = get_flash_clock_divider(); spi_timing_config_set_flash_clock(1, flash_div); //Power on HCLK - REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(0), SPI_MEM_TIMING_CLK_ENA); + mspi_timinng_ll_enable_flash_hclk(0); } else { //We use SPI1 Flash to tune PSRAM, PSRAM timing related regs do nothing on SPI1 uint32_t psram_div = get_psram_clock_divider(); spi_timing_config_set_flash_clock(1, psram_div); //Power on HCLK - REG_SET_BIT(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(0), SPI_MEM_SPI_SMEM_TIMING_CLK_ENA); + mspi_timinng_ll_enable_psram_hclk(0); } } @@ -307,7 +295,7 @@ void mspi_timing_flash_tuning(void) 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 + mspi_timing_ll_enable_flash_variable_dummy(1, false); //GD flash will read error in variable mode with 20MHz uint8_t reference_data[SPI_TIMING_TEST_DATA_LEN] = {0}; spi_timing_config_flash_read_data(1, reference_data, SPI_TIMING_FLASH_TEST_DATA_ADDR, sizeof(reference_data)); @@ -366,7 +354,7 @@ void mspi_timing_psram_tuning(void) get_psram_tuning_configs(&timing_configs); //Disable the variable dummy mode when doing timing tuning - CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); + mspi_timing_ll_enable_flash_variable_dummy(1, false); //Get required config, and set them to PSRAM related registers do_tuning(reference_data, &timing_configs, false); mspi_timing_enter_high_speed_mode(true); diff --git a/components/esp_hw_support/port/esp32s3/mspi_timing_config.c b/components/esp_hw_support/port/esp32s3/mspi_timing_config.c index f48a868a78..96d865afea 100644 --- a/components/esp_hw_support/port/esp32s3/mspi_timing_config.c +++ b/components/esp_hw_support/port/esp32s3/mspi_timing_config.c @@ -12,6 +12,7 @@ #include "esp_types.h" #include "esp_log.h" #include "soc/spi_mem_reg.h" +#include "hal/mspi_timing_tuning_ll.h" #include "mspi_timing_config.h" #include "bootloader_flash.h" @@ -24,15 +25,6 @@ #define QPI_PSRAM_WRITE 0X38 #define QPI_PSRAM_FAST_READ_DUMMY 6 -#define MULTI_LINE_MASK_OCT_FLASH (SPI_MEM_FCMD_OCT | SPI_MEM_FADDR_OCT | SPI_MEM_FDIN_OCT | SPI_MEM_FDOUT_OCT) -#define MULTI_LINE_MASK_QUAD_FLASH (SPI_MEM_FASTRD_MODE | SPI_MEM_FREAD_DUAL | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_QIO) -#define SPI_FLASH_QIO_MODE (SPI_MEM_FREAD_QIO | SPI_MEM_FASTRD_MODE) -#define SPI_FLASH_QUAD_MODE (SPI_MEM_FREAD_QUAD | SPI_MEM_FASTRD_MODE) -#define SPI_FLASH_DIO_MODE (SPI_MEM_FREAD_DIO | SPI_MEM_FASTRD_MODE) -#define SPI_FLASH_DUAL_MODE (SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE) -#define SPI_FLASH_FAST_MODE (SPI_MEM_FASTRD_MODE) -#define SPI_FLASH_SLOW_MODE 0 - #define NOT_INIT_INT 127 //-------------------------------------MSPI Clock Setting-------------------------------------// @@ -73,28 +65,18 @@ void spi_timing_config_set_core_clock(uint8_t spi_num, spi_timing_config_core_cl abort(); } - REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(spi_num), SPI_MEM_CORE_CLK_SEL, reg_val); + mspi_timing_ll_set_core_clock_divider(spi_num, reg_val); } void spi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqdiv) { assert(freqdiv > 0); - if (freqdiv == 1) { - WRITE_PERI_REG(SPI_MEM_CLOCK_REG(spi_num), SPI_MEM_CLK_EQU_SYSCLK); - } else { - uint32_t freqbits = (((freqdiv - 1) << SPI_MEM_CLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI_MEM_CLKCNT_H_S)) | ((freqdiv - 1) << SPI_MEM_CLKCNT_L_S); - WRITE_PERI_REG(SPI_MEM_CLOCK_REG(spi_num), freqbits); - } + mspi_timing_ll_set_flash_clock(spi_num, freqdiv); } void spi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv) { - if (freqdiv == 1) { - WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); - } else { - uint32_t freqbits = (((freqdiv-1)<qio_dummy - 1; - case SPI_FLASH_QUAD_MODE: + case MSPI_TIMING_LL_FLASH_QUAD_MODE: return hpm_dummy->qout_dummy - 1; - case SPI_FLASH_DIO_MODE: + case MSPI_TIMING_LL_FLASH_DIO_MODE: return hpm_dummy->dio_dummy - 1; - case SPI_FLASH_DUAL_MODE: + case MSPI_TIMING_LL_FLASH_DUAL_MODE: return hpm_dummy->dout_dummy - 1; - case SPI_FLASH_FAST_MODE: + case MSPI_TIMING_LL_FLASH_FAST_MODE: return hpm_dummy->fastrd_dummy - 1; - case SPI_FLASH_SLOW_MODE: + case MSPI_TIMING_LL_FLASH_SLOW_MODE: return 0; default: abort(); @@ -164,18 +138,18 @@ static uint32_t spi_timing_config_get_dummy(void) } else #endif { // HPM is not enabled - switch (ctrl_reg & MULTI_LINE_MASK_QUAD_FLASH) { - case SPI_FLASH_QIO_MODE: + switch (mode) { + case MSPI_TIMING_LL_FLASH_QIO_MODE: return SPI1_R_QIO_DUMMY_CYCLELEN; - case SPI_FLASH_QUAD_MODE: + case MSPI_TIMING_LL_FLASH_QUAD_MODE: return SPI1_R_FAST_DUMMY_CYCLELEN; - case SPI_FLASH_DIO_MODE: + case MSPI_TIMING_LL_FLASH_DIO_MODE: return SPI1_R_DIO_DUMMY_CYCLELEN; - case SPI_FLASH_DUAL_MODE: + case MSPI_TIMING_LL_FLASH_DUAL_MODE: return SPI1_R_FAST_DUMMY_CYCLELEN; - case SPI_FLASH_FAST_MODE: + case MSPI_TIMING_LL_FLASH_FAST_MODE: return SPI1_R_FAST_DUMMY_CYCLELEN; - case SPI_FLASH_SLOW_MODE: + case MSPI_TIMING_LL_FLASH_SLOW_MODE: return 0; default: abort(); @@ -186,18 +160,11 @@ static uint32_t spi_timing_config_get_dummy(void) void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy) { if (bootloader_flash_is_octal_mode_enabled()) { - if (extra_dummy > 0) { - SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M); - SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, - SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M); - SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0, - SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); - } + mspi_timing_ll_set_octal_flash_extra_dummy(spi_num, extra_dummy); return; } /** + * HW workaround: * The `SPI_MEM_TIMING_CALI_REG` register is only used for OPI on 728 * Here we only need to update this global variable for extra dummy. Since we use the ROM Flash API, which will set the dummy based on this. * We only initialise the SPI0. And leave the SPI1 for flash driver to configure. @@ -215,31 +182,16 @@ void spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t extra_dumm //-------------------------------------PSRAM timing tuning register config-------------------------------------// void spi_timing_config_psram_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num) { - uint32_t reg_val = 0; - reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num)) & (~(SPI_MEM_SPI_SMEM_DIN0_MODE_M | SPI_MEM_SPI_SMEM_DIN1_MODE_M | SPI_MEM_SPI_SMEM_DIN2_MODE_M | SPI_MEM_SPI_SMEM_DIN3_MODE_M | SPI_MEM_SPI_SMEM_DIN4_MODE_M | SPI_MEM_SPI_SMEM_DIN5_MODE_M | SPI_MEM_SPI_SMEM_DIN6_MODE_M | SPI_MEM_SPI_SMEM_DIN7_MODE_M | SPI_MEM_SPI_SMEM_DINS_MODE_M))) - | (din_mode << SPI_MEM_SPI_SMEM_DIN0_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN1_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN2_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN3_MODE_S) - | (din_mode << SPI_MEM_SPI_SMEM_DIN4_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN5_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN6_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN7_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DINS_MODE_S); - REG_WRITE(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num), reg_val); - - reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num)) & (~(SPI_MEM_SPI_SMEM_DIN0_NUM_M | SPI_MEM_SPI_SMEM_DIN1_NUM_M | SPI_MEM_SPI_SMEM_DIN2_NUM_M | SPI_MEM_SPI_SMEM_DIN3_NUM_M | SPI_MEM_SPI_SMEM_DIN4_NUM_M | SPI_MEM_SPI_SMEM_DIN5_NUM_M | SPI_MEM_SPI_SMEM_DIN6_NUM_M | SPI_MEM_SPI_SMEM_DIN7_NUM_M | SPI_MEM_SPI_SMEM_DINS_NUM_M))) - | (din_num << SPI_MEM_SPI_SMEM_DIN0_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN1_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN2_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN3_NUM_S) - | (din_num << SPI_MEM_SPI_SMEM_DIN4_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN5_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN6_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN7_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DINS_NUM_S); - REG_WRITE(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num), reg_val); + mspi_timing_ll_set_psram_din_mode(spi_num, din_mode); + mspi_timing_ll_set_psram_din_num(spi_num, din_num); } void spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t extra_dummy) { #if CONFIG_SPIRAM_MODE_OCT - if (extra_dummy > 0) { - SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, - SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); - } else { - CLEAR_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0, - SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); - } + mspi_timing_ll_set_octal_psram_extra_dummy(spi_num, extra_dummy); #elif CONFIG_SPIRAM_MODE_QUAD + //HW workaround: Use normal dummy register to set extra dummy, the calibration dedicated extra dummy register doesn't work for quad mode SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(spi_num), SPI_MEM_USR_RD_SRAM_DUMMY_M); SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(spi_num), SPI_MEM_SRAM_RDUMMY_CYCLELEN_V, (QPI_PSRAM_FAST_READ_DUMMY + extra_dummy - 1), SPI_MEM_SRAM_RDUMMY_CYCLELEN_S); #endif diff --git a/components/hal/esp32s3/include/hal/mspi_timing_tuning_ll.h b/components/hal/esp32s3/include/hal/mspi_timing_tuning_ll.h new file mode 100644 index 0000000000..8ca75de1d6 --- /dev/null +++ b/components/hal/esp32s3/include/hal/mspi_timing_tuning_ll.h @@ -0,0 +1,317 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in hal/include/hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include +#include +#include "esp_bit_defs.h" +#include "hal/assert.h" +#include "soc/soc.h" +#include "soc/spi_mem_reg.h" +#include "soc/io_mux_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARRAY_SIZE(arr) (sizeof((arr))/sizeof(*(arr))) +#define MSPI_TIMING_LL_FLASH_OCT_MASK (SPI_MEM_FCMD_OCT | SPI_MEM_FADDR_OCT | SPI_MEM_FDIN_OCT | SPI_MEM_FDOUT_OCT) +#define MSPI_TIMING_LL_FLASH_QUAD_MASK (SPI_MEM_FASTRD_MODE | SPI_MEM_FREAD_DUAL | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_QIO) +#define MSPI_TIMING_LL_FLASH_QIO_MODE_MASK (SPI_MEM_FREAD_QIO | SPI_MEM_FASTRD_MODE) +#define MSPI_TIMING_LL_FLASH_QUAD_MODE_MASK (SPI_MEM_FREAD_QUAD | SPI_MEM_FASTRD_MODE) +#define MSPI_TIMING_LL_FLASH_DIO_MODE_MASK (SPI_MEM_FREAD_DIO | SPI_MEM_FASTRD_MODE) +#define MSPI_TIMING_LL_FLASH_DUAL_MODE_MASK (SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE) +#define MSPI_TIMING_LL_FLASH_FAST_MODE_MASK (SPI_MEM_FASTRD_MODE) +#define MSPI_TIMING_LL_FLASH_SLOW_MODE_MASK 0 + +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; + +/** + * Set all MSPI pin drive strength + * + * @param spi_num SPI0 / SPI1 + * @param val Pin drive strength + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_all_pin_drive(uint8_t spi_num, uint32_t val) +{ + SET_PERI_REG_MASK(SPI_MEM_DATE_REG(spi_num), SPI_MEM_SPICLK_PAD_DRV_CTL_EN); + REG_SET_FIELD(SPI_MEM_DATE_REG(spi_num), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, val); + REG_SET_FIELD(SPI_MEM_DATE_REG(spi_num), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, val); + + uint32_t regs[] = {IO_MUX_GPIO27_REG, IO_MUX_GPIO28_REG, + IO_MUX_GPIO31_REG, IO_MUX_GPIO32_REG, + IO_MUX_GPIO33_REG, IO_MUX_GPIO34_REG, + IO_MUX_GPIO35_REG, IO_MUX_GPIO36_REG, + IO_MUX_GPIO37_REG}; + for (int i = 0; i < ARRAY_SIZE(regs); i++) { + PIN_SET_DRV(regs[i], val); + } +} + +/** + * Set all MSPI Flash clock pin drive strength + * + * @param spi_num SPI0 / SPI1 + * @param val Pin drive strength + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_flash_clock_pin_drive(uint8_t spi_num, uint32_t val) +{ + bool clk_pin_drive_control = GET_PERI_REG_MASK(SPI_MEM_DATE_REG(spi_num), SPI_MEM_SPICLK_PAD_DRV_CTL_EN); + //You should never call this function, while `mspi_timing_ll_set_all_pin_drive()` isn't called + HAL_ASSERT(clk_pin_drive_control); + REG_SET_FIELD(SPI_MEM_DATE_REG(spi_num), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, val); +} + +/** + * Set all MSPI PSRAM clock pin drive strength + * + * @param spi_num SPI0 / SPI1 + * @param val Pin drive strength + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_clock_pin_drive(uint8_t spi_num, uint32_t val) +{ + bool clk_pin_drive_control = GET_PERI_REG_MASK(SPI_MEM_DATE_REG(spi_num), SPI_MEM_SPICLK_PAD_DRV_CTL_EN); + //You should never call this function, while `mspi_timing_ll_set_all_pin_drive()` isn't called + HAL_ASSERT(clk_pin_drive_control); + REG_SET_FIELD(SPI_MEM_DATE_REG(spi_num), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, val); +} + +/** + * Enable Flash HCLK + * + * @param spi_num SPI0 / SPI1 + */ +__attribute__((always_inline)) +static inline void mspi_timinng_ll_enable_flash_hclk(uint8_t spi_num) +{ + REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CLK_ENA); +} + +/** + * Enable PSRAM HCLK + * + * @param spi_num SPI0 / SPI1 + */ +__attribute__((always_inline)) +static inline void mspi_timinng_ll_enable_psram_hclk(uint8_t spi_num) +{ + REG_SET_BIT(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CLK_ENA); +} + +/** + * 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) +{ + REG_SET_FIELD(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY, enable); +} + +/** + * Set MSPI core clock divider + * + * @param spi_num SPI0 / SPI1 + * @param val Divider value + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_core_clock_divider(uint8_t spi_num, uint32_t val) +{ + REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(spi_num), SPI_MEM_CORE_CLK_SEL, val); +} + +/** + * 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 (freqdiv == 1) { + WRITE_PERI_REG(SPI_MEM_CLOCK_REG(spi_num), SPI_MEM_CLK_EQU_SYSCLK); + } else { + uint32_t freqbits = (((freqdiv - 1) << SPI_MEM_CLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI_MEM_CLKCNT_H_S)) | ((freqdiv - 1) << SPI_MEM_CLKCNT_L_S); + WRITE_PERI_REG(SPI_MEM_CLOCK_REG(spi_num), freqbits); + } +} + +/** + * Set MSPI PSRAM clock + * + * @param spi_num SPI0 / SPI1 + * @param freqdiv Divider value + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_clock(uint8_t spi_num, uint32_t freqdiv) +{ + if (freqdiv == 1) { + WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); + } else { + uint32_t freqbits = (((freqdiv-1)< 0) { + SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, + SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); + } else { + CLEAR_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0, + SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); + } +} + +/** + * Set MSPI PSRAM din mode + * + * @param spi_num SPI0 / SPI1 + * @param din_mode Din mode value + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_din_mode(uint8_t spi_num, uint8_t din_mode) +{ + uint32_t reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num)) & (~(SPI_MEM_SPI_SMEM_DIN0_MODE_M | SPI_MEM_SPI_SMEM_DIN1_MODE_M | SPI_MEM_SPI_SMEM_DIN2_MODE_M | SPI_MEM_SPI_SMEM_DIN3_MODE_M | SPI_MEM_SPI_SMEM_DIN4_MODE_M | SPI_MEM_SPI_SMEM_DIN5_MODE_M | SPI_MEM_SPI_SMEM_DIN6_MODE_M | SPI_MEM_SPI_SMEM_DIN7_MODE_M | SPI_MEM_SPI_SMEM_DINS_MODE_M))) + | (din_mode << SPI_MEM_SPI_SMEM_DIN0_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN1_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN2_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN3_MODE_S) + | (din_mode << SPI_MEM_SPI_SMEM_DIN4_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN5_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN6_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DIN7_MODE_S) | (din_mode << SPI_MEM_SPI_SMEM_DINS_MODE_S); + REG_WRITE(SPI_MEM_SPI_SMEM_DIN_MODE_REG(spi_num), reg_val); +} + +/** + * Set MSPI PSRAM din num + * + * @param spi_num SPI0 / SPI1 + * @param din_num Din num value + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_psram_din_num(uint8_t spi_num, uint8_t din_num) +{ + uint32_t reg_val = (REG_READ(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num)) & (~(SPI_MEM_SPI_SMEM_DIN0_NUM_M | SPI_MEM_SPI_SMEM_DIN1_NUM_M | SPI_MEM_SPI_SMEM_DIN2_NUM_M | SPI_MEM_SPI_SMEM_DIN3_NUM_M | SPI_MEM_SPI_SMEM_DIN4_NUM_M | SPI_MEM_SPI_SMEM_DIN5_NUM_M | SPI_MEM_SPI_SMEM_DIN6_NUM_M | SPI_MEM_SPI_SMEM_DIN7_NUM_M | SPI_MEM_SPI_SMEM_DINS_NUM_M))) + | (din_num << SPI_MEM_SPI_SMEM_DIN0_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN1_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN2_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN3_NUM_S) + | (din_num << SPI_MEM_SPI_SMEM_DIN4_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN5_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN6_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DIN7_NUM_S) | (din_num << SPI_MEM_SPI_SMEM_DINS_NUM_S); + REG_WRITE(SPI_MEM_SPI_SMEM_DIN_NUM_REG(spi_num), reg_val); +} + +/** + * Set MSPI Octal PSRAM extra dummy + * + * @param spi_num SPI0 / SPI1 + * @param extra_dummy Extra dummy + */ +__attribute__((always_inline)) +static inline void mspi_timing_ll_set_octal_psram_extra_dummy(uint8_t spi_num, uint8_t extra_dummy) +{ + if (extra_dummy > 0) { + SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, + SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); + } else { + CLEAR_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0, + SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); + } +} + +#ifdef __cplusplus +} +#endif