feat(psram): support 200mhz psram, experimental feature for now

This commit is contained in:
Armando 2024-01-09 12:27:07 +08:00
parent 8d85c08c40
commit 80e18811db
28 changed files with 1067 additions and 949 deletions

View File

@ -131,10 +131,13 @@ if(NOT BOOTLOADER_BUILD)
endif()
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
list(APPEND srcs "mspi_timing_tuning.c" "mspi_timing_config.c")
list(APPEND srcs "mspi_timing_tuning.c")
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY)
list(APPEND srcs "mspi_timing_by_mspi_delay.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS)
list(APPEND srcs "mspi_timing_by_dqs.c")
endif()
endif()
if(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED)

View File

@ -7,6 +7,7 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_private/mspi_timing_types.h"
#ifdef __cplusplus

View File

@ -36,9 +36,12 @@ entries:
systimer (noflash)
if APP_BUILD_TYPE_PURE_RAM_APP = n:
mspi_timing_tuning (noflash)
mspi_timing_config (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY = y:
mspi_timing_by_mspi_delay (noflash)
mspi_timing_config (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y:
mspi_timing_by_dqs (noflash)
mspi_timing_config (noflash)
if SOC_ADC_SHARED_POWER = y:
if ADC_ONESHOT_CTRL_FUNC_IN_IRAM = y:
sar_periph_ctrl (noflash)

View File

@ -0,0 +1,239 @@
/*
* 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 dqs
* This file will only be built, when `SOC_MEMSPI_TIMING_TUNING_BY_DQS == 1`
*/
#include <stdint.h>
#include <string.h>
#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_types.h"
#include "esp_log.h"
#include "mspi_timing_by_dqs.h"
#include "mspi_timing_tuning_configs.h"
#include "esp_private/mspi_timing_config.h"
#include "esp_private/rtc_clk.h"
#include "esp_private/periph_ctrl.h"
#include "hal/psram_ctrlr_ll.h"
#include "hal/mspi_timing_tuning_ll.h"
#define AP_HEX_PSRAM_SYNC_READ 0x0000
#define AP_HEX_PSRAM_SYNC_WRITE 0x8080
#define AP_HEX_PSRAM_RD_CMD_BITLEN 16
#define AP_HEX_PSRAM_WR_CMD_BITLEN 16
#define AP_HEX_PSRAM_ADDR_BITLEN 32
#if CONFIG_SPIRAM_SPEED_250M
#define AP_HEX_PSRAM_RD_DUMMY_BITLEN (2*(18-1))
#define AP_HEX_PSRAM_WR_DUMMY_BITLEN (2*(9-1))
#elif CONFIG_SPIRAM_SPEED_200M
#define AP_HEX_PSRAM_RD_DUMMY_BITLEN (2*(14-1))
#define AP_HEX_PSRAM_WR_DUMMY_BITLEN (2*(7-1))
#else
#define AP_HEX_PSRAM_RD_DUMMY_BITLEN (2*(10-1))
#define AP_HEX_PSRAM_WR_DUMMY_BITLEN (2*(5-1))
#endif
#define WRONG_DELAYLINE 16
const static char *TAG = "MSPI DQS";
static uint32_t s_test_data[MSPI_TIMING_TEST_DATA_LEN] = {0x7f786655, 0xa5ff005a, 0x3f3c33aa, 0xa5ff5a00, 0x1f1e9955, 0xa5005aff, 0x0f0fccaa, 0xa55a00ff,
0x07876655, 0xffa55a00, 0x03c333aa, 0xff00a55a, 0x01e19955, 0xff005aa5, 0x00f0ccaa, 0xff5a00a5,
0x80786655, 0x00a5ff5a, 0xc03c33aa, 0x00a55aff, 0xe01e9355, 0x00ff5aa5, 0xf00fccaa, 0x005affa5,
0xf8876655, 0x5aa5ff00, 0xfcc333aa, 0x5affa500, 0xfee19955, 0x5a00a5ff, 0x11f0ccaa, 0x5a00ffa5};
static mspi_timing_config_t s_test_delayline_config = {
.delayline_table = {{15, 0}, {14, 0}, {13, 0}, {12, 0}, {11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0},
{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}, {0, 10}, {0, 11}, {0, 12}, {0, 13}, {0, 14}, {0, 15}},
.available_config_num = 32,
};
static mspi_ll_dqs_phase_t s_psram_best_phase = MSPI_LL_DQS_PHASE_MAX;
static delayline_config_t s_psram_best_delayline = {WRONG_DELAYLINE, WRONG_DELAYLINE};
void mspi_timing_psram_init(uint32_t psram_freq_mhz)
{
psram_ctrlr_ll_enable_variable_dummy(PSRAM_CTRLR_LL_MSPI_ID_3, false);
mspi_timing_config_set_psram_clock(psram_freq_mhz, MSPI_TIMING_SPEED_MODE_NORMAL_PERF, true);
}
void mspi_timing_config_psram_prepare_reference_data(uint8_t *buf, uint32_t len)
{
assert(len == MSPI_TIMING_TEST_DATA_LEN);
memcpy(buf, &s_test_data, len);
}
void mspi_timing_config_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
{
uint8_t *w_ptr = buf;
while (len) {
int len_to_send = MIN(len, PSRAM_CTRLR_LL_FIFO_MAX_BYTES);
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
AP_HEX_PSRAM_SYNC_WRITE, AP_HEX_PSRAM_WR_CMD_BITLEN,
addr, AP_HEX_PSRAM_ADDR_BITLEN,
AP_HEX_PSRAM_WR_DUMMY_BITLEN,
w_ptr, len_to_send * 8,
NULL, 0,
false);
w_ptr += len_to_send;
addr += len_to_send;
len -= len_to_send;
}
}
void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
{
uint8_t *r_ptr = buf;
while (len) {
int len_to_recv = MIN(len, PSRAM_CTRLR_LL_FIFO_MAX_BYTES);
psram_ctrlr_ll_common_transaction(PSRAM_CTRLR_LL_MSPI_ID_3,
AP_HEX_PSRAM_SYNC_READ, AP_HEX_PSRAM_RD_CMD_BITLEN,
addr, AP_HEX_PSRAM_ADDR_BITLEN,
AP_HEX_PSRAM_RD_DUMMY_BITLEN,
NULL, 0,
r_ptr, len_to_recv * 8,
false);
r_ptr += len_to_recv;
addr += len_to_recv;
len -= len_to_recv;
}
}
void mspi_timing_get_psram_tuning_phases(mspi_timing_config_t *configs)
{
*configs = (mspi_timing_config_t) {
.phase = {MSPI_LL_DQS_PHASE_67_5, MSPI_LL_DQS_PHASE_78_75, MSPI_LL_DQS_PHASE_90, MSPI_LL_DQS_PHASE_101_25},
.available_phase_num = 4,
};
}
void mspi_timing_config_psram_set_tuning_phase(const void *configs, uint8_t id)
{
mspi_ll_dqs_phase_t phase = ((mspi_timing_config_t *)configs)->phase[id];
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, phase);
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, phase);
ESP_EARLY_LOGD(TAG, "set to phase: %d", phase);
}
uint32_t mspi_timing_psram_select_best_tuning_phase(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr)
{
assert(consecutive_length < 5);
uint32_t best_phase_id = 0;
bool success = true;
if (consecutive_length == 0) {
best_phase_id = 0;
success = false;
} else if (consecutive_length == 1) {
best_phase_id = end;
} else if (consecutive_length == 2 || consecutive_length == 3){
best_phase_id = end - 1;
} else {
best_phase_id = end - 2;
}
if (success) {
ESP_EARLY_LOGI(TAG, "tuning success, best phase id is %"PRIu32, best_phase_id);
} else {
ESP_EARLY_LOGW(TAG, "tuning fail, best phase id is fallen back to index %"PRIu32"", best_phase_id);
}
return best_phase_id;
}
void mspi_timing_psram_set_best_tuning_phase(const void *configs, uint8_t best_id)
{
s_psram_best_phase = ((mspi_timing_config_t *)configs)->phase[best_id];
}
void mspi_timing_get_psram_tuning_delaylines(mspi_timing_config_t *configs)
{
ESP_EARLY_LOGD(TAG, "sizeof(delayline_config_t): %d, sizeof(test_config): %d", sizeof(delayline_config_t), sizeof(s_test_delayline_config));
memcpy(configs, &s_test_delayline_config, sizeof(s_test_delayline_config));
}
void mspi_timing_config_psram_set_tuning_delayline(const void *configs, uint8_t id)
{
assert(s_psram_best_phase != MSPI_LL_DQS_PHASE_MAX);
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, s_psram_best_phase);
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, s_psram_best_phase);
ESP_EARLY_LOGD(TAG, "set to best phase: %d", s_psram_best_phase);
const delayline_config_t *delayline_config = &((mspi_timing_config_t *)configs)->delayline_table[id];
for (int i = 0; i < MSPI_LL_PIN_MAX; i++) {
if (i == MSPI_LL_PIN_DQS0 || i == MSPI_LL_PIN_DQS1) {
mspi_timing_ll_set_delayline(i, delayline_config->dqs_delayline);
} else {
mspi_timing_ll_set_delayline(i, delayline_config->data_delayline);
}
}
ESP_EARLY_LOGD(TAG, "set to delayline: {%d, %d}", delayline_config->data_delayline, delayline_config->dqs_delayline);
}
uint32_t mspi_timing_psram_select_best_tuning_delayline(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr)
{
assert(consecutive_length <= 32);
uint32_t bset_delayline_id = 0;
if (consecutive_length <= 1) {
bset_delayline_id = 0;
ESP_EARLY_LOGW(TAG, "tuning fail, best delayline id is fallen back to index %"PRIu32"", bset_delayline_id);
} else {
bset_delayline_id = end - consecutive_length / 2;
ESP_EARLY_LOGI(TAG, "tuning success, best delayline id is %"PRIu32, bset_delayline_id);
}
return bset_delayline_id;
}
void mspi_timing_psram_set_best_tuning_delayline(const void *configs, uint8_t best_id)
{
s_psram_best_delayline = ((mspi_timing_config_t *)configs)->delayline_table[best_id];
}
void mspi_timing_psram_config_clear_tuning_regs(bool control_both_mspi)
{
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, 0);
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, 0);
for (int i = 0; i < MSPI_LL_PIN_MAX; i++) {
mspi_timing_ll_set_delayline(i, 0);
}
}
void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi)
{
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_0, s_psram_best_phase);
mspi_timing_ll_set_dqs_phase(MSPI_LL_DQS_ID_1, s_psram_best_phase);
for (int i = 0; i < MSPI_LL_PIN_MAX; i++) {
if (i == MSPI_LL_PIN_DQS0 || i == MSPI_LL_PIN_DQS1) {
mspi_timing_ll_set_delayline(i, s_psram_best_delayline.dqs_delayline);
} else {
mspi_timing_ll_set_delayline(i, s_psram_best_delayline.data_delayline);
}
}
}
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
}

View File

