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