diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index b97ad036ae..97055bda0e 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -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; diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c index e79463dd4d..22d910e827 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c @@ -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); diff --git a/components/esp_rom/patches/esp_rom_spiflash.c b/components/esp_rom/patches/esp_rom_spiflash.c index 92006d3129..50ac4aaa76 100644 --- a/components/esp_rom/patches/esp_rom_spiflash.c +++ b/components/esp_rom/patches/esp_rom_spiflash.c @@ -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 diff --git a/components/hal/esp32c5/include/hal/spi_flash_ll.h b/components/hal/esp32c5/include/hal/spi_flash_ll.h index acac475ec6..6a3f3570f0 100644 --- a/components/hal/esp32c5/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c5/include/hal/spi_flash_ll.h @@ -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 diff --git a/components/hal/esp32c5/include/hal/spimem_flash_ll.h b/components/hal/esp32c5/include/hal/spimem_flash_ll.h index 1d47df0d05..9b33156f5f 100644 --- a/components/hal/esp32c5/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c5/include/hal/spimem_flash_ll.h @@ -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; } /** diff --git a/components/hal/spi_flash_hal_common.inc b/components/hal/spi_flash_hal_common.inc index 05074cf618..4f8947ecd2 100644 --- a/components/hal/spi_flash_hal_common.inc +++ b/components/hal/spi_flash_hal_common.inc @@ -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; } diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 39f9ad2a96..8929e81ab7 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -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 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 36d3002af6..d6ca686b65 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -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 diff --git a/components/spi_flash/include/spi_flash/spi_flash_defs.h b/components/spi_flash/include/spi_flash/spi_flash_defs.h index 7a8bf432f7..c8629e1bf1 100644 --- a/components/spi_flash/include/spi_flash/spi_flash_defs.h +++ b/components/spi_flash/include/spi_flash/spi_flash_defs.h @@ -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