@ -0,0 +1,201 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief
*
* This file contains configuration APIs doing MSPI timing tuning by MSPI DQS
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_DQS
#include "mspi_timing_tuning_configs.h"
#include "hal/mspi_timing_tuning_ll.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_MEMSPI_TIMING_TUNING_BY_DQS
#define IS_DDR 1
#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
*-------------------------------------------------------------------------------------------------*/
/**
* @brief Init MSPI for PSRAM timing tuning
*
* @param[in] psram_freq_mhz PSRAM frequency in MHz
*/
void mspi_timing_psram_init(uint32_t psram_freq_mhz);
/**
* @brief Prepare reference data buffer
*/
void mspi_timing_config_psram_prepare_reference_data(uint8_t *buf, uint32_t len);
/**
* @brief Configure PSRAM to write data via MSPI3
*
* @param[in] buf buffer
* @param[in] addr address
* @param[in] len length
*/
void mspi_timing_config_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len);
/**
* @brief Configure PSRAM to read data via MSPI3
*
* @param[out] buf buffer
* @param[in] addr address
* @param[in] len length
*/
void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len);
/**
* @brief Get PSRAM tuning configurations for phase
*
* @param[out] config Pointer to PSRAM tuning configurations
*/
void mspi_timing_get_psram_tuning_phases(mspi_timing_config_t *configs);
/**
* @brief Tune PSRAM timing registers for MSPI3 accessing PSRAM
*
* @param[in] configs Timing configs
* @param[in] id Config ID
*/
void mspi_timing_config_psram_set_tuning_phase(const void *configs, uint8_t id);
/**
* @brief Select PSRAM 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_psram_select_best_tuning_phase(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr);
/**
* @brief Set best PSRAM 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_psram_set_best_tuning_phase(const void *configs, uint8_t best_id);
/**
* @brief Get PSRAM tuning configurations for delayline
*
* @param[out] config Pointer to PSRAM tuning configurations
*/
void mspi_timing_get_psram_tuning_delaylines(mspi_timing_config_t *configs);
/**
* @brief Tune PSRAM timing registers for MSPI3 accessing PSRAM
*
* @param[in] configs Timing configs
* @param[in] id Config ID
*/
void mspi_timing_config_psram_set_tuning_delayline(const void *configs, uint8_t id);
/**
* @brief Select PSRAM 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_psram_select_best_tuning_delayline(const void *configs, uint32_t consecutive_length, uint32_t end, const uint8_t *reference_data, bool is_ddr);
/**
* @brief Set best PSRAM 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_psram_set_best_tuning_delayline(const void *configs, uint8_t best_id);
/*-------------------------------------------------------------------------------------------------
* General Timing APIs
*-------------------------------------------------------------------------------------------------*/
/**
* @brief Set PSRAM 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 MSPI3 as well
*/
void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi);
/**
* @brief Clear PSRAM 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 MSPI3 as well
*/
void mspi_timing_psram_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 MSPI1 as well
*/
void mspi_timing_flash_config_set_tuning_regs(bool control_both_mspi);
/**
* @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 MSPI1 as well
*/
void mspi_timing_flash_config_clear_tuning_regs(bool control_both_mspi);
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_DQS
#ifdef __cplusplus
}
#endif

View File

