1 /*
2 * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "sdkconfig.h"
8 #include "esp_log.h"
9 #include "esp_err.h"
10 #include "esp_rom_gpio.h"
11 #include "esp32s3/rom/gpio.h"
12 #include "esp32s3/rom/spi_flash.h"
13 #include "esp32s3/rom/opi_flash.h"
14 #include "esp_private/spi_flash_os.h"
15 #include "opi_flash_private.h"
16 #include "soc/spi_mem_reg.h"
17 #include "soc/io_mux_reg.h"
18 #include "opi_flash_cmd_format_mxic.h"
19
20 #define SPI_FLASH_SPI_CMD_WRCR2 0x72
21 #define SPI_FLASH_SPI_CMD_RDSR 0x05
22 #define SPI_FLASH_SPI_CMD_RDCR 0x15
23 #define SPI_FLASH_SPI_CMD_WRSRCR 0x01
24
25 /**
26 * Supported Flash chip vendor id
27 */
28 #define ESP_FLASH_CHIP_MXIC_OCT 0xC2
29
30 const static char *TAG = "Octal Flash";
31 // default value is rom_default_spiflash_legacy_flash_func
32 extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs;
33 extern int SPI_write_enable(void *spi);
34 static uint32_t s_chip_id;
35
36
s_register_rom_function(void)37 static void s_register_rom_function(void)
38 {
39 static spiflash_legacy_funcs_t rom_func =
40 {
41 .read_sub_len = 32,
42 .write_sub_len = 32,
43 .unlock = esp_rom_opiflash_wait_idle,
44 .erase_block = esp_rom_opiflash_erase_block_64k,
45 .erase_sector = esp_rom_opiflash_erase_sector,
46 .read = esp_rom_opiflash_read,
47 .write = esp_rom_opiflash_write,
48 .wait_idle = esp_rom_opiflash_wait_idle,
49 .wren = esp_rom_opiflash_wren,
50 .erase_area = esp_rom_opiflash_erase_area,
51 };
52 rom_spiflash_legacy_funcs = &rom_func;
53 }
54
55 #if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
56 /*----------------------------------------------------------------------------------------------------
57 MXIC Specific Functions
58 -----------------------------------------------------------------------------------------------------*/
s_probe_mxic_chip(uint32_t chip_id,uint8_t * out_vendor_id)59 static esp_err_t s_probe_mxic_chip(uint32_t chip_id, uint8_t *out_vendor_id)
60 {
61 if (chip_id >> 16 != ESP_FLASH_CHIP_MXIC_OCT) {
62 return ESP_ERR_NOT_FOUND;
63 }
64 if (((chip_id >> 8) & 0xff) != 0x80) {
65 ESP_EARLY_LOGE(TAG, "Detected MXIC Flash, but memory type is not Octal");
66 return ESP_ERR_NOT_FOUND;
67 }
68 *out_vendor_id = ESP_FLASH_CHIP_MXIC_OCT;
69
70 return ESP_OK;
71 }
72
73 // 0x00: SPI; 0x01: STR OPI; 0x02: DTR OPI
s_set_flash_dtr_str_opi_mode(int spi_num,uint8_t val)74 static void s_set_flash_dtr_str_opi_mode(int spi_num, uint8_t val)
75 {
76 uint8_t cmd_len = 8;
77 int addr_bit_len = 32;
78 int dummy = 0;
79 int data_bit_len = 8;
80
81 SPI_write_enable(&g_rom_flashchip);
82 //SPI command, WRCR2
83 esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_FASTRD_MODE,
84 SPI_FLASH_SPI_CMD_WRCR2, cmd_len,
85 0, addr_bit_len,
86 dummy,
87 (uint8_t *)&val, data_bit_len,
88 NULL, 0,
89 ESP_ROM_OPIFLASH_SEL_CS0,
90 false);
91 }
92
93 //To set the output driver strength
s_set_flash_ouput_driver_strength(int spi_num,uint8_t strength)94 static void s_set_flash_ouput_driver_strength(int spi_num, uint8_t strength)
95 {
96 uint16_t reg_val = 0;
97 uint8_t sr_reg_val = 0;
98 uint8_t cr_reg_val = 0;
99 uint8_t cmd_len = 8;
100 uint32_t addr = 0;
101 int addr_bit_len = 0;
102 int dummy = 0;
103 int data_bit_len = 8;
104
105 //Read
106 //SPI command, RDSR
107 esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_FASTRD_MODE,
108 SPI_FLASH_SPI_CMD_RDSR, cmd_len,
109 addr, addr_bit_len,
110 dummy,
111 NULL, 0,
112 (uint8_t*)&sr_reg_val, data_bit_len,
113 ESP_ROM_OPIFLASH_SEL_CS0,
114 false);
115
116 //SPI command, RDCR
117 esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_FASTRD_MODE,
118 SPI_FLASH_SPI_CMD_RDCR, cmd_len,
119 addr, addr_bit_len,
120 dummy,
121 NULL, 0,
122 (uint8_t*)&cr_reg_val, data_bit_len,
123 ESP_ROM_OPIFLASH_SEL_CS0,
124 false);
125
126 //Modify
127 reg_val = (((cr_reg_val & 0xf8) | strength) << 8) | sr_reg_val;
128
129 //Write
130 //SPI command, WRSR/WRCR
131 data_bit_len = 16;
132 SPI_write_enable(&g_rom_flashchip);
133 esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_FASTRD_MODE,
134 SPI_FLASH_SPI_CMD_WRSRCR, cmd_len,
135 addr, addr_bit_len,
136 dummy,
137 (uint8_t*)®_val, data_bit_len,
138 NULL, 0,
139 ESP_ROM_OPIFLASH_SEL_CS0,
140 false);
141 }
142
s_set_pin_drive_capability(uint8_t drv)143 static void s_set_pin_drive_capability(uint8_t drv)
144 {
145 //flash clock
146 REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3);
147 //cs0
148 PIN_SET_DRV(IO_MUX_GPIO29_REG, 3);
149 }
150
s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode)151 static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode)
152 {
153 static const esp_rom_opiflash_def_t opiflash_cmd_def_mxic = OPI_CMD_FORMAT_MXIC();
154 esp_rom_opiflash_legacy_driver_init(&opiflash_cmd_def_mxic);
155 esp_rom_spiflash_wait_idle(&g_rom_flashchip);
156
157 // increase flash output driver strength
158 s_set_flash_ouput_driver_strength(1, 7);
159
160 // STR/DTR specific setting
161 esp_rom_spiflash_wait_idle(&g_rom_flashchip);
162 #if CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
163 s_set_pin_drive_capability(3);
164 s_set_flash_dtr_str_opi_mode(1, 0x1);
165 esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd);
166 esp_rom_spi_set_dtr_swap_mode(0, false, false);
167 esp_rom_spi_set_dtr_swap_mode(1, false, false);
168 #else //CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
169 s_set_pin_drive_capability(3);
170 s_set_flash_dtr_str_opi_mode(1, 0x2);
171 esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd);
172 esp_rom_spi_set_dtr_swap_mode(0, true, true);
173 esp_rom_spi_set_dtr_swap_mode(1, true, true);
174 #endif
175
176 esp_rom_opiflash_wait_idle();
177 }
178 #endif // #if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
179
s_mxic_set_required_regs(uint32_t chip_id)180 static void s_mxic_set_required_regs(uint32_t chip_id)
181 {
182 bool is_swap = false;
183 #if CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
184 is_swap = true;
185 #else
186 //STR mode does not need to enable ddr_swap registers
187 #endif
188 esp_rom_spi_set_dtr_swap_mode(0, is_swap, is_swap);
189 esp_rom_spi_set_dtr_swap_mode(1, is_swap, is_swap);
190 }
191
192
193 /*----------------------------------------------------------------------------------------------------
194 General Functions
195 -----------------------------------------------------------------------------------------------------*/
196 typedef struct opi_flash_func_t {
197 esp_err_t (*probe)(uint32_t flash_id, uint8_t *out_vendor_id); //Function pointer for detecting Flash chip vendor
198 void (*init)(esp_rom_spiflash_read_mode_t mode); //Function pointer for initialising certain Flash chips
199 void (*regs_set)(uint32_t flash_id); //Function pointer for setting required registers, decided by certain flash chips.
200 } opi_flash_func_t;
201
202 #if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
203 static const opi_flash_func_t opi_flash_func_mxic = {
204 .probe = &s_probe_mxic_chip,
205 .init = &s_flash_init_mxic,
206 .regs_set = &s_mxic_set_required_regs,
207 };
208 #endif
209
210 static const opi_flash_func_t *registered_chip_funcs[] = {
211 #if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
212 &opi_flash_func_mxic,
213 #endif
214 NULL,
215 };
216
217 //To check which Flash chip is used
218 static const opi_flash_func_t **s_chip_func = NULL;
219
esp_opiflash_init(uint32_t chip_id)220 esp_err_t esp_opiflash_init(uint32_t chip_id)
221 {
222 esp_err_t ret = ESP_FAIL;
223 esp_rom_spiflash_read_mode_t mode;
224 #if CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
225 mode = ESP_ROM_SPIFLASH_OPI_STR_MODE;
226 #elif CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
227 mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
228 #else
229 mode = ESP_ROM_SPIFLASH_FASTRD_MODE;
230 #endif
231
232 const opi_flash_func_t **chip_func = ®istered_chip_funcs[0];
233
234 uint8_t vendor_id = 0;
235 while (*chip_func) {
236 ret = (*chip_func)->probe(chip_id, &vendor_id);
237 if (ret == ESP_OK) {
238 // Detect this is the supported chip type
239 s_chip_id = chip_id;
240 (*chip_func)->init(mode);
241 s_register_rom_function();
242 break;
243 }
244 chip_func++;
245 }
246 s_chip_func = chip_func;
247
248 if (ret != ESP_OK) {
249 ESP_EARLY_LOGE(TAG, "No detected Flash chip, please check the menuconfig to see if the chip is supported");
250 abort();
251 }
252
253 return ESP_OK;
254 }
255
256 /**
257 * Add Flash chip specifically required MSPI register settings here
258 */
esp_opiflash_set_required_regs(void)259 void esp_opiflash_set_required_regs(void)
260 {
261 (*s_chip_func)->regs_set(s_chip_id);
262 }
263