feat(spi_flash): Add 32M flash support on esp32c5

This commit is contained in:
C.S.M 2024-12-16 17:37:52 +08:00
parent d695060742
commit d448c4ed05
9 changed files with 98 additions and 10 deletions

View File

@ -128,7 +128,10 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
#include "esp32s3/rom/opi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/opi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/opi_flash.h"
#endif
#include "spi_flash/spi_flash_defs.h"
#if ESP_TEE_BUILD
#include "esp_flash_partitions.h"
@ -592,37 +595,37 @@ void bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t fla
switch (flash_mode) {
case ESP_ROM_SPIFLASH_DOUT_MODE:
cache_rd.addr_bit_len = 32;
cache_rd.dummy_bit_len = 8;
cache_rd.dummy_bit_len = SPI_FLASH_DOUT_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_DUAL_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_DIO_MODE:
cache_rd.addr_bit_len = 32;
cache_rd.dummy_bit_len = 4;
cache_rd.dummy_bit_len = SPI_FLASH_DIO_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_DIO_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_QOUT_MODE:
cache_rd.addr_bit_len = 32;
cache_rd.dummy_bit_len = 8;
cache_rd.dummy_bit_len = SPI_FLASH_QOUT_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_QUAD_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_QIO_MODE:
cache_rd.addr_bit_len = 32;
cache_rd.dummy_bit_len = 6;
cache_rd.dummy_bit_len = SPI_FLASH_QIO_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_QIO_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_FASTRD_MODE:
cache_rd.addr_bit_len = 32;
cache_rd.dummy_bit_len = 8;
cache_rd.dummy_bit_len = SPI_FLASH_FASTRD_DUMMY_BITLEN;
cache_rd.cmd = CMD_FASTRD_4B;
cache_rd.cmd_bit_len = 8;
break;
case ESP_ROM_SPIFLASH_SLOWRD_MODE:
cache_rd.addr_bit_len = 32;
cache_rd.dummy_bit_len = 0;
cache_rd.dummy_bit_len = SPI_FLASH_SLOWRD_DUMMY_BITLEN;
cache_rd.cmd = CMD_SLOWRD_4B;
cache_rd.cmd_bit_len = 8;
break;

View File

@ -29,6 +29,7 @@
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "hal/mspi_timing_tuning_ll.h"
#include "bootloader_flash_override.h"
void bootloader_flash_update_id()
{
@ -117,6 +118,9 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
case ESP_IMAGE_FLASH_SIZE_32MB:
size = 32;
break;
default:
size = 2;
}
@ -193,6 +197,9 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr)
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
case ESP_IMAGE_FLASH_SIZE_32MB:
str = "32MB";
break;
default:
str = "2MB";
break;
@ -227,6 +234,10 @@ esp_err_t bootloader_init_spi_flash(void)
bootloader_enable_qio_mode();
#endif
#if CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
bootloader_flash_32bits_address_map_enable(bootloader_flash_get_spi_mode());
#endif
print_flash_info(&bootloader_image_hdr);
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
@ -295,6 +306,10 @@ void bootloader_flash_hardware_init(void)
bootloader_spi_flash_resume();
bootloader_flash_unlock();
#if CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
bootloader_flash_32bits_address_map_enable(bootloader_flash_get_spi_mode());
#endif
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
update_flash_config(&hdr);
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);

View File

@ -17,6 +17,9 @@
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/spi_flash.h"
#include "esp32p4/rom/opi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/spi_flash.h"
#include "esp32c5/rom/opi_flash.h"
#endif
#define SPI_IDX 1
@ -756,7 +759,34 @@ void esp_rom_opiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const
REG_SET_BIT(SPI_MEM_C_CTRL_REG, SPI_MEM_C_Q_POL);
}
}
#elif CONFIG_IDF_TARGET_ESP32C5
extern void esp_rom_spi_set_address_bit_len(int spi, int addr_bits);
void esp_rom_opiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const esp_rom_opiflash_spi0rd_t *cache)
{
esp_rom_spi_set_op_mode(0, mode);
if (cache) {
esp_rom_spi_set_address_bit_len(0, cache->addr_bit_len);
// Patch for ROM function `esp_rom_opiflash_cache_mode_config`, because when dummy is 0,
// `SPI_MEM_USR_DUMMY` should be 0. `esp_rom_opiflash_cache_mode_config` doesn't handle this
// properly.
if (cache->dummy_bit_len == 0) {
REG_CLR_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_DUMMY);
} else {
REG_SET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_DUMMY);
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, cache->dummy_bit_len - 1 + rom_spiflash_legacy_data->dummy_len_plus[0]);
}
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, cache->cmd);
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_BITLEN, cache->cmd_bit_len - 1);
REG_SET_FIELD(SPI_MEM_DDR_REG(0), SPI_FMEM_VAR_DUMMY, cache->var_dummy_en);
}
if (mode == ESP_ROM_SPIFLASH_DIO_MODE || mode == ESP_ROM_SPIFLASH_QIO_MODE) {
REG_SET_FIELD(SPI_MEM_RD_STATUS_REG(0), SPI_MEM_WB_MODE, 0x00);
REG_SET_FIELD(SPI_MEM_RD_STATUS_REG(0), SPI_MEM_WB_MODE_BITLEN, 7);
REG_SET_FIELD(SPI_MEM_RD_STATUS_REG(0), SPI_MEM_WB_MODE_EN, 1);
}
}
#endif // IDF_TARGET

