]> granicus.if.org Git - esp-idf/commitdiff
bootloader: Add QIO support for ESP32-D2WD SPI flash
authorAngus Gratton <angus@espressif.com>
Thu, 13 Apr 2017 07:08:53 +0000 (17:08 +1000)
committerAngus Gratton <gus@projectgus.com>
Thu, 13 Apr 2017 07:55:47 +0000 (17:55 +1000)
components/bootloader/src/main/bootloader_start.c
components/bootloader/src/main/flash_qio_mode.c
components/esp32/include/rom/efuse.h
components/esp32/include/rom/spi_flash.h
components/esp32/ld/esp32.rom.ld

index 536077af4fa76f82b2338a1e44e337f34c9ebf37..28446c264724c3fcee35912c7e165816c69b1bf2 100644 (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...");
index 55c618654b40daa4627aa679b450647f2d25ea51..cd288290cb83f11636758342f34f3a4d79aff042 100644 (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)
     { }
index 58cfdb20bc3e00b9d7a03b04326280feaed95e46..337227ab0d47ccdcdc0887361bf2d160de014d65 100644 (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)
index 97efccc368a6aa6673ae53d8cff70204e13d009f..35d010d79791ef3894a30e13827b44f850b117de 100644 (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
  *
  */
index 6529e31dfa9c09de63ef715dfa2452e9fa7ac769..3b81f2cecfbc5e0f1b758a17ed35574e925442e0 100644 (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 );
 
 /*