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