bootloader: Add QIO support for ESP32-D2WD SPI flash

This commit is contained in:
Angus Gratton 2017-04-13 17:08:53 +10:00 committed by Angus Gratton
parent 85e76a7cfc
commit f7793840e1
5 changed files with 75 additions and 6 deletions

View file

@ -19,6 +19,7 @@
#include "esp_log.h"
#include "rom/cache.h"
#include "rom/efuse.h"
#include "rom/ets_sys.h"
#include "rom/spi_flash.h"
#include "rom/crc.h"
@ -258,6 +259,15 @@ void bootloader_main()
/* disable watch dog here */
REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
return;
}
#endif
esp_rom_spiflash_unlock();
ESP_LOGI(TAG, "Enabling RNG early entropy source...");

View file

@ -16,7 +16,9 @@
#include "flash_qio_mode.h"
#include "esp_log.h"
#include "rom/spi_flash.h"
#include "rom/efuse.h"
#include "soc/spi_struct.h"
#include "soc/efuse_reg.h"
#include "sdkconfig.h"
/* SPI flash controller */
@ -33,6 +35,9 @@
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
static const char *TAG = "qio_mode";
typedef unsigned (*read_status_fn_t)();
@ -77,7 +82,7 @@ static void write_status_16b_wrsr(unsigned new_status);
const static qio_info_t chip_data[] = {
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
/* Final entry is default entry, if no other IDs have matched.
@ -102,6 +107,9 @@ static void enable_qio_mode(read_status_fn_t read_status_fn,
*/
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[];
void bootloader_enable_qio_mode(void)
{
uint32_t raw_flash_id;
@ -149,6 +157,20 @@ static void enable_qio_mode(read_status_fn_t read_status_fn,
uint8_t status_qio_bit)
{
uint32_t status;
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
// spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP.
//
// For now, in this situation we only support Quad I/O mode for ESP32-D2WD where WP pin is known.
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_RESERVE);
uint32_t pkg_ver = chip_ver & 0x7;
const uint32_t PKG_VER_ESP32_D2WD = 2; // TODO: use chip detection API once available
if (pkg_ver != PKG_VER_ESP32_D2WD) {
ESP_LOGE(TAG, "Quad I/O is only supported for standard pin numbers or ESP32-D2WD. Falling back to Dual I/O.");
return;
}
}
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
@ -180,8 +202,10 @@ static void enable_qio_mode(read_status_fn_t read_status_fn,
#else
mode = ESP_ROM_SPIFLASH_QIO_MODE;
#endif
esp_rom_spiflash_config_readmode(mode);
esp_rom_spiflash_select_qio_pins(ESP32_D2WD_WP_GPIO, spiconfig);
}
static unsigned read_status_8b_rdsr()
@ -223,6 +247,17 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
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)
{ }

View file

@ -60,15 +60,20 @@ void ets_efuse_program_op(void);
uint32_t ets_efuse_get_8M_clock(void);
/**
* @brief Read spi pad configuration, show gpio number of flash pad, includes 5 pads.
* @brief Read spi flash pin configuration from Efuse
*
* @param null
*
* @return uint32_t: 0, invalid, flash pad decided by strapping
* else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd
* @return
* - 0 for default SPI pins.
* - 1 for default HSPI pins.
* - Other values define a custom pin configuration mask. Pins are encoded as per the EFUSE_SPICONFIG_RET_SPICLK,
* EFUSE_SPICONFIG_RET_SPIQ, EFUSE_SPICONFIG_RET_SPID, EFUSE_SPICONFIG_RET_SPICS0, EFUSE_SPICONFIG_RET_SPIHD macros.
* WP pin (for quad I/O modes) is not saved in efuse and not returned by this function.
*/
uint32_t ets_efuse_get_spiconfig(void);
#define EFUSE_SPICONFIG_SPI_DEFAULTS 0
#define EFUSE_SPICONFIG_HSPI_DEFAULTS 1
#define EFUSE_SPICONFIG_RET_SPICLK_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPICLK_SHIFT 0
#define EFUSE_SPICONFIG_RET_SPICLK(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICLK_SHIFT) & EFUSE_SPICONFIG_RET_SPICLK_MASK)

View file

@ -512,6 +512,24 @@ esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr,
esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi);
/** @brief Enable Quad I/O pin functions
*
* @note Please do not call this function in SDK.
*
* Sets the HD & WP pin functions for Quad I/O modes, based on the
* efuse SPI pin configuration.
*
* @param wp_gpio_num - Number of the WP pin to reconfigure for quad I/O.
*
* @param spiconfig - Pin configuration, as returned from ets_efuse_get_spiconfig().
* - If this parameter is 0, default SPI pins are used and wp_gpio_num parameter is ignored.
* - If this parameter is 1, default HSPI pins are used and wp_gpio_num parameter is ignored.
* - For other values, this parameter encodes the HD pin number and also the CLK pin number. CLK pin selection is used
* to determine if HSPI or SPI peripheral will be used (use HSPI if CLK pin is the HSPI clock pin, otherwise use SPI).
* Both HD & WP pins are configured via GPIO matrix to map to the selected peripheral.
*/
void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num, uint32_t spiconfig);
/** @brief Global esp_rom_spiflash_chip_t structure used by ROM functions
*
*/

View file

@ -1537,6 +1537,7 @@ PROVIDE ( esp_rom_spiflash_read_user_cmd = 0x400621b0 );
PROVIDE ( esp_rom_spiflash_write_encrypted_disable = 0x40062e60 );
PROVIDE ( esp_rom_spiflash_write_encrypted_enable = 0x40062df4 );
PROVIDE ( esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c );
PROVIDE ( esp_rom_spiflash_select_qio_pins = 0x40061ddc );
PROVIDE ( g_rom_spiflash_chip = 0x3ffae270 );
/*