diff --git a/components/bootloader_support/include_bootloader/bootloader_flash.h b/components/bootloader_support/include_bootloader/bootloader_flash.h index 6482dde99e..e2e0f3ed65 100644 --- a/components/bootloader_support/include_bootloader/bootloader_flash.h +++ b/components/bootloader_support/include_bootloader/bootloader_flash.h @@ -19,11 +19,26 @@ #include #include #include /* including in bootloader for error values */ +#include "sdkconfig.h" #define FLASH_SECTOR_SIZE 0x1000 #define FLASH_BLOCK_SIZE 0x10000 #define MMAP_ALIGNED_MASK 0x0000FFFF +/* SPI commands (actual on-wire commands not SPI controller bitmasks) + Suitable for use with the bootloader_execute_flash_command static function. +*/ +#define CMD_RDID 0x9F +#define CMD_WRSR 0x01 +#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */ +#define CMD_WREN 0x06 +#define CMD_WRDI 0x04 +#define CMD_RDSR 0x05 +#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ +#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */ +#define CMD_WRAP 0x77 /* Set burst with wrap command */ + + /* Provide a Flash API for bootloader_support code, that can be used from bootloader or app code. @@ -136,4 +151,30 @@ static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vad return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) / MMU_BLOCK_SIZE; } +/** + * @brief Execute a user command on the flash + * + * @param command The command value to execute. + * @param mosi_data MOSI data to send + * @param mosi_len Length of MOSI data, in bits + * @param miso_len Length of MISO data to receive, in bits + * @return Received MISO data + */ +uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len); + +/** + * @brief Enable the flash write protect (WEL bit). + */ +void bootloader_enable_wp(void); + +#if CONFIG_IDF_TARGET_ESP32S2 +/** + * @brief Set the burst mode setting command for specified wrap mode. + * + * @param mode The specified warp mode. + * @return always ESP_OK + */ +esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode); +#endif + #endif diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index 358aa134be..d001402a0c 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -16,10 +16,26 @@ #include #include #include +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if CONFIG_IDF_TARGET_ESP32 +# include "soc/spi_struct.h" +# include "soc/spi_reg.h" + /* SPI flash controller */ +# define SPIFLASH SPI1 +#else +# include "soc/spi_mem_struct.h" +# include "soc/spi_mem_reg.h" + /* SPI flash controller */ +# define SPIFLASH SPIMEM1 +#endif + #if CONFIG_IDF_TARGET_ESP32S2BETA #include "esp32s2beta/rom/spi_flash.h" #endif + #ifndef BOOTLOADER_BUILD /* Normal app version maps to esp_spi_flash.h operations... */ @@ -363,4 +379,90 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) } return spi_to_esp_err(rc); } + #endif + +extern uint8_t g_rom_spiflash_dummy_len_plus[]; +uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) +{ + uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; +#if CONFIG_IDF_TARGET_ESP32 + SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode +#endif + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user.usr_addr = 0; + SPIFLASH.user.usr_command = 1; + SPIFLASH.user2.usr_command_bitlen = 7; + + SPIFLASH.user2.usr_command_value = command; + SPIFLASH.user.usr_miso = miso_len > 0; +#if CONFIG_IDF_TARGET_ESP32 + SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0; +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0; +#endif + SPIFLASH.user.usr_mosi = mosi_len > 0; +#if CONFIG_IDF_TARGET_ESP32 + SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0; +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0; +#endif + SPIFLASH.data_buf[0] = mosi_data; + + if (g_rom_spiflash_dummy_len_plus[1]) { + /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */ + if (miso_len > 0) { + SPIFLASH.user.usr_dummy = 1; + SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1; + } else { + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user1.usr_dummy_cyclelen = 0; + } + } + + SPIFLASH.cmd.usr = 1; + while (SPIFLASH.cmd.usr != 0) { + } + + SPIFLASH.ctrl.val = old_ctrl_reg; + return SPIFLASH.data_buf[0]; +} + +void bootloader_enable_wp(void) +{ + bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ +} + +#if SOC_CACHE_SUPPORT_WRAP +esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode) +{ + uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val; + uint32_t reg_bkp_usr = SPIFLASH.user.val; + SPIFLASH.user.fwrite_dio = 0; + SPIFLASH.user.fwrite_dual = 0; + SPIFLASH.user.fwrite_qio = 1; + SPIFLASH.user.fwrite_quad = 0; + SPIFLASH.ctrl.fcmd_dual = 0; + SPIFLASH.ctrl.fcmd_quad = 0; + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user.usr_addr = 1; + SPIFLASH.user.usr_command = 1; + SPIFLASH.user2.usr_command_bitlen = 7; + SPIFLASH.user2.usr_command_value = CMD_WRAP; + SPIFLASH.user1.usr_addr_bitlen = 23; + SPIFLASH.addr = 0; + SPIFLASH.user.usr_miso = 0; + SPIFLASH.user.usr_mosi = 1; + SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7; + SPIFLASH.data_buf[0] = (uint32_t) mode << 4;; + SPIFLASH.cmd.usr = 1; + while(SPIFLASH.cmd.usr != 0) + { } + + SPIFLASH.ctrl.val = reg_bkp_ctrl; + SPIFLASH.user.val = reg_bkp_usr; + return ESP_OK; +} +#endif //SOC_CACHE_SUPPORT_WRAP \ No newline at end of file diff --git a/components/bootloader_support/src/esp32/bootloader_esp32.c b/components/bootloader_support/src/esp32/bootloader_esp32.c index d488a62f0d..6a380bbcd9 100644 --- a/components/bootloader_support/src/esp32/bootloader_esp32.c +++ b/components/bootloader_support/src/esp32/bootloader_esp32.c @@ -22,6 +22,7 @@ #include "bootloader_clock.h" #include "bootloader_common.h" #include "bootloader_flash_config.h" +#include "bootloader_flash.h" #include "soc/cpu.h" #include "soc/dport_reg.h" @@ -265,6 +266,8 @@ static esp_err_t bootloader_init_spi_flash(void) print_flash_info(&bootloader_image_hdr); update_flash_config(&bootloader_image_hdr); + //ensure the flash is write-protected + bootloader_enable_wp(); return ESP_OK; } diff --git a/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c b/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c index 066271e4f7..b4f2ed5e78 100644 --- a/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c +++ b/components/bootloader_support/src/esp32s2beta/bootloader_esp32s2beta.c @@ -24,6 +24,7 @@ #include "bootloader_init.h" #include "bootloader_clock.h" #include "bootloader_flash_config.h" +#include "bootloader_flash.h" #include "esp32s2beta/rom/cache.h" #include "esp32s2beta/rom/ets_sys.h" @@ -225,6 +226,8 @@ static esp_err_t bootloader_init_spi_flash(void) print_flash_info(&bootloader_image_hdr); update_flash_config(&bootloader_image_hdr); + //ensure the flash is write-protected + bootloader_enable_wp(); return ESP_OK; } diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index 1dac9c5fc6..20475b5abc 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -15,6 +15,7 @@ #include #include "bootloader_flash_config.h" #include "flash_qio_mode.h" +#include "bootloader_flash.h" #include "esp_log.h" #include "esp_err.h" #if CONFIG_IDF_TARGET_ESP32 @@ -25,30 +26,10 @@ #include "esp32s2beta/rom/efuse.h" #include "soc/spi_mem_struct.h" #endif -#include "soc/spi_struct.h" -#include "soc/spi_reg.h" #include "soc/efuse_periph.h" #include "soc/io_mux_reg.h" #include "sdkconfig.h" -/* SPI flash controller */ -#if CONFIG_IDF_TARGET_ESP32 -#define SPIFLASH SPI1 -#elif CONFIG_IDF_TARGET_ESP32S2BETA -#define SPIFLASH SPIMEM1 -#endif - -/* SPI commands (actual on-wire commands not SPI controller bitmasks) - Suitable for use with the execute_flash_command static function. -*/ -#define CMD_RDID 0x9F -#define CMD_WRSR 0x01 -#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */ -#define CMD_WREN 0x06 -#define CMD_WRDI 0x04 -#define CMD_RDSR 0x05 -#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ -#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */ static const char *TAG = "qio_mode"; @@ -126,57 +107,15 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, The command passed here is always the on-the-wire command given to the SPI flash unit. */ -static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len); /* dummy_len_plus values defined in ROM for SPI flash configuration */ -extern uint8_t g_rom_spiflash_dummy_len_plus[]; uint32_t bootloader_read_flash_id(void) { - uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24); + uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24); id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); return id; } -#if CONFIG_IDF_TARGET_ESP32S2BETA -#define FLASH_WRAP_CMD 0x77 -typedef enum { - FLASH_WRAP_MODE_8B = 0, - FLASH_WRAP_MODE_16B = 2, - FLASH_WRAP_MODE_32B = 4, - FLASH_WRAP_MODE_64B = 6, - FLASH_WRAP_MODE_DISABLE = 1 -} spi_flash_wrap_mode_t; -static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode) -{ - uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val; - uint32_t reg_bkp_usr = SPIFLASH.user.val; - SPIFLASH.user.fwrite_dio = 0; - SPIFLASH.user.fwrite_dual = 0; - SPIFLASH.user.fwrite_qio = 1; - SPIFLASH.user.fwrite_quad = 0; - SPIFLASH.ctrl.fcmd_dual = 0; - SPIFLASH.ctrl.fcmd_quad = 0; - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 1; - SPIFLASH.user.usr_command = 1; - SPIFLASH.user2.usr_command_bitlen = 7; - SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD; - SPIFLASH.user1.usr_addr_bitlen = 23; - SPIFLASH.addr = 0; - SPIFLASH.user.usr_miso = 0; - SPIFLASH.user.usr_mosi = 1; - SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7; - SPIFLASH.data_buf[0] = (uint32_t) mode << 4;; - SPIFLASH.cmd.usr = 1; - while (SPIFLASH.cmd.usr != 0) { - } - - SPIFLASH.ctrl.val = reg_bkp_ctrl; - SPIFLASH.user.val = reg_bkp_usr; - return ESP_OK; -} -#endif - void bootloader_enable_qio_mode(void) { uint32_t raw_flash_id; @@ -208,8 +147,8 @@ void bootloader_enable_qio_mode(void) enable_qio_mode(chip_data[i].read_status_fn, chip_data[i].write_status_fn, chip_data[i].status_qio_bit); -#if CONFIG_IDF_TARGET_ESP32S2BETA - spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE); +#if SOC_CACHE_SUPPORT_WRAP + bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE); #endif } @@ -226,7 +165,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, ESP_LOGD(TAG, "Initial flash chip status 0x%x", status); if ((status & (1 << status_qio_bit)) == 0) { - execute_flash_command(CMD_WREN, 0, 0, 0); + bootloader_execute_flash_command(CMD_WREN, 0, 0, 0); write_status_fn(status | (1 << status_qio_bit)); esp_rom_spiflash_wait_idle(&g_rom_flashchip); @@ -264,95 +203,48 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, static unsigned read_status_8b_rdsr(void) { - return execute_flash_command(CMD_RDSR, 0, 0, 8); + return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8); } static unsigned read_status_8b_rdsr2(void) { - return execute_flash_command(CMD_RDSR2, 0, 0, 8); + return bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8); } static unsigned read_status_16b_rdsr_rdsr2(void) { - return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8); + return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8); } static void write_status_8b_wrsr(unsigned new_status) { - execute_flash_command(CMD_WRSR, new_status, 8, 0); + bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0); } static void write_status_8b_wrsr2(unsigned new_status) { - execute_flash_command(CMD_WRSR2, new_status, 8, 0); + bootloader_execute_flash_command(CMD_WRSR2, new_status, 8, 0); } static void write_status_16b_wrsr(unsigned new_status) { - execute_flash_command(CMD_WRSR, new_status, 16, 0); + bootloader_execute_flash_command(CMD_WRSR, new_status, 16, 0); } static unsigned read_status_8b_xmc25qu64a(void) { - execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */ + bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */ esp_rom_spiflash_wait_idle(&g_rom_flashchip); - uint32_t read_status = execute_flash_command(CMD_RDSR, 0, 0, 8); - execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ + uint32_t read_status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8); + bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ return read_status; } static void write_status_8b_xmc25qu64a(unsigned new_status) { - execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */ + bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */ esp_rom_spiflash_wait_idle(&g_rom_flashchip); - execute_flash_command(CMD_WRSR, new_status, 8, 0); + bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0); esp_rom_spiflash_wait_idle(&g_rom_flashchip); - execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ -} - -static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) -{ - uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; -#if CONFIG_IDF_TARGET_ESP32 - SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode -#elif CONFIG_IDF_TARGET_ESP32S2BETA - SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode -#endif - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 0; - SPIFLASH.user.usr_command = 1; - SPIFLASH.user2.usr_command_bitlen = 7; - - SPIFLASH.user2.usr_command_value = command; - SPIFLASH.user.usr_miso = miso_len > 0; -#if CONFIG_IDF_TARGET_ESP32 - SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0; -#elif CONFIG_IDF_TARGET_ESP32S2BETA - SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0; -#endif - SPIFLASH.user.usr_mosi = mosi_len > 0; -#if CONFIG_IDF_TARGET_ESP32 - SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0; -#elif CONFIG_IDF_TARGET_ESP32S2BETA - SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0; -#endif - SPIFLASH.data_buf[0] = mosi_data; - - if (g_rom_spiflash_dummy_len_plus[1]) { - /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */ - if (miso_len > 0) { - SPIFLASH.user.usr_dummy = 1; - SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1; - } else { - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user1.usr_dummy_cyclelen = 0; - } - } - - SPIFLASH.cmd.usr = 1; - while (SPIFLASH.cmd.usr != 0) { - } - - SPIFLASH.ctrl.val = old_ctrl_reg; - return SPIFLASH.data_buf[0]; + bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ } diff --git a/components/esp_rom/include/esp32/rom/spi_flash.h b/components/esp_rom/include/esp32/rom/spi_flash.h index f4b17ae5be..6174f05e73 100644 --- a/components/esp_rom/include/esp32/rom/spi_flash.h +++ b/components/esp_rom/include/esp32/rom/spi_flash.h @@ -121,6 +121,7 @@ extern "C" { #define ESP_ROM_SPIFLASH_BP2 BIT4 #define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) #define ESP_ROM_SPIFLASH_QE BIT9 +#define ESP_ROM_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2) //Extra dummy for flash read #define ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M 0 diff --git a/components/esp_rom/include/esp32s2beta/rom/spi_flash.h b/components/esp_rom/include/esp32s2beta/rom/spi_flash.h index a94772b6ea..bc114bf538 100644 --- a/components/esp_rom/include/esp32s2beta/rom/spi_flash.h +++ b/components/esp_rom/include/esp32s2beta/rom/spi_flash.h @@ -116,6 +116,7 @@ extern "C" { #define ESP_ROM_SPIFLASH_BP2 BIT4 #define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) #define ESP_ROM_SPIFLASH_QE BIT9 +#define ESP_ROM_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2) #define FLASH_ID_GD25LQ32C 0xC86016 diff --git a/components/soc/esp32s2beta/include/soc/soc_caps.h b/components/soc/esp32s2beta/include/soc/soc_caps.h index 85a465e89f..1db501548c 100644 --- a/components/soc/esp32s2beta/include/soc/soc_caps.h +++ b/components/soc/esp32s2beta/include/soc/soc_caps.h @@ -4,3 +4,5 @@ // include them here. #pragma once + +#define SOC_CACHE_SUPPORT_WRAP 1 diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index b077d6c6de..46574c4c5a 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/components/spi_flash/CMakeLists.txt @@ -1,5 +1,3 @@ -set(priv_requires bootloader_support soc) - if(BOOTLOADER_BUILD) if (CONFIG_IDF_TARGET_ESP32) # ESP32 Bootloader needs SPIUnlock from this file, but doesn't @@ -12,6 +10,7 @@ if(BOOTLOADER_BUILD) set(srcs) endif() set(cache_srcs "") + set(priv_requires bootloader_support soc) else() set(cache_srcs "cache_utils.c" diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index f40b0b8340..e0c679ed3b 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -49,8 +49,9 @@ menu "SPI Flash driver" default y help Enable this flag to use patched versions of SPI flash ROM driver functions. - This option is needed to write to flash on ESP32-D2WD, and any configuration - where external SPI flash is connected to non-default pins. + This option should be enabled, if any one of the following is true: (1) need to write + to flash on ESP32-D2WD; (2) main SPI flash is connected to non-default pins; (3) main + SPI flash chip is manufactured by ISSI. choice SPI_FLASH_DANGEROUS_WRITE bool "Writing to dangerous flash regions" diff --git a/components/spi_flash/esp32/spi_flash_rom_patch.c b/components/spi_flash/esp32/spi_flash_rom_patch.c index 125c2dfa56..965da48827 100644 --- a/components/spi_flash/esp32/spi_flash_rom_patch.c +++ b/components/spi_flash/esp32/spi_flash_rom_patch.c @@ -21,8 +21,14 @@ #define SPI_IDX 1 #define OTH_IDX 0 + extern esp_rom_spiflash_chip_t g_rom_spiflash_chip; +static inline bool is_issi_chip(const esp_rom_spiflash_chip_t* chip) +{ + return (((chip->device_id >> 16)&0xff) == 0x9D); +} + esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi) { uint32_t status; @@ -61,25 +67,43 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *sp esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void) { uint32_t status; + uint32_t new_status; esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip); - if (esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) { - return ESP_ROM_SPIFLASH_RESULT_ERR; - } + if (is_issi_chip(&g_rom_spiflash_chip)) { + // ISSI chips have different QE position - /* Clear all bits except QIE, if it is set. - (This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.) - */ - status &= ESP_ROM_SPIFLASH_QE; + if (esp_rom_spiflash_read_status(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) { + return ESP_ROM_SPIFLASH_RESULT_ERR; + } + + /* Clear all bits in the mask. + (This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.) + */ + new_status = status & (~ESP_ROM_SPIFLASH_BP_MASK_ISSI); + // Skip if nothing needs to be cleared. Otherwise will waste time waiting for the flash to clear nothing. + if (new_status == status) return ESP_ROM_SPIFLASH_RESULT_OK; + + CLEAR_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B); + } else { + if (esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) { + return ESP_ROM_SPIFLASH_RESULT_ERR; + } + + /* Clear all bits except QE, if it is set. + (This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.) + */ + new_status = status & ESP_ROM_SPIFLASH_QE; + SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B); + } esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip); REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN); while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) { } esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip); - SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B); - if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status) != ESP_ROM_SPIFLASH_RESULT_OK) { + if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, new_status) != ESP_ROM_SPIFLASH_RESULT_OK) { return ESP_ROM_SPIFLASH_RESULT_ERR; } diff --git a/components/spi_flash/esp32s2beta/flash_ops_esp32s2beta.c b/components/spi_flash/esp32s2beta/flash_ops_esp32s2beta.c index 876fb0e62b..d46716ec57 100644 --- a/components/spi_flash/esp32s2beta/flash_ops_esp32s2beta.c +++ b/components/spi_flash/esp32s2beta/flash_ops_esp32s2beta.c @@ -20,6 +20,7 @@ #include "soc/soc_memory_layout.h" #include "esp32s2beta/rom/spi_flash.h" #include "esp32s2beta/rom/cache.h" +#include "bootloader_flash.h" #include "hal/spi_flash_hal.h" #include "esp_flash.h" @@ -71,48 +72,22 @@ esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_a #define SPICACHE SPIMEM0 #define SPIFLASH SPIMEM1 -#define FLASH_WRAP_CMD 0x77 esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode) { - uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val; - uint32_t reg_bkp_usr = SPIFLASH.user.val; - SPIFLASH.user.fwrite_dio = 0; - SPIFLASH.user.fwrite_dual = 0; - SPIFLASH.user.fwrite_qio = 1; - SPIFLASH.user.fwrite_quad = 0; - SPIFLASH.ctrl.fcmd_dual = 0; - SPIFLASH.ctrl.fcmd_quad = 0; - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 1; - SPIFLASH.user.usr_command = 1; - SPIFLASH.user2.usr_command_bitlen = 7; - SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD; - SPIFLASH.user1.usr_addr_bitlen = 23; - SPIFLASH.addr = 0; - SPIFLASH.user.usr_miso = 0; - SPIFLASH.user.usr_mosi = 1; - SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7; - SPIFLASH.data_buf[0] = (uint32_t) mode << 4;; - SPIFLASH.cmd.usr = 1; - while(SPIFLASH.cmd.usr != 0) - { } - - SPIFLASH.ctrl.val = reg_bkp_ctrl; - SPIFLASH.user.val = reg_bkp_usr; - return ESP_OK; + return bootloader_flash_wrap_set(mode); } esp_err_t spi_flash_enable_wrap(uint32_t wrap_size) { switch(wrap_size) { case 8: - return spi_flash_wrap_set(FLASH_WRAP_MODE_8B); + return bootloader_flash_wrap_set(FLASH_WRAP_MODE_8B); case 16: - return spi_flash_wrap_set(FLASH_WRAP_MODE_16B); + return bootloader_flash_wrap_set(FLASH_WRAP_MODE_16B); case 32: - return spi_flash_wrap_set(FLASH_WRAP_MODE_32B); + return bootloader_flash_wrap_set(FLASH_WRAP_MODE_32B); case 64: - return spi_flash_wrap_set(FLASH_WRAP_MODE_64B); + return bootloader_flash_wrap_set(FLASH_WRAP_MODE_64B); default: return ESP_FAIL; } @@ -120,7 +95,7 @@ esp_err_t spi_flash_enable_wrap(uint32_t wrap_size) void spi_flash_disable_wrap(void) { - spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE); + bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE); } bool spi_flash_support_wrap_size(uint32_t wrap_size) diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index f9f532045c..3b2c0ba768 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -35,8 +35,6 @@ #include "esp32/clk.h" #elif CONFIG_IDF_TARGET_ESP32S2BETA #include "esp32s2beta/clk.h" -#include "soc/spi_mem_reg.h" -#include "soc/spi_mem_struct.h" #endif #include "esp_flash_partitions.h" #include "cache_utils.h" @@ -832,6 +830,7 @@ void spi_flash_dump_counters(void) #endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS + #if defined(CONFIG_SPI_FLASH_USE_LEGACY_IMPL) && defined(CONFIG_IDF_TARGET_ESP32S2BETA) // TODO esp32s2beta: Remove once ESP32S2Beta has new SPI Flash API support esp_flash_t *esp_flash_default_chip = NULL;