View File

@ -70,6 +70,7 @@ typedef union {
#define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n)
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time)
#define spi_flash_ll_set_extra_address(dev, extra_addr) { /* Not supported on gpspi on ESP32-C5*/ }
#define spi_flash_ll_wb_mode_enable(dev, wb_mode_enale) { /* Not supported on gpspi on ESP32-C5*/ }
#else
#define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev)
#define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev)
@ -101,6 +102,7 @@ typedef union {
#define spi_flash_ll_sync_reset() spimem_flash_ll_sync_reset()
#define spi_flash_ll_set_common_command_register_info(dev, ctrl_reg, user_reg, user1_reg, user2_reg) spimem_flash_ll_set_common_command_register_info((spi_mem_dev_t*)dev, ctrl_reg, user_reg, user1_reg, user2_reg)
#define spi_flash_ll_get_common_command_register_info(dev, ctrl_reg, user_reg, user1_reg, user2_reg) spimem_flash_ll_get_common_command_register_info((spi_mem_dev_t*)dev, ctrl_reg, user_reg, user1_reg, user2_reg)
#define spi_flash_ll_wb_mode_enable(dev, wb_mode_enale) spimem_flash_ll_wb_mode_enable((spi_mem_dev_t*)dev, wb_mode_enale)
#endif

View File

@ -555,6 +555,7 @@ static inline int spimem_flash_ll_get_addr_bitlen(spi_mem_dev_t *dev)
__attribute__((always_inline))
static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
{
dev->cache_fctrl.cache_usr_addr_4byte = (bitlen == 32) ? 1 : 0;
dev->user1.usr_addr_bitlen = (bitlen - 1);
dev->user.usr_addr = bitlen ? 1 : 0;
}
@ -567,8 +568,20 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t
*/
static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr)
{
dev->cache_fctrl.cache_usr_addr_4byte = 0;
// Fixed wb mode to 0x00, the bit length fixed to 8
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr);
dev->rd_status.wb_mode_bitlen = 7; // 8 - 1
}
/**
* Enable extra address for bits M0-M7 in DIO/QIO mode.
*
* @param dev Beginning address of the peripheral registers.
* @param wb_mode_enable true for enabling wb_mode
*/
static inline void spimem_flash_ll_wb_mode_enable(spi_mem_dev_t *dev, bool wb_mode_enable)
{
dev->rd_status.wb_mode_en = wb_mode_enable;
}
/**

View File

@ -126,10 +126,15 @@ esp_err_t spi_flash_hal_configure_host_io_mode(
* - DIO is similar.
*/
if (conf_required) {
#if !SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
int line_width = (io_mode == SPI_FLASH_DIO? 2: 4);
dummy_cyclelen_base -= SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS / line_width;
addr_bitlen += SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS;
#endif
spi_flash_ll_set_extra_address(dev, 0);
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
spi_flash_ll_wb_mode_enable(dev, true);
#endif
}
#endif
#else
@ -204,6 +209,9 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr
if (trans->miso_len > 0) {
spi_flash_ll_get_buffer_data(dev, trans->miso_data, trans->miso_len);
}
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
spi_flash_ll_wb_mode_enable(dev, false);
#endif
return ESP_OK;
}

View File

@ -1143,6 +1143,14 @@ config SOC_SPI_MEM_SUPPORT_WRAP
bool
default y
config SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
bool
default y
config SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP
bool
default y
config SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED
bool
default y

View File

@ -462,6 +462,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_WB_MODE_INDEPENDENT_CONTROL (1)
#define SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP (1)
#define SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1
#define SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1

View File

@ -1,9 +1,11 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc_caps.h"
#pragma once
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
@ -55,10 +57,15 @@
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
#define SPI_FLASH_DIO_ADDR_BITLEN 24
#if !SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
#define SPI_FLASH_DIO_DUMMY_BITLEN 4
#define SPI_FLASH_QIO_ADDR_BITLEN 24
#define SPI_FLASH_QIO_DUMMY_BITLEN 6
#else
#define SPI_FLASH_DIO_DUMMY_BITLEN 0
#define SPI_FLASH_QIO_DUMMY_BITLEN 4
#endif
#define SPI_FLASH_DIO_ADDR_BITLEN 24
#define SPI_FLASH_QIO_ADDR_BITLEN 24
#define SPI_FLASH_QOUT_ADDR_BITLEN 24
#define SPI_FLASH_QOUT_DUMMY_BITLEN 8
#define SPI_FLASH_DOUT_ADDR_BITLEN 24