• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
6 
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 "bootloader_flash_config.h"
17 #include "flash_qio_mode.h"
18 #include "sdkconfig.h"
19 #include "bootloader_flash_priv.h"
20 #include "esp_log.h"
21 #include "esp_err.h"
22 #include "esp_rom_efuse.h"
23 #include "flash_qio_mode.h"
24 #if CONFIG_IDF_TARGET_ESP32
25 #include "esp32/rom/spi_flash.h"
26 #elif CONFIG_IDF_TARGET_ESP32S2
27 #include "esp32s2/rom/spi_flash.h"
28 #elif CONFIG_IDF_TARGET_ESP32S3
29 #include "esp32s3/rom/spi_flash.h"
30 #elif CONFIG_IDF_TARGET_ESP32C3
31 #include "esp32c3/rom/spi_flash.h"
32 #endif
33 #include "soc/efuse_periph.h"
34 #include "soc/io_mux_reg.h"
35 
36 
37 static const char *TAG = "qio_mode";
38 
39 typedef unsigned (*read_status_fn_t)(void);
40 typedef void (*write_status_fn_t)(unsigned);
41 
42 typedef struct __attribute__((packed))
43 {
44     const char *manufacturer;
45     uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
46     uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
47     uint16_t id_mask; /* Bits to match on in flash chip ID */
48     read_status_fn_t read_status_fn;
49     write_status_fn_t write_status_fn;
50     uint8_t status_qio_bit;
51 } qio_info_t;
52 
53 /* Read 8 bit status using RDSR command */
54 static unsigned read_status_8b_rdsr(void);
55 /* Read 8 bit status (second byte) using RDSR2 command */
56 static unsigned read_status_8b_rdsr2(void);
57 /* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
58 static unsigned read_status_16b_rdsr_rdsr2(void);
59 
60 /* Write 8 bit status using WRSR */
61 static void write_status_8b_wrsr(unsigned new_status);
62 /* Write 8 bit status (second byte) using WRSR2 */
63 static void write_status_8b_wrsr2(unsigned new_status);
64 /* Write 16 bit status using WRSR */
65 static void write_status_16b_wrsr(unsigned new_status);
66 
67 /* Read 8 bit status of XM25QU64A  */
68 static unsigned read_status_8b_xmc25qu64a(void);
69 /* Write 8 bit status of XM25QU64A */
70 static void write_status_8b_xmc25qu64a(unsigned new_status);
71 
72 /* Array of known flash chips and data to enable Quad I/O mode
73 
74    Manufacturer & flash ID can be tested by running "esptool.py
75    flash_id"
76 
77    If manufacturer ID matches, and flash ID ORed with flash ID mask
78    matches, enable_qio_mode() will execute "Read Cmd", test if bit
79    number "QIE Bit" is set, and if not set it will call "Write Cmd"
80    with this bit set.
81 
82    Searching of this table stops when the first match is found.
83  */
84 const static qio_info_t chip_data[] = {
85     /*   Manufacturer,   mfg_id, flash_id, id mask, Read Status,                Write Status,               QIE Bit */
86     { "MXIC",        0xC2,   0x2000, 0xFF00,    read_status_8b_rdsr,        write_status_8b_wrsr,       6 },
87     { "ISSI",        0x9D,   0x4000, 0xCF00,    read_status_8b_rdsr,        write_status_8b_wrsr,       6 }, /* IDs 0x40xx, 0x70xx */
88     { "WinBond",     0xEF,   0x4000, 0xFF00,    read_status_16b_rdsr_rdsr2, write_status_16b_wrsr,      9 },
89     { "GD",          0xC8,   0x6000, 0xFF00,    read_status_16b_rdsr_rdsr2, write_status_16b_wrsr,      9 },
90     { "XM25QU64A",   0x20,   0x3817, 0xFFFF,    read_status_8b_xmc25qu64a,  write_status_8b_xmc25qu64a, 6 },
91 
92     /* Final entry is default entry, if no other IDs have matched.
93 
94        This approach works for chips including:
95        GigaDevice (mfg ID 0xC8, flash IDs including 4016),
96        FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016)
97        BY25Q32 (mfg ID 0x68, flash IDs including 4016)
98     */
99     { NULL,          0xFF,    0xFFFF, 0xFFFF,   read_status_8b_rdsr2,       write_status_8b_wrsr2,      1 },
100 };
101 
102 #define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
103 
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);
107 
108 /* Generic function to use the "user command" SPI controller functionality
109    to send commands to the SPI flash and read the respopnse.
110 
111    The command passed here is always the on-the-wire command given to the SPI flash unit.
112 */
113 
114 /* dummy_len_plus values defined in ROM for SPI flash configuration */
bootloader_read_flash_id(void)115 uint32_t bootloader_read_flash_id(void)
116 {
117     uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24);
118     id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
119     return id;
120 }
121 
bootloader_enable_qio_mode(void)122 void bootloader_enable_qio_mode(void)
123 {
124     uint32_t raw_flash_id;
125     uint8_t mfg_id;
126     uint16_t flash_id;
127     size_t i;
128 
129     ESP_LOGD(TAG, "Probing for QIO mode enable...");
130     esp_rom_spiflash_wait_idle(&g_rom_flashchip);
131 
132     raw_flash_id = g_rom_flashchip.device_id;
133     ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id);
134 
135     mfg_id = (raw_flash_id >> 16) & 0xFF;
136     flash_id = raw_flash_id & 0xFFFF;
137     ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
138 
139     for (i = 0; i < NUM_CHIPS - 1; i++) {
140         const qio_info_t *chip = &chip_data[i];
141         if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
142             ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
143             break;
144         }
145     }
146 
147     if (i == NUM_CHIPS - 1) {
148         ESP_LOGI(TAG, "Enabling default flash chip QIO");
149     }
150     enable_qio_mode(chip_data[i].read_status_fn,
151                     chip_data[i].write_status_fn,
152                     chip_data[i].status_qio_bit);
153 #if SOC_CACHE_SUPPORT_WRAP
154     bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
155 #endif
156 }
157 
enable_qio_mode(read_status_fn_t read_status_fn,write_status_fn_t write_status_fn,uint8_t status_qio_bit)158 static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
159                                  write_status_fn_t write_status_fn,
160                                  uint8_t status_qio_bit)
161 {
162     uint32_t status;
163     const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
164 
165     esp_rom_spiflash_wait_idle(&g_rom_flashchip);
166 
167     status = read_status_fn();
168     ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
169 
170     if ((status & (1 << status_qio_bit)) == 0) {
171         bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
172         write_status_fn(status | (1 << status_qio_bit));
173 
174         esp_rom_spiflash_wait_idle(&g_rom_flashchip);
175 
176         status = read_status_fn();
177         ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
178         if ((status & (1 << status_qio_bit)) == 0) {
179             ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode");
180             return ESP_FAIL;
181         }
182 
183     } else {
184         ESP_LOGD(TAG, "QIO mode already enabled in flash");
185     }
186 
187     ESP_LOGD(TAG, "Enabling QIO mode...");
188 
189     esp_rom_spiflash_read_mode_t mode;
190 #if CONFIG_ESPTOOLPY_FLASHMODE_QOUT
191     mode = ESP_ROM_SPIFLASH_QOUT_MODE;
192 #else
193     mode = ESP_ROM_SPIFLASH_QIO_MODE;
194 #endif
195 
196     esp_rom_spiflash_config_readmode(mode);
197 
198 #if CONFIG_IDF_TARGET_ESP32
199     int wp_pin = bootloader_flash_get_wp_pin();
200     esp_rom_spiflash_select_qio_pins(wp_pin, spiconfig);
201 #else
202     esp_rom_spiflash_select_qio_pins(esp_rom_efuse_get_flash_wp_gpio(), spiconfig);
203 #endif
204     return ESP_OK;
205 }
206 
read_status_8b_rdsr(void)207 static unsigned read_status_8b_rdsr(void)
208 {
209     return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
210 }
211 
read_status_8b_rdsr2(void)212 static unsigned read_status_8b_rdsr2(void)
213 {
214     return bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
215 }
216 
read_status_16b_rdsr_rdsr2(void)217 static unsigned read_status_16b_rdsr_rdsr2(void)
218 {
219     return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
220 }
221 
write_status_8b_wrsr(unsigned new_status)222 static void write_status_8b_wrsr(unsigned new_status)
223 {
224     bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
225 }
226 
write_status_8b_wrsr2(unsigned new_status)227 static void write_status_8b_wrsr2(unsigned new_status)
228 {
229     bootloader_execute_flash_command(CMD_WRSR2, new_status, 8, 0);
230 }
231 
write_status_16b_wrsr(unsigned new_status)232 static void write_status_16b_wrsr(unsigned new_status)
233 {
234     bootloader_execute_flash_command(CMD_WRSR, new_status, 16, 0);
235 }
236 
read_status_8b_xmc25qu64a(void)237 static unsigned read_status_8b_xmc25qu64a(void)
238 {
239     bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0);  /* Enter OTP mode */
240     esp_rom_spiflash_wait_idle(&g_rom_flashchip);
241     uint32_t read_status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
242     bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0);   /* Exit OTP mode */
243     return read_status;
244 }
245 
write_status_8b_xmc25qu64a(unsigned new_status)246 static void write_status_8b_xmc25qu64a(unsigned new_status)
247 {
248     bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0);  /* Enter OTP mode */
249     esp_rom_spiflash_wait_idle(&g_rom_flashchip);
250     bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
251     esp_rom_spiflash_wait_idle(&g_rom_flashchip);
252     bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0);   /* Exit OTP mode */
253 }
254