@ -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
*/
@ -22,7 +22,7 @@
#include "hal/mspi_timing_tuning_ll.h"
#include "hal/clk_tree_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "mspi_timing_config.h"
#include "esp_private/mspi_timing_config.h"
#include "mspi_timing_by_mspi_delay.h"
#include "bootloader_flash.h"
#include "esp32s3/rom/spi_flash.h"
@ -169,9 +169,9 @@ static void s_set_flash_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
mspi_timing_ll_set_quad_flash_dummy(spi_num, dummy + g_rom_spiflash_dummy_len_plus[spi_num]);
}
void mspi_timing_config_flash_set_tuning_regs(const void *timing_params)
void mspi_timing_config_flash_set_tuning_regs(const void *configs, uint8_t id)
{
const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
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
@ -239,9 +239,9 @@ static void s_set_psram_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
#endif
}
void mspi_timing_config_psram_set_tuning_regs(const void *timing_params)
void mspi_timing_config_psram_set_tuning_regs(const void *configs, uint8_t id)
{
const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
const mspi_timing_tuning_param_t *params = &((mspi_timing_config_t *)configs)->tuning_config_table[id];
/**
* 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless
* SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning
@ -322,6 +322,14 @@ static void s_psram_execution(uint8_t *buf, uint32_t addr, uint32_t len, bool is
}
}
void mspi_timing_config_psram_prepare_reference_data(uint8_t *buf, uint32_t len)
{
assert((len == MSPI_TIMING_TEST_DATA_LEN) && (len % 4 == 0));
for (int i=0; i < len/4; i++) {
((uint32_t *)buf)[i] = 0xa5ff005a;
}
}
void mspi_timing_config_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
{
s_psram_execution(buf, addr, len, false);
@ -439,9 +447,9 @@ static uint32_t s_select_best_tuning_config_dtr(const mspi_timing_config_t *conf
for (; current_point <= end; current_point++) {
if (is_flash) {
mspi_timing_config_flash_set_tuning_regs(&(configs->tuning_config_table[current_point]));
mspi_timing_config_flash_set_tuning_regs(configs, current_point);
} else {
mspi_timing_config_psram_set_tuning_regs(&(configs->tuning_config_table[current_point]));
mspi_timing_config_psram_set_tuning_regs(configs, current_point);
}
ret = get_working_pll_freq(reference_data, is_flash, &temp_max_freq, &temp_min_freq);
@ -522,16 +530,16 @@ uint32_t mspi_timing_psram_select_best_tuning_config(const void *configs, uint32
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 *timing_params)
void mspi_timing_flash_set_best_tuning_config(const void *configs, uint8_t best_id)
{
const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
s_flash_best_timing_tuning_config = *params;
const mspi_timing_tuning_param_t params = ((const mspi_timing_config_t *)configs)->tuning_config_table[best_id];
s_flash_best_timing_tuning_config = params;
}
void mspi_timing_psram_set_best_tuning_config(const void *timing_params)
void mspi_timing_psram_set_best_tuning_config(const void *configs, uint8_t best_id)
{
const mspi_timing_tuning_param_t *params = (const mspi_timing_tuning_param_t *)timing_params;
s_psram_best_timing_tuning_config = *params;
const mspi_timing_tuning_param_t params = ((const mspi_timing_config_t *)configs)->tuning_config_table[best_id];
s_psram_best_timing_tuning_config = params;
}

View File

@ -40,7 +40,7 @@ typedef struct {
* MSPI timing tuning configurations
*/
typedef struct {
mspi_timing_tuning_param_t tuning_config_table[MSPI_TIMING_CONFIG_NUM_DEFAULT]; // Available timing tuning configs
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;
@ -67,9 +67,10 @@ void mspi_timing_flash_init(uint32_t flash_freq_mhz);
/**
* @brief Tune Flash timing registers for SPI1 accessing Flash
*
* @param[in] params Timing parameters
* @param[in] configs Timing configs
* @param[in] id Config ID
*/
void mspi_timing_config_flash_set_tuning_regs(const void *timing_params);
void mspi_timing_config_flash_set_tuning_regs(const void *configs, uint8_t id);
/**
* @brief Configure Flash to read data via SPI1
@ -97,9 +98,15 @@ void mspi_timing_psram_init(uint32_t psram_freq_mhz);
/**
* @brief Tune PSRAM timing registers for SPI1 accessing PSRAM
*
* @param[in] params Timing parameters
* @param[in] configs Timing configs
* @param[in] id Config ID
*/
void mspi_timing_config_psram_set_tuning_regs(const void *timing_params);
void mspi_timing_config_psram_set_tuning_regs(const void *configs, uint8_t id);
/**
* @brief Prepare reference data buffer
*/
void mspi_timing_config_psram_prepare_reference_data(uint8_t *buf, uint32_t len);
/**
* @brief Configure PSRAM to write data via SPI1
@ -140,9 +147,10 @@ uint32_t mspi_timing_flash_select_best_tuning_config(const void *configs, uint32
* @brief Set best Flash tuning configs.
* After this, calling `mspi_timing_enter_high_speed_mode` will set these configs correctly
*
* @param[in] timing_params Timing tuning parameters
* @param[in] configs Timing tuning configs
* @param[in] best_id Best config ID
*/
void mspi_timing_flash_set_best_tuning_config(const void *timing_params);
void mspi_timing_flash_set_best_tuning_config(const void *configs, uint8_t best_id);
/**
* @brief Select PSRAM best tuning configuration
@ -161,9 +169,10 @@ uint32_t mspi_timing_psram_select_best_tuning_config(const void *configs, uint32
* @brief Set best PSRAM tuning configs.
* After this, calling `mspi_timing_enter_high_speed_mode` will set these configs correctly
*
* @param[in] timing_params Timing tuning parameters
* @param[in] configs Timing tuning configs
* @param[in] best_id Best config ID
*/
void mspi_timing_psram_set_best_tuning_config(const void *timing_params);
void mspi_timing_psram_set_best_tuning_config(const void *configs, uint8_t best_id);
/*-------------------------------------------------------------------------------------------------

View File

@ -17,12 +17,16 @@
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "esp_private/mspi_timing_tuning.h"
#include "mspi_timing_config.h"
#include "esp_private/mspi_timing_config.h"
#include "mspi_timing_by_mspi_delay.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
#include "mspi_timing_by_dqs.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY || SOC_MEMSPI_TIMING_TUNING_BY_DQS
#include "mspi_timing_tuning_configs.h"
#include "hal/mspi_timing_tuning_ll.h"
#endif
#if SOC_MEMSPI_TIMING_TUNING_BY_DQS
#include "hal/psram_ctrlr_ll.h"
#endif
#if SOC_MEMSPI_CLK_SRC_IS_INDEPENDENT
#include "hal/spimem_flash_ll.h"
#endif
@ -60,6 +64,8 @@
*/
typedef enum {
MSPI_TIMING_TUNING_MSPI_DIN_DUMMY, //tune by mspi din and dummy
MSPI_TIMING_TUNING_MSPI_DQS_PHASE, //tune by mspi dqs phase
MSPI_TIMING_TUNING_MSPI_DELAYLINE, //tune by mspi delayline
} mspi_timing_tuning_t;
typedef struct mspi_tuning_cfg_drv_s mspi_tuning_cfg_drv_t;
@ -72,6 +78,11 @@ struct mspi_tuning_cfg_drv_s {
*/
mspi_timing_tuning_t flash_tuning_type;
/**
* @brief How many test times during sweep
*/
uint32_t sweep_test_nums;
/**
* @brief Init MSPI for Flash timing tuning
*
@ -82,9 +93,10 @@ struct mspi_tuning_cfg_drv_s {
/**
* @brief Configure MSPI for Flash timing tuning
*
* @param[in] params Timing tuning parameters
* @param[in] configs Timing tuning configs
* @param[in] id Config ID
*/
void (*flash_tune_mspi)(const void *params);
void (*flash_tune_mspi)(const void *configs, uint8_t id);
/**
* @brief Flash read
@ -112,9 +124,10 @@ struct mspi_tuning_cfg_drv_s {
* @brief Set best Flash tuning configs.
* After this, calling `mspi_timing_enter_high_speed_mode` will set these configs correctly
*
* @param[in] params Timing tuning parameters
* @param[in] configs Timing tuning configs
* @param[in] best_id Best config ID
*/
void (*flash_set_best_tuning_config)(const void *params);
void (*flash_set_best_tuning_config)(const void *configs, uint8_t best_id);
/**
* @brief PSRAM tuning scheme type
@ -131,9 +144,10 @@ struct mspi_tuning_cfg_drv_s {
/**
* @brief Configure MSPI for PSRAM timing tuning
*
* @param[in] params Timing tuning parameters
* @param[in] configs Timing tuning configs
* @param[in] id Config ID
*/
void (*psram_tune_mspi)(const void *params);
void (*psram_tune_mspi)(const void *configs, uint8_t id);
/**
* @brief PSRAM read
@ -161,9 +175,10 @@ struct mspi_tuning_cfg_drv_s {
* @brief Set best PSRAM tuning configs.
* After this, calling `mspi_timing_enter_high_speed_mode` will set these configs correctly
*
* @param[in] params Timing tuning parameters
* @param[in] configs Timing tuning config
* @param[in] best_id Best config ID
*/
void (*psram_set_best_tuning_config)(const void *params);
void (*psram_set_best_tuning_config)(const void *configs, uint8_t best_id);
};
static mspi_tuning_cfg_drv_t s_tuning_cfg_drv = {};
@ -185,6 +200,7 @@ void s_register_config_driver(mspi_tuning_cfg_drv_t *cfg_drv, bool is_flash)
s_tuning_cfg_drv.psram_select_best_tuning_config = cfg_drv->psram_select_best_tuning_config;
s_tuning_cfg_drv.psram_set_best_tuning_config = cfg_drv->psram_set_best_tuning_config;
}
s_tuning_cfg_drv.sweep_test_nums = cfg_drv->sweep_test_nums;
}
#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
@ -192,33 +208,36 @@ void s_register_config_driver(mspi_tuning_cfg_drv_t *cfg_drv, bool is_flash)
* We use different MSPI timing tuning config to read data to see if current MSPI sampling is successful.
* The sampling result will be stored in an array. In this array, successful item will be 1, failed item will be 0.
*/
static void s_sweep_for_success_sample_points(uint8_t *reference_data, void *config, bool is_flash, uint8_t *out_array)
static void s_sweep_for_success_sample_points(uint8_t *reference_data, void *config, bool is_flash, uint32_t *out_array)
{
const mspi_timing_config_t *timing_config = (const mspi_timing_config_t *)config;
uint32_t config_idx = 0;
uint8_t read_data[MSPI_TIMING_TEST_DATA_LEN] = {0};
for (config_idx = 0; config_idx < timing_config->available_config_num; config_idx++) {
memset(read_data, 0, MSPI_TIMING_TEST_DATA_LEN);
for (int i = 0; i < s_tuning_cfg_drv.sweep_test_nums; i++) {
memset(read_data, 0, MSPI_TIMING_TEST_DATA_LEN);
#if MSPI_TIMING_FLASH_NEEDS_TUNING
if (is_flash) {
s_tuning_cfg_drv.flash_tune_mspi(&(timing_config->tuning_config_table[config_idx]));
s_tuning_cfg_drv.flash_read(read_data, MSPI_TIMING_FLASH_TEST_DATA_ADDR, sizeof(read_data));
}
if (is_flash) {
s_tuning_cfg_drv.flash_tune_mspi(timing_config, config_idx);
s_tuning_cfg_drv.flash_read(read_data, MSPI_TIMING_FLASH_TEST_DATA_ADDR, sizeof(read_data));
}
#endif
#if MSPI_TIMING_PSRAM_NEEDS_TUNING
if (!is_flash) {
s_tuning_cfg_drv.psram_tune_mspi(&(timing_config->tuning_config_table[config_idx]));
s_tuning_cfg_drv.psram_read(read_data, MSPI_TIMING_PSRAM_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
}
if (!is_flash) {
s_tuning_cfg_drv.psram_tune_mspi(timing_config, config_idx);
s_tuning_cfg_drv.psram_read(read_data, MSPI_TIMING_PSRAM_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
}
#endif
if (memcmp(reference_data, read_data, sizeof(read_data)) == 0) {
out_array[config_idx] = 1;
ESP_EARLY_LOGD(TAG, "%"PRIu32", good", config_idx);
} else {
ESP_EARLY_LOGD(TAG, "%"PRIu32", bad", config_idx);
if (memcmp(reference_data, read_data, sizeof(read_data)) == 0) {
out_array[config_idx] += 1;
}
}
}
ESP_EARLY_LOGD(TAG, "test nums: %d, test result: [id][good/bad][good_times]:", s_tuning_cfg_drv.sweep_test_nums);
for (config_idx = 0; config_idx < timing_config->available_config_num; config_idx++) {
ESP_EARLY_LOGD(TAG, "[%"PRIu32"][%s][%d] ", config_idx, out_array[config_idx] == s_tuning_cfg_drv.sweep_test_nums ? "good" : "bad", out_array[config_idx]);
}
}
@ -228,7 +247,7 @@ static void s_sweep_for_success_sample_points(uint8_t *reference_data, void *con
* out_length: 3
* outout_end_index: 6
*/
static void s_find_max_consecutive_success_points(uint8_t *array, uint32_t size, uint32_t *out_length, uint32_t *out_end_index)
static void s_find_max_consecutive_success_points(uint32_t *array, uint32_t size, uint32_t *out_length, uint32_t *out_end_index)
{
uint32_t max = 0;
uint32_t match_num = 0;
@ -236,7 +255,7 @@ static void s_find_max_consecutive_success_points(uint8_t *array, uint32_t size,
uint32_t end = 0;
while (i < size) {
if (array[i]) {
if (array[i] == s_tuning_cfg_drv.sweep_test_nums) {
match_num++;
} else {
if (match_num > max) {
@ -262,18 +281,18 @@ static void s_select_best_tuning_config(mspi_timing_config_t *config, uint32_t c
#elif MSPI_TIMING_FLASH_STR_MODE
best_point = s_tuning_cfg_drv.flash_select_best_tuning_config(timing_config, consecutive_length, end, NULL, IS_SDR);
#endif
s_tuning_cfg_drv.flash_set_best_tuning_config(&(timing_config->tuning_config_table[best_point]));
s_tuning_cfg_drv.flash_set_best_tuning_config(timing_config, best_point);
} else {
#if MSPI_TIMING_PSRAM_DTR_MODE
best_point = s_tuning_cfg_drv.psram_select_best_tuning_config(timing_config, consecutive_length, end, reference_data, IS_DDR);
#elif MSPI_TIMING_PSRAM_STR_MODE
best_point = s_tuning_cfg_drv.psram_select_best_tuning_config(timing_config, consecutive_length, end, NULL, IS_SDR);
#endif
s_tuning_cfg_drv.psram_set_best_tuning_config(&(timing_config->tuning_config_table[best_point]));
s_tuning_cfg_drv.psram_set_best_tuning_config(timing_config, best_point);
}
}
static void s_do_tuning(uint8_t *reference_data, void *timing_config, bool is_flash)
static void s_do_tuning(uint8_t *reference_data, mspi_timing_config_t *config, bool is_flash)
{
/**
* We use MSPI to tune the timing:
@ -283,7 +302,7 @@ static void s_do_tuning(uint8_t *reference_data, void *timing_config, bool is_fl
*/
uint32_t consecutive_length = 0;
uint32_t last_success_point = 0;
uint8_t sample_result[MSPI_TIMING_CONFIG_NUM_DEFAULT] = {0};
uint32_t sample_result[MSPI_TIMING_CONFIG_NUM_MAX] = {0};
#if MSPI_TIMING_FLASH_NEEDS_TUNING
if (is_flash) {
@ -296,9 +315,9 @@ static void s_do_tuning(uint8_t *reference_data, void *timing_config, bool is_fl
}
#endif
s_sweep_for_success_sample_points(reference_data, timing_config, is_flash, sample_result);
s_find_max_consecutive_success_points(sample_result, MSPI_TIMING_CONFIG_NUM_DEFAULT, &consecutive_length, &last_success_point);
s_select_best_tuning_config(timing_config, consecutive_length, last_success_point, reference_data, is_flash);
s_sweep_for_success_sample_points(reference_data, config, is_flash, sample_result);
s_find_max_consecutive_success_points(sample_result, config->available_config_num, &consecutive_length, &last_success_point);
s_select_best_tuning_config(config, consecutive_length, last_success_point, reference_data, is_flash);
}
#endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
@ -318,6 +337,7 @@ void mspi_timing_flash_tuning(void)
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
mspi_tuning_cfg_drv_t drv = {
.flash_tuning_type = MSPI_TIMING_TUNING_MSPI_DIN_DUMMY,
.sweep_test_nums = 1,
.flash_init_mspi = mspi_timing_flash_init,
.flash_tune_mspi = mspi_timing_config_flash_set_tuning_regs,
.flash_read = mspi_timing_config_flash_read_data,
@ -362,16 +382,15 @@ void mspi_timing_psram_tuning(void)
*/
mspi_timing_enter_low_speed_mode(true);
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
// write data into psram, used to do timing tuning test.
uint8_t reference_data[MSPI_TIMING_TEST_DATA_LEN];
for (int i=0; i < MSPI_TIMING_TEST_DATA_LEN/4; i++) {
((uint32_t *)reference_data)[i] = 0xa5ff005a;
}
mspi_timing_config_psram_prepare_reference_data(reference_data, MSPI_TIMING_TEST_DATA_LEN);
mspi_timing_config_psram_write_data(reference_data, MSPI_TIMING_PSRAM_TEST_DATA_ADDR, MSPI_TIMING_TEST_DATA_LEN);
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
mspi_tuning_cfg_drv_t drv = {
.psram_tuning_type = MSPI_TIMING_TUNING_MSPI_DIN_DUMMY,
.sweep_test_nums = 1,
.psram_init_mspi = mspi_timing_psram_init,
.psram_tune_mspi = mspi_timing_config_psram_set_tuning_regs,
.psram_read = mspi_timing_config_psram_read_data,
@ -381,14 +400,48 @@ void mspi_timing_psram_tuning(void)
bool is_flash = false;
s_register_config_driver(&drv, is_flash);
mspi_timing_config_t timing_configs = {0};
mspi_timing_config_t timing_configs = {};
mspi_timing_get_psram_tuning_configs(&timing_configs);
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
//Disable the variable dummy mode when doing timing tuning
mspi_timing_ll_enable_flash_variable_dummy(1, false);
//Get required config, and set them to PSRAM related registers
s_do_tuning(reference_data, &timing_configs, false);
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
#if SOC_MEMSPI_TIMING_TUNING_BY_DQS
bool is_flash = false;
mspi_timing_config_t timing_configs = {};
//Phase
mspi_tuning_cfg_drv_t drv = {
.psram_tuning_type = MSPI_TIMING_TUNING_MSPI_DQS_PHASE,
.sweep_test_nums = 1,
.psram_init_mspi = mspi_timing_psram_init,
.psram_tune_mspi = mspi_timing_config_psram_set_tuning_phase,
.psram_read = mspi_timing_config_psram_read_data,
.psram_select_best_tuning_config = mspi_timing_psram_select_best_tuning_phase,
.psram_set_best_tuning_config = mspi_timing_psram_set_best_tuning_phase,
};
s_register_config_driver(&drv, is_flash);
mspi_timing_get_psram_tuning_phases(&timing_configs);
s_do_tuning(reference_data, &timing_configs, false);
//Delayline
drv = (mspi_tuning_cfg_drv_t) {
.psram_tuning_type = MSPI_TIMING_TUNING_MSPI_DELAYLINE,
.sweep_test_nums = MSPI_TIMING_DELAYLINE_TEST_NUMS,
.psram_init_mspi = mspi_timing_psram_init,
.psram_tune_mspi = mspi_timing_config_psram_set_tuning_delayline,
.psram_read = mspi_timing_config_psram_read_data,
.psram_select_best_tuning_config = mspi_timing_psram_select_best_tuning_delayline,
.psram_set_best_tuning_config = mspi_timing_psram_set_best_tuning_delayline,
};
s_register_config_driver(&drv, is_flash);
mspi_timing_get_psram_tuning_delaylines(&timing_configs);
s_do_tuning(reference_data, &timing_configs, false);
#endif
mspi_timing_enter_high_speed_mode(true);
}
@ -495,14 +548,22 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down)
*----------------------------------------------------------------------------*/
bool spi_timing_is_tuned(void)
{
#if MSPI_TIMING_MSPI1_IS_INVOLVED
//esp flash driver needs to be notified
#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
//either flash or psram or both is tuned, needs notify flash driver
return true;
#else
//otherwise no need
return false;
#endif
#else
//if mspi1 is not involved in timing tuning
return false;
#endif //MSPI_TIMING_MSPI1_IS_INVOLVED
}
#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
#if MSPI_TIMING_MSPI1_IS_INVOLVED && (MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING)
void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config)
{
// Get clock configuration directly from system.
@ -522,7 +583,7 @@ void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing
// This function shouldn't be called if timing tuning is not used.
abort();
}
#endif // MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
#endif // #if MSPI_TIMING_MSPI1_IS_INVOLVED && (MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING)
/*------------------------------------------------------------------------------
* Common settings

View File

@ -1,3 +1,5 @@
target_include_directories(${COMPONENT_LIB} PUBLIC .)
set(srcs "rtc_clk_init.c"
"rtc_clk.c"
"pmu_param.c"
@ -10,6 +12,10 @@ set(srcs "rtc_clk_init.c"
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "esp_crypto_lock.c")
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
list(APPEND srcs "mspi_timing_config.c")
endif()
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c")
endif()

View File

@ -0,0 +1,38 @@
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_types.h"
#include "esp_log.h"
#include "soc/soc_caps.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/mspi_timing_config.h"
#include "mspi_timing_tuning_configs.h"
#include "hal/psram_ctrlr_ll.h"
const static char *TAG = "MSPI Timing";
//-------------------------------------MSPI Clock Setting-------------------------------------//
void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_speed_mode_t speed_mode, bool control_both_mspi)
{
uint32_t freqdiv = MSPI_TIMING_MPLL_FREQ_MHZ / MSPI_TIMING_CORE_CLOCK_DIV / psram_freq_mhz;
assert(freqdiv > 0);
ESP_EARLY_LOGD(TAG, "psram_freq_mhz: %d mhz, bus clock div: %d", psram_freq_mhz, freqdiv);
PERIPH_RCC_ATOMIC() {
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
psram_ctrlr_ll_set_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, freqdiv);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, freqdiv);
}
}
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
}

View File

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#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_CORE_CLOCK_DIV 1
#if CONFIG_SPIRAM_SPEED_250M
#define MSPI_TIMING_PSRAM_NEEDS_TUNING 1
#define MSPI_TIMING_MPLL_FREQ_MHZ 500
#elif CONFIG_SPIRAM_SPEED_200M
#define MSPI_TIMING_PSRAM_NEEDS_TUNING 1
#define MSPI_TIMING_MPLL_FREQ_MHZ 400
#else
#define MSPI_TIMING_MPLL_FREQ_MHZ 400
#endif
#define MSPI_TIMING_PSRAM_DTR_MODE CONFIG_SPIRAM_MODE_HEX

View File

@ -13,6 +13,10 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "esp_crypto_lock.c"
"sar_periph_ctrl.c")
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
list(APPEND srcs "mspi_timing_config.c")
endif()
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c")
endif()

View File

@ -11,22 +11,15 @@
#include "esp_types.h"
#include "esp_log.h"
#include "soc/soc_caps.h"
#include "mspi_timing_config.h"
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
#include "esp_private/mspi_timing_config.h"
#include "mspi_timing_tuning_configs.h"
#include "hal/mspi_timing_tuning_ll.h"
#endif
#if SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM
#define FLASH_LOW_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT
#define FLASH_HIGH_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_CORE_CLOCK_MHZ
#define PSRAM_LOW_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_LL_CORE_CLOCK_MHZ_DEFAULT
#define PSRAM_HIGH_SPEED_CORE_CLOCK_MHZ MSPI_TIMING_CORE_CLOCK_MHZ
#endif //SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM
#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
/**
* Currently we only need these on chips with timing tuning
*/
@ -76,4 +69,3 @@ void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_spe
assert(freqdiv > 0);
mspi_timing_ll_set_psram_clock(0, freqdiv);
}
#endif //#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING

View File

@ -9,7 +9,8 @@
#include "esp_assert.h"
#include "esp_flash_partitions.h"
#define MSPI_TIMING_CONFIG_NUM_DEFAULT 20 //This should be larger than the max available timing config num
#define MSPI_TIMING_MSPI1_IS_INVOLVED 1 //This means esp flash driver needs to be notified
#define MSPI_TIMING_CONFIG_NUM_MAX 20 //This should be larger than the max available timing config num
#define MSPI_TIMING_TEST_DATA_LEN 64
#define MSPI_TIMING_PSRAM_TEST_DATA_ADDR 0
#define MSPI_TIMING_FLASH_TEST_DATA_ADDR ESP_BOOTLOADER_OFFSET

View File

@ -12,10 +12,10 @@
#include "esp_private/periph_ctrl.h"
#include "esp_private/rtc_clk.h"
#include "esp_private/esp_ldo_psram.h"
#include "esp_private/mspi_timing_tuning.h"
#include "../esp_psram_impl.h"
#include "rom/opi_flash.h"
#include "hal/psram_ctrlr_ll.h"
#include "hal/ldo_ll.h"
#include "hal/mspi_timing_tuning_ll.h"
// Reset and Clock Control registers are mixing with other peripherals, so we need to use a critical section
#define PSRAM_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
@ -29,10 +29,25 @@
#define AP_HEX_PSRAM_RD_CMD_BITLEN 16
#define AP_HEX_PSRAM_WR_CMD_BITLEN 16
#define AP_HEX_PSRAM_ADDR_BITLEN 32
#if CONFIG_SPIRAM_SPEED_250M
#define AP_HEX_PSRAM_RD_DUMMY_BITLEN (2*(18-1))
#define AP_HEX_PSRAM_WR_DUMMY_BITLEN (2*(9-1))
#define AP_HEX_PSRAM_RD_LATENCY 6
#define AP_HEX_PSRAM_WR_LATENCY 3
#elif CONFIG_SPIRAM_SPEED_200M
#define AP_HEX_PSRAM_RD_DUMMY_BITLEN (2*(14-1))
#define AP_HEX_PSRAM_WR_DUMMY_BITLEN (2*(7-1))
#define AP_HEX_PSRAM_RD_LATENCY 4
#define AP_HEX_PSRAM_WR_LATENCY 1
#else
#define AP_HEX_PSRAM_RD_DUMMY_BITLEN (2*(10-1))
#define AP_HEX_PSRAM_WR_DUMMY_BITLEN (2*(5-1))
#define AP_HEX_PSRAM_VENDOR_ID 0xD
#define AP_HEX_PSRAM_RD_LATENCY 2
#define AP_HEX_PSRAM_WR_LATENCY 2
#endif
#define AP_HEX_PSRAM_VENDOR_ID 0xD
#define AP_HEX_PSRAM_CS_SETUP_TIME 4
#define AP_HEX_PSRAM_CS_HOLD_TIME 4
#define AP_HEX_PSRAM_CS_ECC_HOLD_TIME 4
@ -164,7 +179,6 @@ static void s_init_psram_mode_reg(int spi_num, hex_psram_mode_reg_t *mode_reg_co
false);
addr = 0x4;
//write
s_psram_common_transaction(spi_num,
AP_HEX_PSRAM_REG_WRITE, cmd_len,
addr, addr_bit_len,
@ -173,9 +187,9 @@ static void s_init_psram_mode_reg(int spi_num, hex_psram_mode_reg_t *mode_reg_co
NULL, 0,
false);
//read
addr = 0x8;
data_bit_len = 8;
//read
s_psram_common_transaction(spi_num,
AP_HEX_PSRAM_REG_READ, cmd_len,
addr, addr_bit_len,
@ -269,11 +283,9 @@ static void s_print_psram_info(hex_psram_mode_reg_t *reg_val)
static void s_config_mspi_for_psram(void)
{
//TODO: IDF-6495, to change back to burst cmd
//Config Write CMD phase for SPI0 to access PSRAM
psram_ctrlr_ll_set_wr_cmd(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_PSRAM_WR_CMD_BITLEN, AP_HEX_PSRAM_SYNC_WRITE);
//TODO: IDF-6495, to change back to burst cmd
//Config Read CMD phase for SPI0 to access PSRAM
psram_ctrlr_ll_set_rd_cmd(PSRAM_CTRLR_LL_MSPI_ID_2, AP_HEX_PSRAM_RD_CMD_BITLEN, AP_HEX_PSRAM_SYNC_READ);
@ -363,26 +375,28 @@ esp_err_t esp_psram_impl_enable(void)
PSRAM_RCC_ATOMIC() {
psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_reset_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2);
psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_XTAL);
psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_XTAL);
psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_MPLL);
psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_MPLL);
}
mspi_timing_ll_pin_drv_set(2);
mspi_timing_ll_enable_dqs(true);
s_set_psram_cs_timing();
#if CONFIG_SPIRAM_ECC_ENABLE
s_configure_psram_ecc();
#endif
//enter MSPI slow mode to init PSRAM device registers
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, 2);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, 2);
//TODO: IDF-6495, to add back
// psram_ctrlr_ll_enable_dll(PSRAM_CTRLR_LL_MSPI_ID_2, true);
// psram_ctrlr_ll_enable_dll(PSRAM_CTRLR_LL_MSPI_ID_3, true);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, 40);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, 40);
psram_ctrlr_ll_enable_dll(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_dll(PSRAM_CTRLR_LL_MSPI_ID_3, true);
static hex_psram_mode_reg_t mode_reg = {};
mode_reg.mr0.lt = 1;
mode_reg.mr0.read_latency = 2;
mode_reg.mr0.read_latency = AP_HEX_PSRAM_RD_LATENCY;
mode_reg.mr0.drive_str = 0;
mode_reg.mr4.wr_latency = 2;
mode_reg.mr4.wr_latency = AP_HEX_PSRAM_WR_LATENCY;
mode_reg.mr8.bl = 3;
mode_reg.mr8.bt = 0;
mode_reg.mr8.rbx = 1;
@ -404,7 +418,18 @@ esp_err_t esp_psram_impl_enable(void)
mode_reg.mr2.density == 0x7 ? PSRAM_SIZE_32MB :
mode_reg.mr2.density == 0x6 ? PSRAM_SIZE_64MB : 0;
#if CONFIG_SPIRAM_SPEED_250M
if (mode_reg.mr2.density == 0x7) {
ESP_EARLY_LOGE(TAG, "PSRAM Not support 250MHz speed");
return ESP_ERR_NOT_SUPPORTED;
}
#endif
s_config_mspi_for_psram();
mspi_timing_psram_tuning();
psram_ctrlr_ll_enable_variable_dummy(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_enable_variable_dummy(PSRAM_CTRLR_LL_MSPI_ID_3, true);
return ESP_OK;
}

View File

@ -30,6 +30,10 @@ menu "PSRAM config"
help
Select the speed for the PSRAM chip.
config SPIRAM_SPEED_200M
depends on IDF_EXPERIMENTAL_FEATURES
bool "200MHz clock speed"
config SPIRAM_SPEED_20M
bool "20MHz clock speed"
endchoice
@ -37,6 +41,8 @@ menu "PSRAM config"
config SPIRAM_SPEED
int
default 20 if SPIRAM_SPEED_20M
default 100 if SPIRAM_SPEED_100M
default 200 if SPIRAM_SPEED_200M
config SPIRAM_ECC_ENABLE
bool "Enable PSRAM ECC"

View File

@ -22,7 +22,7 @@
__attribute__((unused)) const static char *TAG = "PSRAM";
TEST_CASE("test psram heap allocable", "[psram]")
static void s_test_psram_heap_allocable(void)
{
size_t largest_size = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
ESP_LOGI(TAG, "largest size is %zu", largest_size);
@ -46,6 +46,18 @@ TEST_CASE("test psram heap allocable", "[psram]")
free(ext_buffer);
}
TEST_CASE("test psram heap allocable", "[psram]")
{
s_test_psram_heap_allocable();
}
TEST_CASE("stress test psram heap allocable", "[psram][manual][ignore]")
{
for (int times = 0; times < 50; times++) {
s_test_psram_heap_allocable();
}
}
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA
#include "esp_partition.h"
#include "driver/gptimer.h"

View File

@ -0,0 +1,190 @@
/*
* SPDX-FileCopyrightText: 2023-2024 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 <stdint.h>
#include <stdbool.h>
#include "hal/assert.h"
#include "soc/soc.h"
#include "soc/iomux_mspi_pin_reg.h"
#include "soc/iomux_mspi_pin_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* MSPI DQS ID
*/
typedef enum {
MSPI_LL_DQS_ID_0,
MSPI_LL_DQS_ID_1,
} mspi_ll_dqs_id_t;
/**
* MSPI DQS Phase
*/
typedef enum {
MSPI_LL_DQS_PHASE_67_5,
MSPI_LL_DQS_PHASE_78_75,
MSPI_LL_DQS_PHASE_90,
MSPI_LL_DQS_PHASE_101_25,
MSPI_LL_DQS_PHASE_MAX,
} mspi_ll_dqs_phase_t;
/**
* MSPI Delayline
*
* @note The Sequence of these enums should not be changed
*/
typedef enum {
MSPI_LL_PIN_D = 0,
MSPI_LL_PIN_Q,
MSPI_LL_PIN_WP,
MSPI_LL_PIN_HD,
MSPI_LL_PIN_D4,
MSPI_LL_PIN_D5,
MSPI_LL_PIN_D6,
MSPI_LL_PIN_D7,
MSPI_LL_PIN_DQS0,
MSPI_LL_PIN_CLK,
MSPI_LL_PIN_CS,
MSPI_LL_PIN_D8,
MSPI_LL_PIN_D9,
MSPI_LL_PIN_D10,
MSPI_LL_PIN_D11,
MSPI_LL_PIN_D12,
MSPI_LL_PIN_D13,
MSPI_LL_PIN_D14,
MSPI_LL_PIN_D15,
MSPI_LL_PIN_DQS1,
MSPI_LL_PIN_MAX,
} mspi_ll_pin_t;
/**
* Set all MSPI DQS phase
*
* @param dqs_id DQS ID
* @param phase Phase
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_dqs_phase(mspi_ll_dqs_id_t dqs_id, mspi_ll_dqs_phase_t phase)
{
HAL_ASSERT(dqs_id < 2);
if (dqs_id == MSPI_LL_DQS_ID_0) {
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_PHASE, phase);
} else {
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQS_1_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_1_PHASE, phase);
}
}
/**
* Set all MSPI delayline
*
* @param pin Pin
* @param delayline Delayline
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_set_delayline(mspi_ll_pin_t pin, uint8_t delayline)
{
HAL_ASSERT(pin < MSPI_LL_PIN_MAX);
switch (pin) {
case MSPI_LL_PIN_DQS0:
MSPI_IOMUX.psram_pin_group.dqs0.reg_psram_dqs_delay_90 = delayline;
MSPI_IOMUX.psram_pin_group.dqs0.reg_psram_dqs_delay_270 = delayline;
break;
case MSPI_LL_PIN_DQS1:
MSPI_IOMUX.psram_pin_group.dqs1.reg_psram_dqs_delay_90 = delayline;
MSPI_IOMUX.psram_pin_group.dqs1.reg_psram_dqs_delay_270 = delayline;
break;
case MSPI_LL_PIN_D:
case MSPI_LL_PIN_Q:
case MSPI_LL_PIN_WP:
case MSPI_LL_PIN_HD:
case MSPI_LL_PIN_D4:
case MSPI_LL_PIN_D5:
case MSPI_LL_PIN_D6:
case MSPI_LL_PIN_D7:
MSPI_IOMUX.psram_pin_group.pin_group0[pin].reg_psram_pin_dlc = delayline;
break;
case MSPI_LL_PIN_CLK:
case MSPI_LL_PIN_CS:
case MSPI_LL_PIN_D8:
case MSPI_LL_PIN_D9:
case MSPI_LL_PIN_D10:
case MSPI_LL_PIN_D11:
case MSPI_LL_PIN_D12:
case MSPI_LL_PIN_D13:
case MSPI_LL_PIN_D14:
case MSPI_LL_PIN_D15:
pin = (mspi_ll_pin_t)(pin - MSPI_LL_PIN_CLK);
MSPI_IOMUX.psram_pin_group.pin_group1[pin].reg_psram_pin_dlc = delayline;
break;
default:
HAL_ASSERT(false);
break;
}
}
/**
* Enable DQS
*
* @param en Enable/disable
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_enable_dqs(bool en)
{
if (en) {
REG_SET_BIT(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_XPD);
REG_SET_BIT(IOMUX_MSPI_PIN_PSRAM_DQS_1_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_1_XPD);
} else {
REG_CLR_BIT(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_XPD);
REG_CLR_BIT(IOMUX_MSPI_PIN_PSRAM_DQS_1_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_1_XPD);
}
}
/**
* Set all MSPI pin drive
*
* @param drv Pin drive
*/
__attribute__((always_inline))
static inline void mspi_timing_ll_pin_drv_set(uint8_t drv)
{
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_D_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_Q_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_Q_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_WP_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_WP_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_HOLD_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_HOLD_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ4_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ4_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ5_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ5_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ6_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ6_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ7_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ7_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ8_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ8_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ9_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ9_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ10_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ10_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ11_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ11_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ12_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ12_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ13_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ13_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ14_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ14_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQ15_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQ15_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQS_0_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_0_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_DQS_1_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_DQS_1_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_CK_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_CK_DRV, drv);
REG_SET_FIELD(IOMUX_MSPI_PIN_PSRAM_CS_PIN0_REG, IOMUX_MSPI_PIN_REG_PSRAM_CS_DRV, drv);
}
#ifdef __cplusplus
}
#endif

View File

@ -16,8 +16,11 @@
#include <stdbool.h>
#include <sys/param.h>
#include "hal/assert.h"
#include "hal/misc.h"
#include "soc/spi_mem_s_struct.h"
#include "soc/spi_mem_s_reg.h"
#include "soc/spi1_mem_s_reg.h"
#include "soc/spi1_mem_s_struct.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/clk_tree_defs.h"
#include "rom/opi_flash.h"
@ -26,13 +29,15 @@
extern "C" {
#endif
#define PSRAM_CTRLR_LL_MSPI_ID_2 2
#define PSRAM_CTRLR_LL_MSPI_ID_3 3
#define PSRAM_CTRLR_LL_MSPI_ID_2 2
#define PSRAM_CTRLR_LL_MSPI_ID_3 3
#define PSRAM_CTRLR_LL_PMS_REGION_NUMS 4
#define PSRAM_CTRLR_LL_PMS_ATTR_WRITABLE (1<<0)
#define PSRAM_CTRLR_LL_PMS_ATTR_READABLE (1<<1)
#define PSRAM_CTRLR_LL_FIFO_MAX_BYTES 64
/**
* @brief Set PSRAM write cmd
@ -134,8 +139,11 @@ static inline void psram_ctrlr_ll_set_rd_dummy(uint32_t mspi_id, uint32_t dummy_
__attribute__((always_inline))
static inline void psram_ctrlr_ll_enable_variable_dummy(uint32_t mspi_id, bool en)
{
(void)mspi_id;
SPIMEM2.smem_ddr.smem_var_dummy = en;
if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_2) {
SPIMEM2.smem_ddr.smem_var_dummy = en;
} else if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_3) {
SPIMEM3.ddr.fmem_var_dummy = en;
}
}
/**
@ -350,15 +358,20 @@ static inline void psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph
/**
* @brief Set PSRAM core clock
*
* @param mspi_id mspi_id
* @param core_clk_mhz core clock mhz
* @param mspi_id mspi_id
* @param freqdiv Divider value
*/
__attribute__((always_inline))
static inline void psram_ctrlr_ll_set_core_clock(uint8_t spi_num, uint32_t core_clk_mhz)
static inline void psram_ctrlr_ll_set_core_clock(uint8_t spi_num, uint32_t freqdiv)
{
//TODO: IDF-7517
HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_core_clk_en = 1;
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl00, reg_psram_core_clk_div_num, freqdiv - 1);
}
/// 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 psram_ctrlr_ll_set_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; psram_ctrlr_ll_set_core_clock(__VA_ARGS__)
/**
* @brief Set PSRAM bus clock
*
@ -368,12 +381,20 @@ static inline void psram_ctrlr_ll_set_core_clock(uint8_t spi_num, uint32_t core_
__attribute__((always_inline))
static inline void psram_ctrlr_ll_set_bus_clock(uint32_t mspi_id, uint32_t freqdiv)
{
(void)mspi_id;
if (freqdiv == 1) {
WRITE_PERI_REG(SPI_MEM_S_SRAM_CLK_REG, SPI_MEM_S_SCLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI_MEM_S_SCLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI_MEM_S_SCLKCNT_H_S)) | ((freqdiv - 1) << SPI_MEM_S_SCLKCNT_L_S);
WRITE_PERI_REG(SPI_MEM_S_SRAM_CLK_REG, freqbits);
if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_2) {
if (freqdiv == 1) {
WRITE_PERI_REG(SPI_MEM_S_SRAM_CLK_REG, SPI_MEM_S_SCLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI_MEM_S_SCLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI_MEM_S_SCLKCNT_H_S)) | ((freqdiv - 1) << SPI_MEM_S_SCLKCNT_L_S);
WRITE_PERI_REG(SPI_MEM_S_SRAM_CLK_REG, freqbits);
}
} else if (mspi_id == PSRAM_CTRLR_LL_MSPI_ID_3) {
if (freqdiv == 1) {
WRITE_PERI_REG(SPI1_MEM_S_CLOCK_REG, SPI1_MEM_S_CLK_EQU_SYSCLK);
} else {
uint32_t freqbits = (((freqdiv - 1) << SPI1_MEM_S_CLKCNT_N_S)) | (((freqdiv / 2 - 1) << SPI1_MEM_S_CLKCNT_H_S)) | ((freqdiv - 1) << SPI1_MEM_S_CLKCNT_L_S);
WRITE_PERI_REG(SPI1_MEM_S_CLOCK_REG, freqbits);
}
}
}

View File

@ -627,6 +627,11 @@ static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_
// Not supported on esp32p4
}
static inline void spimem_flash_ll_set_extra_dummy(spi_mem_dev_t *dev, uint32_t extra_dummy)
{
//for compatibility
}
/**
* Get the spi flash source clock frequency. Used for calculating
* the divider parameters.

View File

@ -1011,6 +1011,14 @@ config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_SPI_MEM_SUPPORT_TIMING_TUNING
bool
default y
config SOC_MEMSPI_TIMING_TUNING_BY_DQS
bool
default y
config SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED
bool
default y

View File

@ -169,35 +169,6 @@
#define SPI_D7_GPIO_NUM 36
#define SPI_DQS_GPIO_NUM 37
#define PIN_FUNC_SPI_DEBUG 4
#define FLASH_CS_DEBUG_GPIO_NUM 49
#define FLASH_Q_DEBUG_GPIO_NUM 50
#define FLASH_WP_DEBUG_GPIO_NUM 51
#define FLASH_HD_DEBUG_GPIO_NUM 52
#define FLASH_CLK_DEBUG_GPIO_NUM 53
#define FLASH_D_DEBUG_GPIO_NUM 54
#define PSRAM_D_DEBUG_GPIO_NUM 28
#define PSRAM_Q_DEBUG_GPIO_NUM 29
#define PSRAM_WP_DEBUG_GPIO_NUM 30
#define PSRAM_HOLD_DEBUG_GPIO_NUM 31
#define PSRAM_DP4_DEBUG_GPIO_NUM 32
#define PSRAM_DP5_DEBUG_GPIO_NUM 33
#define PSRAM_DP6_DEBUG_GPIO_NUM 34
#define PSRAM_DP7_DEBUG_GPIO_NUM 35
#define PSRAM_DQS0_DEBUG_GPIO_NUM 36
#define PSRAM_CLK_DEBUG_GPIO_NUM 22
#define PSRAM_CS_DEBUG_GPIO_NUM 23
#define PSRAM_DP8_DEBUG_GPIO_NUM 39
#define PSRAM_DP9_DEBUG_GPIO_NUM 40
#define PSRAM_DP10_DEBUG_GPIO_NUM 41
#define PSRAM_DP11_DEBUG_GPIO_NUM 42
#define PSRAM_DP12_DEBUG_GPIO_NUM 43
#define PSRAM_DP13_DEBUG_GPIO_NUM 44
#define PSRAM_DP14_DEBUG_GPIO_NUM 45
#define PSRAM_DP15_DEBUG_GPIO_NUM 46
#define PSRAM_DQS1_DEBUG_GPIO_NUM 47
#define SD_CLK_GPIO_NUM 43
#define SD_CMD_GPIO_NUM 44
#define SD_DATA0_GPIO_NUM 39

View File

@ -1386,6 +1386,39 @@ extern "C" {
#define IOMUX_MSPI_PIN_REG_PSRAM_DQS_1_DELAY_270_V 0x0000000FU
#define IOMUX_MSPI_PIN_REG_PSRAM_DQS_1_DELAY_270_S 17
/**
* Usage:
* PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[FLASH_CS_DEBUG_GPIO_NUM], PIN_FUNC_SPI_DEBUG);
*/
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) REG_SET_FIELD(PIN_NAME, MCU_SEL, FUNC)
#define PIN_FUNC_SPI_DEBUG 4
#define FLASH_CS_DEBUG_GPIO_NUM 49
#define FLASH_Q_DEBUG_GPIO_NUM 50
#define FLASH_WP_DEBUG_GPIO_NUM 51
#define FLASH_HD_DEBUG_GPIO_NUM 52
#define FLASH_CLK_DEBUG_GPIO_NUM 53
#define FLASH_D_DEBUG_GPIO_NUM 54
#define PSRAM_D_DEBUG_GPIO_NUM 28
#define PSRAM_Q_DEBUG_GPIO_NUM 29
#define PSRAM_WP_DEBUG_GPIO_NUM 30
#define PSRAM_HOLD_DEBUG_GPIO_NUM 31
#define PSRAM_DP4_DEBUG_GPIO_NUM 32
#define PSRAM_DP5_DEBUG_GPIO_NUM 33
#define PSRAM_DP6_DEBUG_GPIO_NUM 34
#define PSRAM_DP7_DEBUG_GPIO_NUM 35
#define PSRAM_DQS0_DEBUG_GPIO_NUM 36
#define PSRAM_CLK_DEBUG_GPIO_NUM 22
#define PSRAM_CS_DEBUG_GPIO_NUM 23
#define PSRAM_DP8_DEBUG_GPIO_NUM 39
#define PSRAM_DP9_DEBUG_GPIO_NUM 40
#define PSRAM_DP10_DEBUG_GPIO_NUM 41
#define PSRAM_DP11_DEBUG_GPIO_NUM 42
#define PSRAM_DP12_DEBUG_GPIO_NUM 43
#define PSRAM_DP13_DEBUG_GPIO_NUM 44
#define PSRAM_DP14_DEBUG_GPIO_NUM 45
#define PSRAM_DP15_DEBUG_GPIO_NUM 46
#define PSRAM_DQS1_DEBUG_GPIO_NUM 47
#ifdef __cplusplus
}
#endif

View File

@ -219,829 +219,97 @@ typedef union {
} iomux_mspi_pin_flash_d_pin0_reg_t;
/** Group: psram_d_pin */
/** Type of psram_d_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
/** psram_pin */
typedef union {
struct {
/** reg_psram_d_dli : R/W; bitpos: [3:0]; default: 0;
* psram d dli
/** reg_psram_pin_dli : R/W; bitpos: [3:0]; default: 0;
* psram pin dli
*/
uint32_t reg_psram_d_dli:4;
/** reg_psram_d_dlc : R/W; bitpos: [7:4]; default: 0;
* psram d dlc
uint32_t reg_psram_pin_dli:4;
/** reg_psram_pin_dlc : R/W; bitpos: [7:4]; default: 0;
* psram pin dlc
*/
uint32_t reg_psram_d_dlc:4;
/** reg_psram_d_hys : R/W; bitpos: [8]; default: 0;
* psram d hys
uint32_t reg_psram_pin_dlc:4;
/** reg_psram_pin_hys : R/W; bitpos: [8]; default: 0;
* psram pin hys
*/
uint32_t reg_psram_d_hys:1;
/** reg_psram_d_ie : R/W; bitpos: [9]; default: 0;
uint32_t reg_psram_pin_hys:1;
/** reg_psram_pin_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_d_ie:1;
/** reg_psram_d_wpu : R/W; bitpos: [10]; default: 0;
* psram d wpu
uint32_t reg_psram_pin_ie:1;
/** reg_psram_pin_wpu : R/W; bitpos: [10]; default: 0;
* psram pin wpu
*/
uint32_t reg_psram_d_wpu:1;
/** reg_psram_d_wpd : R/W; bitpos: [11]; default: 0;
* psram d wpd
uint32_t reg_psram_pin_wpu:1;
/** reg_psram_pin_wpd : R/W; bitpos: [11]; default: 0;
* psram pin wpd
*/
uint32_t reg_psram_d_wpd:1;
uint32_t reg_psram_pin_wpd:1;
/** reg_psram_d_drv : R/W; bitpos: [13:12]; default: 0;
* psram d drv
* psram pin drv
*/
uint32_t reg_psram_d_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_d_pin0_reg_t;
} iomux_mspi_pin_psram_pin_reg_t;
/** Group: psram_q_pin */
/** Type of psram_q_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
/** psram_dqs_pin */
typedef union {
struct {
/** reg_psram_q_dli : R/W; bitpos: [3:0]; default: 0;
* psram q dli
/** reg_psram_dqs_xpd : R/W; bitpos: [0]; default: 0;
* psram xpd dqs
*/
uint32_t reg_psram_q_dli:4;
/** reg_psram_q_dlc : R/W; bitpos: [7:4]; default: 0;
* psram q dlc
uint32_t reg_psram_dqs_xpd:1;
/** reg_psram_dqs_phase : R/W; bitpos: [2:1]; default: 0;
* psram dqs phase
*/
uint32_t reg_psram_q_dlc:4;
/** reg_psram_q_hys : R/W; bitpos: [8]; default: 0;
* psram q hys
uint32_t reg_psram_dqs_phase:2;
/** reg_psram_dqs_dli : R/W; bitpos: [6:3]; default: 0;
* psram dqs dli
*/
uint32_t reg_psram_q_hys:1;
/** reg_psram_q_ie : R/W; bitpos: [9]; default: 0;
uint32_t reg_psram_dqs_dli:4;
/** reg_psram_dqs_delay_90 : R/W; bitpos: [10:7]; default: 0;
* psram dqs delay 90
*/
uint32_t reg_psram_dqs_delay_90:4;
/** reg_psram_dqs_hys : R/W; bitpos: [11]; default: 0;
* psram dqs hys
*/
uint32_t reg_psram_dqs_hys:1;
/** reg_psram_dqs_ie : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t reg_psram_q_ie:1;
/** reg_psram_q_wpu : R/W; bitpos: [10]; default: 0;
* psram q wpu
uint32_t reg_psram_dqs_ie:1;
/** reg_psram_dqs_wpu : R/W; bitpos: [13]; default: 0;
* psram dqs wpu
*/
uint32_t reg_psram_q_wpu:1;
/** reg_psram_q_wpd : R/W; bitpos: [11]; default: 0;
* psram q wpd
uint32_t reg_psram_dqs_wpu:1;
/** reg_psram_dqs_wpd : R/W; bitpos: [14]; default: 0;
* psram dqs wpd
*/
uint32_t reg_psram_q_wpd:1;
/** reg_psram_q_drv : R/W; bitpos: [13:12]; default: 0;
* psram q drv
uint32_t reg_psram_dqs_wpd:1;
/** reg_psram_dqs_drv : R/W; bitpos: [16:15]; default: 0;
* psram dqs drv
*/
uint32_t reg_psram_q_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_q_pin0_reg_t;
/** Group: psram_wp_pin */
/** Type of psram_wp_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_wp_dli : R/W; bitpos: [3:0]; default: 0;
* psram wp dli
uint32_t reg_psram_dqs_drv:2;
/** reg_psram_dqs_delay_270 : R/W; bitpos: [20:17]; default: 0;
* psram dqs delay 270
*/
uint32_t reg_psram_wp_dli:4;
/** reg_psram_wp_dlc : R/W; bitpos: [7:4]; default: 0;
* psram wp dlc
*/
uint32_t reg_psram_wp_dlc:4;
/** reg_psram_wp_hys : R/W; bitpos: [8]; default: 0;
* psram wp hys
*/
uint32_t reg_psram_wp_hys:1;
/** reg_psram_wp_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_wp_ie:1;
/** reg_psram_wp_wpu : R/W; bitpos: [10]; default: 0;
* psram wp wpu
*/
uint32_t reg_psram_wp_wpu:1;
/** reg_psram_wp_wpd : R/W; bitpos: [11]; default: 0;
* psram wp wpd
*/
uint32_t reg_psram_wp_wpd:1;
/** reg_psram_wp_drv : R/W; bitpos: [13:12]; default: 0;
* psram wp drv
*/
uint32_t reg_psram_wp_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_wp_pin0_reg_t;
/** Group: psram_hold_pin */
/** Type of psram_hold_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_hold_dli : R/W; bitpos: [3:0]; default: 0;
* psram hold dli
*/
uint32_t reg_psram_hold_dli:4;
/** reg_psram_hold_dlc : R/W; bitpos: [7:4]; default: 0;
* psram hold dlc
*/
uint32_t reg_psram_hold_dlc:4;
/** reg_psram_hold_hys : R/W; bitpos: [8]; default: 0;
* psram hold hys
*/
uint32_t reg_psram_hold_hys:1;
/** reg_psram_hold_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_hold_ie:1;
/** reg_psram_hold_wpu : R/W; bitpos: [10]; default: 0;
* psram hold wpu
*/
uint32_t reg_psram_hold_wpu:1;
/** reg_psram_hold_wpd : R/W; bitpos: [11]; default: 0;
* psram hold wpd
*/
uint32_t reg_psram_hold_wpd:1;
/** reg_psram_hold_drv : R/W; bitpos: [13:12]; default: 0;
* psram hold drv
*/
uint32_t reg_psram_hold_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_hold_pin0_reg_t;
/** Group: psram_dq4_pin */
/** Type of psram_dq4_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq4_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq4 dli
*/
uint32_t reg_psram_dq4_dli:4;
/** reg_psram_dq4_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq4 dlc
*/
uint32_t reg_psram_dq4_dlc:4;
/** reg_psram_dq4_hys : R/W; bitpos: [8]; default: 0;
* psram dq4 hys
*/
uint32_t reg_psram_dq4_hys:1;
/** reg_psram_dq4_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq4_ie:1;
/** reg_psram_dq4_wpu : R/W; bitpos: [10]; default: 0;
* psram dq4 wpu
*/
uint32_t reg_psram_dq4_wpu:1;
/** reg_psram_dq4_wpd : R/W; bitpos: [11]; default: 0;
* psram dq4 wpd
*/
uint32_t reg_psram_dq4_wpd:1;
/** reg_psram_dq4_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq4 drv
*/
uint32_t reg_psram_dq4_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq4_pin0_reg_t;
/** Group: psram_dq5_pin */
/** Type of psram_dq5_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq5_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq5 dli
*/
uint32_t reg_psram_dq5_dli:4;
/** reg_psram_dq5_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq5 dlc
*/
uint32_t reg_psram_dq5_dlc:4;
/** reg_psram_dq5_hys : R/W; bitpos: [8]; default: 0;
* psram dq5 hys
*/
uint32_t reg_psram_dq5_hys:1;
/** reg_psram_dq5_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq5_ie:1;
/** reg_psram_dq5_wpu : R/W; bitpos: [10]; default: 0;
* psram dq5 wpu
*/
uint32_t reg_psram_dq5_wpu:1;
/** reg_psram_dq5_wpd : R/W; bitpos: [11]; default: 0;
* psram dq5 wpd
*/
uint32_t reg_psram_dq5_wpd:1;
/** reg_psram_dq5_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq5 drv
*/
uint32_t reg_psram_dq5_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq5_pin0_reg_t;
/** Group: psram_dq6_pin */
/** Type of psram_dq6_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq6_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq6 dli
*/
uint32_t reg_psram_dq6_dli:4;
/** reg_psram_dq6_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq6 dlc
*/
uint32_t reg_psram_dq6_dlc:4;
/** reg_psram_dq6_hys : R/W; bitpos: [8]; default: 0;
* psram dq6 hys
*/
uint32_t reg_psram_dq6_hys:1;
/** reg_psram_dq6_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq6_ie:1;
/** reg_psram_dq6_wpu : R/W; bitpos: [10]; default: 0;
* psram dq6 wpu
*/
uint32_t reg_psram_dq6_wpu:1;
/** reg_psram_dq6_wpd : R/W; bitpos: [11]; default: 0;
* psram dq6 wpd
*/
uint32_t reg_psram_dq6_wpd:1;
/** reg_psram_dq6_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq6 drv
*/
uint32_t reg_psram_dq6_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq6_pin0_reg_t;
/** Group: psram_dq7_pin */
/** Type of psram_dq7_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq7_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq7 dli
*/
uint32_t reg_psram_dq7_dli:4;
/** reg_psram_dq7_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq7 dlc
*/
uint32_t reg_psram_dq7_dlc:4;
/** reg_psram_dq7_hys : R/W; bitpos: [8]; default: 0;
* psram dq7 hys
*/
uint32_t reg_psram_dq7_hys:1;
/** reg_psram_dq7_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq7_ie:1;
/** reg_psram_dq7_wpu : R/W; bitpos: [10]; default: 0;
* psram dq7 wpu
*/
uint32_t reg_psram_dq7_wpu:1;
/** reg_psram_dq7_wpd : R/W; bitpos: [11]; default: 0;
* psram dq7 wpd
*/
uint32_t reg_psram_dq7_wpd:1;
/** reg_psram_dq7_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq7 drv
*/
uint32_t reg_psram_dq7_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq7_pin0_reg_t;
/** Group: psram_dqs_0_pin */
/** Type of psram_dqs_0_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dqs_0_xpd : R/W; bitpos: [0]; default: 0;
* psram xpd dqs0
*/
uint32_t reg_psram_dqs_0_xpd:1;
/** reg_psram_dqs_0_phase : R/W; bitpos: [2:1]; default: 0;
* psram dqs0 phase
*/
uint32_t reg_psram_dqs_0_phase:2;
/** reg_psram_dqs_0_dli : R/W; bitpos: [6:3]; default: 0;
* psram dqs0 dli
*/
uint32_t reg_psram_dqs_0_dli:4;
/** reg_psram_dqs_0_delay_90 : R/W; bitpos: [10:7]; default: 0;
* psram dqs0 delay 90
*/
uint32_t reg_psram_dqs_0_delay_90:4;
/** reg_psram_dqs_0_hys : R/W; bitpos: [11]; default: 0;
* psram dqs0 hys
*/
uint32_t reg_psram_dqs_0_hys:1;
/** reg_psram_dqs_0_ie : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t reg_psram_dqs_0_ie:1;
/** reg_psram_dqs_0_wpu : R/W; bitpos: [13]; default: 0;
* psram dqs0 wpu
*/
uint32_t reg_psram_dqs_0_wpu:1;
/** reg_psram_dqs_0_wpd : R/W; bitpos: [14]; default: 0;
* psram dqs0 wpd
*/
uint32_t reg_psram_dqs_0_wpd:1;
/** reg_psram_dqs_0_drv : R/W; bitpos: [16:15]; default: 0;
* psram dqs0 drv
*/
uint32_t reg_psram_dqs_0_drv:2;
/** reg_psram_dqs_0_delay_270 : R/W; bitpos: [20:17]; default: 0;
* psram dqs0 delay 270
*/
uint32_t reg_psram_dqs_0_delay_270:4;
uint32_t reg_psram_dqs_delay_270:4;
uint32_t reserved_21:11;
};
uint32_t val;
} iomux_mspi_pin_psram_dqs_0_pin0_reg_t;
/** Group: psram_ck_pin */
/** Type of psram_ck_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_ck_dli : R/W; bitpos: [3:0]; default: 0;
* psram ck dli
*/
uint32_t reg_psram_ck_dli:4;
/** reg_psram_ck_dlc : R/W; bitpos: [7:4]; default: 0;
* psram ck dlc
*/
uint32_t reg_psram_ck_dlc:4;
/** reg_psram_ck_hys : R/W; bitpos: [8]; default: 0;
* psram ck hys
*/
uint32_t reg_psram_ck_hys:1;
/** reg_psram_ck_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_ck_ie:1;
/** reg_psram_ck_wpu : R/W; bitpos: [10]; default: 0;
* psram ck wpu
*/
uint32_t reg_psram_ck_wpu:1;
/** reg_psram_ck_wpd : R/W; bitpos: [11]; default: 0;
* psram ck wpd
*/
uint32_t reg_psram_ck_wpd:1;
/** reg_psram_ck_drv : R/W; bitpos: [13:12]; default: 0;
* psram ck drv
*/
uint32_t reg_psram_ck_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_ck_pin0_reg_t;
/** Group: psram_cs_pin */
/** Type of psram_cs_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_cs_dli : R/W; bitpos: [3:0]; default: 0;
* psram cs dli
*/
uint32_t reg_psram_cs_dli:4;
/** reg_psram_cs_dlc : R/W; bitpos: [7:4]; default: 0;
* psram cs dlc
*/
uint32_t reg_psram_cs_dlc:4;
/** reg_psram_cs_hys : R/W; bitpos: [8]; default: 0;
* psram cs hys
*/
uint32_t reg_psram_cs_hys:1;
/** reg_psram_cs_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_cs_ie:1;
/** reg_psram_cs_wpu : R/W; bitpos: [10]; default: 0;
* psram cs wpu
*/
uint32_t reg_psram_cs_wpu:1;
/** reg_psram_cs_wpd : R/W; bitpos: [11]; default: 0;
* psram cs wpd
*/
uint32_t reg_psram_cs_wpd:1;
/** reg_psram_cs_drv : R/W; bitpos: [13:12]; default: 0;
* psram cs drv
*/
uint32_t reg_psram_cs_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_cs_pin0_reg_t;
/** Group: psram_dq8_pin */
/** Type of psram_dq8_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq8_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq8 dli
*/
uint32_t reg_psram_dq8_dli:4;
/** reg_psram_dq8_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq8 dlc
*/
uint32_t reg_psram_dq8_dlc:4;
/** reg_psram_dq8_hys : R/W; bitpos: [8]; default: 0;
* psram dq8 hys
*/
uint32_t reg_psram_dq8_hys:1;
/** reg_psram_dq8_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq8_ie:1;
/** reg_psram_dq8_wpu : R/W; bitpos: [10]; default: 0;
* psram dq8 wpu
*/
uint32_t reg_psram_dq8_wpu:1;
/** reg_psram_dq8_wpd : R/W; bitpos: [11]; default: 0;
* psram dq8 wpd
*/
uint32_t reg_psram_dq8_wpd:1;
/** reg_psram_dq8_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq8 drv
*/
uint32_t reg_psram_dq8_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq8_pin0_reg_t;
/** Group: psram_dq9_pin */
/** Type of psram_dq9_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq9_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq9 dli
*/
uint32_t reg_psram_dq9_dli:4;
/** reg_psram_dq9_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq9 dlc
*/
uint32_t reg_psram_dq9_dlc:4;
/** reg_psram_dq9_hys : R/W; bitpos: [8]; default: 0;
* psram dq9 hys
*/
uint32_t reg_psram_dq9_hys:1;
/** reg_psram_dq9_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq9_ie:1;
/** reg_psram_dq9_wpu : R/W; bitpos: [10]; default: 0;
* psram dq9 wpu
*/
uint32_t reg_psram_dq9_wpu:1;
/** reg_psram_dq9_wpd : R/W; bitpos: [11]; default: 0;
* psram dq9 wpd
*/
uint32_t reg_psram_dq9_wpd:1;
/** reg_psram_dq9_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq9 drv
*/
uint32_t reg_psram_dq9_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq9_pin0_reg_t;
/** Group: psram_dq10_pin */
/** Type of psram_dq10_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq10_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq10 dli
*/
uint32_t reg_psram_dq10_dli:4;
/** reg_psram_dq10_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq10 dlc
*/
uint32_t reg_psram_dq10_dlc:4;
/** reg_psram_dq10_hys : R/W; bitpos: [8]; default: 0;
* psram dq10 hys
*/
uint32_t reg_psram_dq10_hys:1;
/** reg_psram_dq10_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq10_ie:1;
/** reg_psram_dq10_wpu : R/W; bitpos: [10]; default: 0;
* psram dq10 wpu
*/
uint32_t reg_psram_dq10_wpu:1;
/** reg_psram_dq10_wpd : R/W; bitpos: [11]; default: 0;
* psram dq10 wpd
*/
uint32_t reg_psram_dq10_wpd:1;
/** reg_psram_dq10_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq10 drv
*/
uint32_t reg_psram_dq10_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq10_pin0_reg_t;
/** Group: psram_dq11_pin */
/** Type of psram_dq11_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq11_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq11 dli
*/
uint32_t reg_psram_dq11_dli:4;
/** reg_psram_dq11_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq11 dlc
*/
uint32_t reg_psram_dq11_dlc:4;
/** reg_psram_dq11_hys : R/W; bitpos: [8]; default: 0;
* psram dq11 hys
*/
uint32_t reg_psram_dq11_hys:1;
/** reg_psram_dq11_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq11_ie:1;
/** reg_psram_dq11_wpu : R/W; bitpos: [10]; default: 0;
* psram dq11 wpu
*/
uint32_t reg_psram_dq11_wpu:1;
/** reg_psram_dq11_wpd : R/W; bitpos: [11]; default: 0;
* psram dq11 wpd
*/
uint32_t reg_psram_dq11_wpd:1;
/** reg_psram_dq11_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq11 drv
*/
uint32_t reg_psram_dq11_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq11_pin0_reg_t;
/** Group: psram_dq12_pin */
/** Type of psram_dq12_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq12_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq12 dli
*/
uint32_t reg_psram_dq12_dli:4;
/** reg_psram_dq12_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq12 dlc
*/
uint32_t reg_psram_dq12_dlc:4;
/** reg_psram_dq12_hys : R/W; bitpos: [8]; default: 0;
* psram dq12 hys
*/
uint32_t reg_psram_dq12_hys:1;
/** reg_psram_dq12_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq12_ie:1;
/** reg_psram_dq12_wpu : R/W; bitpos: [10]; default: 0;
* psram dq12 wpu
*/
uint32_t reg_psram_dq12_wpu:1;
/** reg_psram_dq12_wpd : R/W; bitpos: [11]; default: 0;
* psram dq12 wpd
*/
uint32_t reg_psram_dq12_wpd:1;
/** reg_psram_dq12_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq12 drv
*/
uint32_t reg_psram_dq12_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq12_pin0_reg_t;
/** Group: psram_dq13_pin */
/** Type of psram_dq13_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq13_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq13 dli
*/
uint32_t reg_psram_dq13_dli:4;
/** reg_psram_dq13_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq13 dlc
*/
uint32_t reg_psram_dq13_dlc:4;
/** reg_psram_dq13_hys : R/W; bitpos: [8]; default: 0;
* psram dq13 hys
*/
uint32_t reg_psram_dq13_hys:1;
/** reg_psram_dq13_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq13_ie:1;
/** reg_psram_dq13_wpu : R/W; bitpos: [10]; default: 0;
* psram dq13 wpu
*/
uint32_t reg_psram_dq13_wpu:1;
/** reg_psram_dq13_wpd : R/W; bitpos: [11]; default: 0;
* psram dq13 wpd
*/
uint32_t reg_psram_dq13_wpd:1;
/** reg_psram_dq13_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq13 drv
*/
uint32_t reg_psram_dq13_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq13_pin0_reg_t;
/** Group: psram_dq14_pin */
/** Type of psram_dq14_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq14_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq14 dli
*/
uint32_t reg_psram_dq14_dli:4;
/** reg_psram_dq14_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq14 dlc
*/
uint32_t reg_psram_dq14_dlc:4;
/** reg_psram_dq14_hys : R/W; bitpos: [8]; default: 0;
* psram dq14 hys
*/
uint32_t reg_psram_dq14_hys:1;
/** reg_psram_dq14_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq14_ie:1;
/** reg_psram_dq14_wpu : R/W; bitpos: [10]; default: 0;
* psram dq14 wpu
*/
uint32_t reg_psram_dq14_wpu:1;
/** reg_psram_dq14_wpd : R/W; bitpos: [11]; default: 0;
* psram dq14 wpd
*/
uint32_t reg_psram_dq14_wpd:1;
/** reg_psram_dq14_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq14 drv
*/
uint32_t reg_psram_dq14_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq14_pin0_reg_t;
/** Group: psram_dq15_pin */
/** Type of psram_dq15_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dq15_dli : R/W; bitpos: [3:0]; default: 0;
* psram dq15 dli
*/
uint32_t reg_psram_dq15_dli:4;
/** reg_psram_dq15_dlc : R/W; bitpos: [7:4]; default: 0;
* psram dq15 dlc
*/
uint32_t reg_psram_dq15_dlc:4;
/** reg_psram_dq15_hys : R/W; bitpos: [8]; default: 0;
* psram dq15 hys
*/
uint32_t reg_psram_dq15_hys:1;
/** reg_psram_dq15_ie : R/W; bitpos: [9]; default: 0;
* Reserved
*/
uint32_t reg_psram_dq15_ie:1;
/** reg_psram_dq15_wpu : R/W; bitpos: [10]; default: 0;
* psram dq15 wpu
*/
uint32_t reg_psram_dq15_wpu:1;
/** reg_psram_dq15_wpd : R/W; bitpos: [11]; default: 0;
* psram dq15 wpd
*/
uint32_t reg_psram_dq15_wpd:1;
/** reg_psram_dq15_drv : R/W; bitpos: [13:12]; default: 0;
* psram dq15 drv
*/
uint32_t reg_psram_dq15_drv:2;
uint32_t reserved_14:18;
};
uint32_t val;
} iomux_mspi_pin_psram_dq15_pin0_reg_t;
/** Group: psram_dqs_1_pin */
/** Type of psram_dqs_1_pin0 register
* IOMUX_MSPI_PIN_PSRAM_D_PIN0_REG
*/
typedef union {
struct {
/** reg_psram_dqs_1_xpd : R/W; bitpos: [0]; default: 0;
* psram xpd dqs1
*/
uint32_t reg_psram_dqs_1_xpd:1;
/** reg_psram_dqs_1_phase : R/W; bitpos: [2:1]; default: 0;
* psram dqs1 phase
*/
uint32_t reg_psram_dqs_1_phase:2;
/** reg_psram_dqs_1_dli : R/W; bitpos: [6:3]; default: 0;
* psram dqs1 dli
*/
uint32_t reg_psram_dqs_1_dli:4;
/** reg_psram_dqs_1_delay_90 : R/W; bitpos: [10:7]; default: 0;
* psram dqs1 delay 90
*/
uint32_t reg_psram_dqs_1_delay_90:4;
/** reg_psram_dqs_1_hys : R/W; bitpos: [11]; default: 0;
* psram dqs1 hys
*/
uint32_t reg_psram_dqs_1_hys:1;
/** reg_psram_dqs_1_ie : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t reg_psram_dqs_1_ie:1;
/** reg_psram_dqs_1_wpu : R/W; bitpos: [13]; default: 0;
* psram dqs1 wpu
*/
uint32_t reg_psram_dqs_1_wpu:1;
/** reg_psram_dqs_1_wpd : R/W; bitpos: [14]; default: 0;
* psram dqs1 wpd
*/
uint32_t reg_psram_dqs_1_wpd:1;
/** reg_psram_dqs_1_drv : R/W; bitpos: [16:15]; default: 0;
* psram dqs1 drv
*/
uint32_t reg_psram_dqs_1_drv:2;
/** reg_psram_dqs_1_delay_270 : R/W; bitpos: [20:17]; default: 0;
* psram dqs1 delay 270
*/
uint32_t reg_psram_dqs_1_delay_270:4;
uint32_t reserved_21:11;
};
uint32_t val;
} iomux_mspi_pin_psram_dqs_1_pin0_reg_t;
} iomux_mspi_pin_psram_dqs_pin_reg_t;
/** psram_pin group */
typedef struct {
volatile iomux_mspi_pin_psram_pin_reg_t pin_group0[8]; //for d, q, wp, hold, dq4, dq5, dq6, dq7
volatile iomux_mspi_pin_psram_dqs_pin_reg_t dqs0;
volatile iomux_mspi_pin_psram_pin_reg_t pin_group1[10]; //for ck, cs, dq8, dq9, dq10, dq11, dq12, dq13, dq14, dq15
volatile iomux_mspi_pin_psram_dqs_pin_reg_t dqs1;
} iomux_mspi_pin_psram_pin_grp_reg_t;
typedef struct {
volatile iomux_mspi_pin_clk_en0_reg_t clk_en0;
@ -1051,28 +319,10 @@ typedef struct {
volatile iomux_mspi_pin_flash_hold_pin0_reg_t flash_hold_pin0;
volatile iomux_mspi_pin_flash_ck_pin0_reg_t flash_ck_pin0;
volatile iomux_mspi_pin_flash_d_pin0_reg_t flash_d_pin0;
volatile iomux_mspi_pin_psram_d_pin0_reg_t psram_d_pin0;
volatile iomux_mspi_pin_psram_q_pin0_reg_t psram_q_pin0;
volatile iomux_mspi_pin_psram_wp_pin0_reg_t psram_wp_pin0;
volatile iomux_mspi_pin_psram_hold_pin0_reg_t psram_hold_pin0;
volatile iomux_mspi_pin_psram_dq4_pin0_reg_t psram_dq4_pin0;
volatile iomux_mspi_pin_psram_dq5_pin0_reg_t psram_dq5_pin0;
volatile iomux_mspi_pin_psram_dq6_pin0_reg_t psram_dq6_pin0;
volatile iomux_mspi_pin_psram_dq7_pin0_reg_t psram_dq7_pin0;
volatile iomux_mspi_pin_psram_dqs_0_pin0_reg_t psram_dqs_0_pin0;
volatile iomux_mspi_pin_psram_ck_pin0_reg_t psram_ck_pin0;
volatile iomux_mspi_pin_psram_cs_pin0_reg_t psram_cs_pin0;
volatile iomux_mspi_pin_psram_dq8_pin0_reg_t psram_dq8_pin0;
volatile iomux_mspi_pin_psram_dq9_pin0_reg_t psram_dq9_pin0;
volatile iomux_mspi_pin_psram_dq10_pin0_reg_t psram_dq10_pin0;
volatile iomux_mspi_pin_psram_dq11_pin0_reg_t psram_dq11_pin0;
volatile iomux_mspi_pin_psram_dq12_pin0_reg_t psram_dq12_pin0;
volatile iomux_mspi_pin_psram_dq13_pin0_reg_t psram_dq13_pin0;
volatile iomux_mspi_pin_psram_dq14_pin0_reg_t psram_dq14_pin0;
volatile iomux_mspi_pin_psram_dq15_pin0_reg_t psram_dq15_pin0;
volatile iomux_mspi_pin_psram_dqs_1_pin0_reg_t psram_dqs_1_pin0;
volatile iomux_mspi_pin_psram_pin_grp_reg_t psram_pin_group;
} iomux_mspi_pin_dev_t;
extern iomux_mspi_pin_dev_t MSPI_IOMUX;
#ifndef __cplusplus
_Static_assert(sizeof(iomux_mspi_pin_dev_t) == 0x6c, "Invalid size of iomux_mspi_pin_dev_t structure");

View File

@ -108,6 +108,7 @@
#define DR_REG_GPIO_BASE (DR_REG_HPPERIPH1_BASE + 0x20000)
#define DR_REG_GPIO_EXT_BASE (DR_REG_HPPERIPH1_BASE + 0x20F00)
#define DR_REG_IO_MUX_BASE (DR_REG_HPPERIPH1_BASE + 0x21000)
#define DR_REG_IOMUX_MSPI_PIN_BASE (DR_REG_HPPERIPH1_BASE + 0x21200)
#define DR_REG_SYSTIMER_BASE (DR_REG_HPPERIPH1_BASE + 0x22000)
#define DR_REG_MEM_MON_BASE (DR_REG_HPPERIPH1_BASE + 0x23000)
#define DR_REG_AUDIO_ADDC_BASE (DR_REG_HPPERIPH1_BASE + 0x24000)

View File

@ -444,6 +444,8 @@
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
#define SOC_SPI_MEM_SUPPORT_WRAP (1)
#define SOC_SPI_MEM_SUPPORT_TIMING_TUNING (1)
#define SOC_MEMSPI_TIMING_TUNING_BY_DQS (1)
#define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1

View File

@ -1259,6 +1259,7 @@ typedef struct spi1_mem_s_dev_s {
volatile spi1_mem_s_date_reg_t date;
} spi1_mem_s_dev_t;
extern spi1_mem_s_dev_t SPIMEM3;
#ifndef __cplusplus
_Static_assert(sizeof(spi1_mem_s_dev_t) == 0x400, "Invalid size of spi1_mem_s_dev_t structure");

View File

@ -59,6 +59,7 @@ PROVIDE ( SDM = 0x500E0F00 );
PROVIDE ( GLITCH_FILTER = 0x500E0F30 );
PROVIDE ( GPIO_ETM = 0x500E0F60 );
PROVIDE ( IOMUX = 0x500E1000 );
PROVIDE ( MSPI_IOMUX = 0x500E1200 );
PROVIDE ( HP_SYSTEM = 0x500E5000 );
PROVIDE ( HP_SYS_CLKRST = 0x500E6000 );