1 /*
2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "soc/soc_caps.h"
8 #include "spi_flash_defs.h"
9 #include "memspi_host_driver.h"
10 #include "string.h"
11 #include "esp_log.h"
12 #include "esp_private/cache_utils.h"
13 #include "esp_flash_partitions.h"
14 #include "esp_memory_utils.h"
15
16
17 #define SPI_FLASH_HAL_MAX_WRITE_BYTES 64
18 #define SPI_FLASH_HAL_MAX_READ_BYTES 64
19
20 DRAM_ATTR static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER();
21
22 #if SOC_MEMSPI_IS_INDEPENDENT
23 extern void spi_flash_hal_gpspi_poll_cmd_done(spi_flash_host_inst_t *host);
24 extern esp_err_t spi_flash_hal_gpspi_device_config(spi_flash_host_inst_t *host);
25 esp_err_t spi_flash_hal_gpspi_configure_host_io_mode(
26 spi_flash_host_inst_t *host,
27 uint32_t command,
28 uint32_t addr_bitlen,
29 int dummy_cyclelen_base,
30 esp_flash_io_mode_t io_mode);
31 extern esp_err_t spi_flash_hal_gpspi_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans);
32 extern esp_err_t spi_flash_hal_gpspi_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len);
33 extern uint32_t spi_flash_hal_gpspi_check_status(spi_flash_host_inst_t *host);
34 extern bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_inst_t *host, const void *p);
35 extern bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_inst_t *host, const void *p);
36
37 /** Default configuration for GPSPI */
38 static const spi_flash_host_driver_t esp_flash_gpspi_host = {
39 .dev_config = spi_flash_hal_gpspi_device_config,
40 .common_command = spi_flash_hal_gpspi_common_command,
41 .read_id = memspi_host_read_id_hs,
42 .erase_chip = memspi_host_erase_chip,
43 .erase_sector = memspi_host_erase_sector,
44 .erase_block = memspi_host_erase_block,
45 .read_status = memspi_host_read_status_hs,
46 .set_write_protect = memspi_host_set_write_protect,
47 .supports_direct_write = spi_flash_hal_gpspi_supports_direct_write,
48 .supports_direct_read = spi_flash_hal_gpspi_supports_direct_read,
49 .program_page = memspi_host_program_page,
50 .write_data_slicer = memspi_host_write_data_slicer,
51 .read = spi_flash_hal_gpspi_read,
52 .read_data_slicer = memspi_host_read_data_slicer,
53 .host_status = spi_flash_hal_gpspi_check_status,
54 .configure_host_io_mode = spi_flash_hal_gpspi_configure_host_io_mode,
55 .poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done,
56 .flush_cache = NULL,
57 .check_suspend = NULL,
58 .resume = spi_flash_hal_resume,
59 .suspend = spi_flash_hal_suspend,
60 };
61 #endif
62
memspi_host_init_pointers(memspi_host_inst_t * host,const memspi_host_config_t * cfg)63 esp_err_t memspi_host_init_pointers(memspi_host_inst_t *host, const memspi_host_config_t *cfg)
64 {
65 if (!esp_ptr_internal(host) && cfg->host_id == SPI1_HOST) {
66 return ESP_ERR_INVALID_ARG;
67 }
68
69 #if SOC_MEMSPI_IS_INDEPENDENT
70 if (cfg->host_id == SPI1_HOST)
71 host->inst.driver = &esp_flash_default_host;
72 else {
73 host->inst.driver = &esp_flash_gpspi_host;
74 }
75 #else
76 host->inst.driver = &esp_flash_default_host;
77 #endif
78
79 esp_err_t err = spi_flash_hal_init(host, cfg);
80 return err;
81 }
82
83 #ifndef CONFIG_SPI_FLASH_ROM_IMPL
84
85 static const char TAG[] = "memspi";
86
memspi_host_read_id_hs(spi_flash_host_inst_t * host,uint32_t * id)87 esp_err_t memspi_host_read_id_hs(spi_flash_host_inst_t *host, uint32_t *id)
88 {
89 uint32_t id_buf = 0;
90 spi_flash_trans_t t = {
91 .command = CMD_RDID,
92 .miso_len = 3,
93 .miso_data = ((uint8_t*) &id_buf),
94 };
95 host->driver->common_command(host, &t);
96
97 uint32_t raw_flash_id = id_buf;
98 ESP_EARLY_LOGV(TAG, "raw_chip_id: %X\n", raw_flash_id);
99 if (raw_flash_id == 0xFFFFFF || raw_flash_id == 0) {
100 ESP_EARLY_LOGE(TAG, "no response\n");
101 return ESP_ERR_FLASH_NO_RESPONSE;
102 }
103 // Byte swap the flash id as it's usually written the other way around
104 uint8_t mfg_id = raw_flash_id & 0xFF;
105 uint16_t flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
106 *id = ((uint32_t)mfg_id << 16) | flash_id;
107 ESP_EARLY_LOGV(TAG, "chip_id: %X\n", *id);
108 return ESP_OK;
109 }
110
memspi_host_read_status_hs(spi_flash_host_inst_t * host,uint8_t * out_sr)111 esp_err_t memspi_host_read_status_hs(spi_flash_host_inst_t *host, uint8_t *out_sr)
112 {
113 //NOTE: we do have a read id function, however it doesn't work in high freq
114 uint32_t stat_buf = 0;
115 spi_flash_trans_t t = {
116 .command = CMD_RDSR,
117 .miso_data = ((uint8_t*) &stat_buf),
118 .miso_len = 1
119 };
120 esp_err_t err = host->driver->common_command(host, &t);
121 if (err != ESP_OK) {
122 return err;
123 }
124 *out_sr = stat_buf;
125 return ESP_OK;
126 }
127
memspi_host_flush_cache(spi_flash_host_inst_t * host,uint32_t addr,uint32_t size)128 esp_err_t memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size)
129 {
130 if ((void*)((memspi_host_inst_t*)host)->spi == (void*) spi_flash_ll_get_hw(SPI1_HOST)) {
131 spi_flash_check_and_flush_cache(addr, size);
132 }
133 return ESP_OK;
134 }
135
memspi_host_erase_chip(spi_flash_host_inst_t * host)136 void memspi_host_erase_chip(spi_flash_host_inst_t *host)
137 {
138 spi_flash_trans_t t = { 0 };
139 t.command = CMD_CHIP_ERASE;
140 host->driver->common_command(host, &t);
141 }
142
143 // Only support 24bit address
memspi_host_erase_sector(spi_flash_host_inst_t * host,uint32_t start_address)144 void memspi_host_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address)
145 {
146 assert(start_address < 0x1000000);
147 spi_flash_trans_t t = {
148 .command = CMD_SECTOR_ERASE,
149 .address_bitlen = 24,
150 .address = start_address
151 };
152 host->driver->common_command(host, &t);
153 }
154
155 // Only support 24bit address
memspi_host_erase_block(spi_flash_host_inst_t * host,uint32_t start_address)156 void memspi_host_erase_block(spi_flash_host_inst_t *host, uint32_t start_address)
157 {
158 assert(start_address < 0x1000000);
159 spi_flash_trans_t t = {
160 .command = CMD_LARGE_BLOCK_ERASE,
161 .address_bitlen = 24,
162 .address = start_address,
163 };
164 host->driver->common_command(host, &t);
165 }
166
167 // Only support 24bit address
memspi_host_program_page(spi_flash_host_inst_t * host,const void * buffer,uint32_t address,uint32_t length)168 void memspi_host_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)
169 {
170 assert(address + length <= 0x1000000);
171 spi_flash_trans_t t = {
172 .command = CMD_PROGRAM_PAGE,
173 .address_bitlen = 24,
174 .address = address,
175 .mosi_len = length,
176 .mosi_data = buffer
177 };
178 host->driver->common_command(host, &t);
179 }
180
memspi_host_read(spi_flash_host_inst_t * host,void * buffer,uint32_t address,uint32_t read_len)181 esp_err_t memspi_host_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)
182 {
183 spi_flash_trans_t t = {
184 .command = CMD_READ,
185 .address_bitlen = 24,
186 .address = address,
187 .miso_len = read_len,
188 .miso_data = buffer
189 };
190 host->driver->common_command(host, &t);
191 return ESP_OK;
192 }
193
memspi_host_set_write_protect(spi_flash_host_inst_t * host,bool wp)194 esp_err_t memspi_host_set_write_protect(spi_flash_host_inst_t *host, bool wp)
195 {
196 spi_flash_trans_t t = {
197 .command = wp ? CMD_WRDI : CMD_WREN
198 };
199 host->driver->common_command(host, &t);
200 return ESP_OK;
201 }
202
203 // When encryption is enabled, etc. the data slicer may be complicated
204 // This is the simple case where the hardware has no other requirements than the size and page boundary
memspi_host_write_data_slicer(spi_flash_host_inst_t * host,uint32_t address,uint32_t len,uint32_t * align_address,uint32_t page_size)205 int memspi_host_write_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size)
206 {
207 uint32_t slicer_flag = ((spi_flash_hal_context_t*)host)->slicer_flags;
208 uint32_t align_addr = address;
209
210 if (slicer_flag & SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR) {
211 if (((align_addr % 2) != 0) && ((len % 2) != 0)) {
212 align_addr -= 1;
213 len += 1;
214 } else if (((align_addr % 2) != 0) && ((len % 2) == 0)) {
215 align_addr -= 1;
216 len += 2;
217 } else if (((align_addr % 2) == 0) && ((len % 2) != 0)) {
218 len += 1;
219 }
220 }
221
222 uint32_t end_bound = (align_addr/page_size + 1) * page_size;
223 // Shouldn't program cross the page, or longer than SPI_FLASH_HAL_MAX_WRITE_BYTES
224 uint32_t max_len = MIN(end_bound - align_addr, SPI_FLASH_HAL_MAX_WRITE_BYTES);
225 *align_address = align_addr;
226 return MIN(max_len, len);
227 }
228
memspi_host_read_data_slicer(spi_flash_host_inst_t * host,uint32_t address,uint32_t len,uint32_t * align_address,uint32_t page_size)229 int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size)
230 {
231 // Shouldn't read longer than SPI_FLASH_HAL_MAX_READ_BYTES
232 uint32_t slicer_flag = ((spi_flash_hal_context_t*)host)->slicer_flags;
233 uint32_t align_addr = address;
234
235 if (slicer_flag & SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR) {
236 if (((align_addr % 2) != 0) && ((len % 2) != 0)) {
237 align_addr -= 1;
238 len += 1;
239 } else if (((align_addr % 2) != 0) && ((len % 2) == 0)) {
240 align_addr -= 1;
241 len += 2;
242 } else if (((align_addr % 2) == 0) && ((len % 2) != 0)) {
243 len += 1;
244 }
245 }
246 uint32_t max_len = SPI_FLASH_HAL_MAX_READ_BYTES;
247 *align_address = align_addr;
248 return MIN(max_len, len);
249 }
250
251 #endif // CONFIG_SPI_FLASH_ROM_IMPL
252