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