Import bootloader from esp-idf v3
[apeos.git] / components / bootloader / subproject / main / flash_qio_mode.c
blob79b145c9761b5aa4bcd2fb29fa940a0b389860bc
1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <stddef.h>
15 #include <stdint.h>
16 #include "flash_qio_mode.h"
17 #include "esp_log.h"
18 #include "esp_err.h"
19 #include "rom/spi_flash.h"
20 #include "rom/efuse.h"
21 #include "soc/spi_struct.h"
22 #include "soc/efuse_reg.h"
23 #include "sdkconfig.h"
25 /* SPI flash controller */
26 #define SPIFLASH SPI1
28 /* SPI commands (actual on-wire commands not SPI controller bitmasks)
29 Suitable for use with the execute_flash_command static function.
31 #define CMD_RDID 0x9F
32 #define CMD_WRSR 0x01
33 #define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
34 #define CMD_WREN 0x06
35 #define CMD_WRDI 0x04
36 #define CMD_RDSR 0x05
37 #define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
39 static const char *TAG = "qio_mode";
41 typedef unsigned (*read_status_fn_t)();
42 typedef void (*write_status_fn_t)(unsigned);
44 typedef struct __attribute__((packed)) {
45 const char *manufacturer;
46 uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
47 uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
48 uint16_t id_mask; /* Bits to match on in flash chip ID */
49 read_status_fn_t read_status_fn;
50 write_status_fn_t write_status_fn;
51 uint8_t status_qio_bit;
52 } qio_info_t;
54 /* Read 8 bit status using RDSR command */
55 static unsigned read_status_8b_rdsr();
56 /* Read 8 bit status (second byte) using RDSR2 command */
57 static unsigned read_status_8b_rdsr2();
58 /* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
59 static unsigned read_status_16b_rdsr_rdsr2();
61 /* Write 8 bit status using WRSR */
62 static void write_status_8b_wrsr(unsigned new_status);
63 /* Write 8 bit status (second byte) using WRSR2 */
64 static void write_status_8b_wrsr2(unsigned new_status);
65 /* Write 16 bit status using WRSR */
66 static void write_status_16b_wrsr(unsigned new_status);
68 #define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
70 #ifndef CONFIG_BOOTLOADER_SPI_WP_PIN // Set in menuconfig if SPI flasher config is set to a quad mode
71 #define CONFIG_BOOTLOADER_SPI_WP_PIN ESP32_D2WD_WP_GPIO
72 #endif
74 /* Array of known flash chips and data to enable Quad I/O mode
76 Manufacturer & flash ID can be tested by running "esptool.py
77 flash_id"
79 If manufacturer ID matches, and flash ID ORed with flash ID mask
80 matches, enable_qio_mode() will execute "Read Cmd", test if bit
81 number "QIE Bit" is set, and if not set it will call "Write Cmd"
82 with this bit set.
84 Searching of this table stops when the first match is found.
86 const static qio_info_t chip_data[] = {
87 /* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
88 { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
89 { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
90 { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
91 { "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
93 /* Final entry is default entry, if no other IDs have matched.
95 This approach works for chips including:
96 GigaDevice (mfg ID 0xC8, flash IDs including 4016),
97 FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016)
99 { NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 },
102 #define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
104 static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
105 write_status_fn_t write_status_fn,
106 uint8_t status_qio_bit);
108 /* Generic function to use the "user command" SPI controller functionality
109 to send commands to the SPI flash and read the respopnse.
111 The command passed here is always the on-the-wire command given to the SPI flash unit.
113 static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
115 /* dummy_len_plus values defined in ROM for SPI flash configuration */
116 extern uint8_t g_rom_spiflash_dummy_len_plus[];
118 void bootloader_enable_qio_mode(void)
120 uint32_t old_ctrl_reg;
121 uint32_t raw_flash_id;
122 uint8_t mfg_id;
123 uint16_t flash_id;
124 int i;
126 ESP_LOGD(TAG, "Probing for QIO mode enable...");
127 esp_rom_spiflash_wait_idle(&g_rom_flashchip);
129 /* Set up some of the SPIFLASH user/ctrl variables which don't change
130 while we're probing using execute_flash_command() */
131 old_ctrl_reg = SPIFLASH.ctrl.val;
132 SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode
133 SPIFLASH.user.usr_dummy = 0;
134 SPIFLASH.user.usr_addr = 0;
135 SPIFLASH.user.usr_command = 1;
136 SPIFLASH.user2.usr_command_bitlen = 7;
138 raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24);
139 ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id);
141 mfg_id = raw_flash_id & 0xFF;
142 flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
143 ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
145 for (i = 0; i < NUM_CHIPS-1; i++) {
146 const qio_info_t *chip = &chip_data[i];
147 if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
148 ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
149 break;
153 if (i == NUM_CHIPS - 1) {
154 ESP_LOGI(TAG, "Enabling default flash chip QIO");
157 esp_err_t res = enable_qio_mode(chip_data[i].read_status_fn,
158 chip_data[i].write_status_fn,
159 chip_data[i].status_qio_bit);
160 if (res != ESP_OK) {
161 // Restore SPI flash CTRL setting, to keep us in DIO/DOUT mode
162 SPIFLASH.ctrl.val = old_ctrl_reg;
166 static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
167 write_status_fn_t write_status_fn,
168 uint8_t status_qio_bit)
170 uint32_t status;
171 const uint32_t spiconfig = ets_efuse_get_spiconfig();
173 if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
174 // spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP,
175 // which is compiled into the bootloader instead.
177 // Most commonly an overriden pin mapping means ESP32-D2WD. Warn if chip is ESP32-D2WD
178 // but someone has changed the WP pin assignment from that chip's WP pin.
179 uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_RESERVE);
180 uint32_t pkg_ver = chip_ver & 0x7;
181 const int PKG_VER_ESP32_D2WD = 2; // TODO: use chip detection API once available
182 if (pkg_ver == PKG_VER_ESP32_D2WD && CONFIG_BOOTLOADER_SPI_WP_PIN != ESP32_D2WD_WP_GPIO) {
183 ESP_LOGW(TAG, "Chip is ESP32-D2WD but flash WP pin is different value to internal flash");
187 esp_rom_spiflash_wait_idle(&g_rom_flashchip);
189 status = read_status_fn();
190 ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
192 if ((status & (1<<status_qio_bit)) == 0) {
193 execute_flash_command(CMD_WREN, 0, 0, 0);
194 write_status_fn(status | (1<<status_qio_bit));
196 esp_rom_spiflash_wait_idle(&g_rom_flashchip);
198 status = read_status_fn();
199 ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
200 if ((status & (1<<status_qio_bit)) == 0) {
201 ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode");
202 return ESP_FAIL;
205 } else {
206 ESP_LOGD(TAG, "QIO mode already enabled in flash");
209 ESP_LOGD(TAG, "Enabling QIO mode...");
211 esp_rom_spiflash_read_mode_t mode;
212 #if CONFIG_FLASHMODE_QOUT
213 mode = ESP_ROM_SPIFLASH_QOUT_MODE;
214 #else
215 mode = ESP_ROM_SPIFLASH_QIO_MODE;
216 #endif
218 esp_rom_spiflash_config_readmode(mode);
220 esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
222 return ESP_OK;
225 static unsigned read_status_8b_rdsr()
227 return execute_flash_command(CMD_RDSR, 0, 0, 8);
230 static unsigned read_status_8b_rdsr2()
232 return execute_flash_command(CMD_RDSR2, 0, 0, 8);
235 static unsigned read_status_16b_rdsr_rdsr2()
237 return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
240 static void write_status_8b_wrsr(unsigned new_status)
242 execute_flash_command(CMD_WRSR, new_status, 8, 0);
245 static void write_status_8b_wrsr2(unsigned new_status)
247 execute_flash_command(CMD_WRSR2, new_status, 8, 0);
250 static void write_status_16b_wrsr(unsigned new_status)
252 execute_flash_command(CMD_WRSR, new_status, 16, 0);
255 static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
257 SPIFLASH.user2.usr_command_value = command;
258 SPIFLASH.user.usr_miso = miso_len > 0;
259 SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
260 SPIFLASH.user.usr_mosi = mosi_len > 0;
261 SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
262 SPIFLASH.data_buf[0] = mosi_data;
264 if (g_rom_spiflash_dummy_len_plus[1]) {
265 /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
266 if (miso_len > 0) {
267 SPIFLASH.user.usr_dummy = 1;
268 SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
269 } else {
270 SPIFLASH.user.usr_dummy = 0;
271 SPIFLASH.user1.usr_dummy_cyclelen = 0;
275 SPIFLASH.cmd.usr = 1;
276 while(SPIFLASH.cmd.usr != 0)
279 return SPIFLASH.data_buf[0];