1 /*
2 * Copyright (c) 2021-2025 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT espressif_esp32_flash_controller
8 #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
9
10 #define FLASH_WRITE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, write_block_size)
11 #define FLASH_ERASE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, erase_block_size)
12
13 /*
14 * HAL includes go first to
15 * avoid BIT macro redefinition
16 */
17 #include <esp_flash.h>
18 #include <spi_flash_mmap.h>
19 #include <soc/spi_struct.h>
20 #include <esp_flash_encrypt.h>
21 #include <esp_flash_internal.h>
22 #include <bootloader_flash_priv.h>
23
24 #include <zephyr/kernel.h>
25 #include <zephyr/device.h>
26 #include <zephyr/devicetree.h>
27 #include <zephyr/sys/util.h>
28 #include <stddef.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <stdint.h>
32 #include <zephyr/drivers/flash.h>
33 #include <soc.h>
34 #ifdef CONFIG_ESP_FLASH_ASYNC_IPM
35 #include <zephyr/drivers/ipm.h>
36 #endif
37
38 #include <zephyr/logging/log.h>
39 LOG_MODULE_REGISTER(flash_esp32, CONFIG_FLASH_LOG_LEVEL);
40
41 #define FLASH_SEM_TIMEOUT (k_is_in_isr() ? K_NO_WAIT : K_FOREVER)
42
43 #ifdef CONFIG_ESP32_EFUSE_VIRTUAL_KEEP_IN_FLASH
44 #define ENCRYPTION_IS_VIRTUAL (!efuse_hal_flash_encryption_enabled())
45 #else
46 #define ENCRYPTION_IS_VIRTUAL 0
47 #endif
48
49 #ifndef ALIGN_OFFSET
50 #define ALIGN_OFFSET(num, align) ((num) & ((align) - 1))
51 #endif
52
53 struct flash_esp32_dev_config {
54 spi_dev_t *controller;
55 };
56
57 #ifdef CONFIG_ESP_FLASH_ASYNC
58
59 #ifdef CONFIG_ESP_FLASH_ASYNC_WORK
60 K_THREAD_STACK_DEFINE(esp_flash_workqueue_stack, CONFIG_ESP_FLASH_ASYNC_WORK_STACK_SIZE);
61 static struct k_work_q esp_flash_workqueue;
62 #endif
63
64 enum flash_op {
65 FLASH_OP_NONE,
66 FLASH_OP_READ,
67 FLASH_OP_WRITE,
68 FLASH_OP_ERASE
69 };
70
71 typedef void (*flash_done_cb_t)(void *);
72
73 struct flash_req {
74 enum flash_op op;
75 off_t addr;
76 size_t len;
77 void *buf;
78 int result;
79 };
80
81 #ifdef CONFIG_ESP_FLASH_ASYNC_IPM
82 enum host_remote_cmd {
83 CMD_NONE,
84 CMD_REQUEST,
85 CMD_RESPONSE
86 };
87 #endif
88 #endif /* CONFIG_ESP_FLASH_ASYNC */
89
90 struct flash_esp32_dev_data {
91 #ifdef CONFIG_MULTITHREADING
92 #ifdef CONFIG_ESP_FLASH_ASYNC
93 const struct device *dev;
94 struct k_mutex lock;
95 struct flash_req req;
96 struct k_work work;
97 struct k_sem sync;
98 #ifdef CONFIG_ESP_FLASH_ASYNC_IPM
99 const struct device *ipm;
100 struct k_work remote_work;
101 struct flash_req remote_req;
102 struct k_sem remote_sync;
103 #endif
104 #endif
105 struct k_sem sem;
106 #endif /* CONFIG_MULTITHREADING */
107 };
108
109 static const struct flash_parameters flash_esp32_parameters = {
110 .write_block_size = FLASH_WRITE_BLK_SZ,
111 .erase_value = 0xff,
112 };
113
114 #if defined(CONFIG_MULTITHREADING) && !defined(CONFIG_ESP_FLASH_ASYNC)
flash_esp32_sem_take(const struct device * dev)115 static inline void flash_esp32_sem_take(const struct device *dev)
116 {
117 struct flash_esp32_dev_data *data = dev->data;
118
119 k_sem_take(&data->sem, FLASH_SEM_TIMEOUT);
120 }
121
flash_esp32_sem_give(const struct device * dev)122 static inline void flash_esp32_sem_give(const struct device *dev)
123 {
124 struct flash_esp32_dev_data *data = dev->data;
125
126 k_sem_give(&data->sem);
127 }
128 #else /* CONFIG_MULTITHREADING && !CONFIG_ESP_FLASH_ASYNC */
129
130 #define flash_esp32_sem_take(dev) do {} while (0)
131 #define flash_esp32_sem_give(dev) do {} while (0)
132
133 #endif /* CONFIG_MULTITHREADING && !CONFIG_ESP_FLASH_ASYNC */
134
135 #ifdef CONFIG_ESP_FLASH_HOST
136 #ifndef CONFIG_MCUBOOT
flash_esp32_read_check_enc(off_t address,void * buffer,size_t length)137 static int flash_esp32_read_check_enc(off_t address, void *buffer, size_t length)
138 {
139 int ret = 0;
140
141 if (esp_flash_encryption_enabled()) {
142 LOG_DBG("Flash read ENCRYPTED - address 0x%lx size 0x%x", address, length);
143 ret = esp_flash_read_encrypted(NULL, address, buffer, length);
144 } else {
145 LOG_DBG("Flash read RAW - address 0x%lx size 0x%x", address, length);
146 ret = esp_flash_read(NULL, buffer, address, length);
147 }
148
149 if (ret != 0) {
150 LOG_ERR("Flash read error: %d", ret);
151 return -EIO;
152 }
153
154 return 0;
155 }
156
flash_esp32_write_check_enc(off_t address,const void * buffer,size_t length)157 static int flash_esp32_write_check_enc(off_t address, const void *buffer, size_t length)
158 {
159 int ret = 0;
160
161 if (esp_flash_encryption_enabled() && !ENCRYPTION_IS_VIRTUAL) {
162 LOG_DBG("Flash write ENCRYPTED - address 0x%lx size 0x%x", address, length);
163 ret = esp_flash_write_encrypted(NULL, address, buffer, length);
164 } else {
165 LOG_DBG("Flash write RAW - address 0x%lx size 0x%x", address, length);
166 ret = esp_flash_write(NULL, buffer, address, length);
167 }
168
169 if (ret != 0) {
170 LOG_ERR("Flash write error: %d", ret);
171 return -EIO;
172 }
173
174 return 0;
175 }
176
177 #ifdef CONFIG_ESP_FLASH_ENCRYPTION
178 #define FLASH_BUFFER_SIZE 32
179
180 static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size, bool erase);
181 static bool aligned_flash_erase(size_t addr, size_t size);
182
183 /* Auxiliar buffer to store the sector that will be partially written */
184 static uint8_t write_aux_buf[FLASH_SECTOR_SIZE] = {0};
185
186 /* Auxiliar buffer to store the sector that will be partially erased */
187 static uint8_t erase_aux_buf[FLASH_SECTOR_SIZE] = {0};
188
aligned_flash_write(size_t dest_addr,const void * src,size_t size,bool erase)189 static bool aligned_flash_write(size_t dest_addr, const void *src, size_t size, bool erase)
190 {
191 bool flash_encryption_enabled = esp_flash_encryption_enabled();
192
193 /* When flash encryption is enabled, write alignment is 32 bytes, however to avoid
194 * inconsistences the region may be erased right before writing, thus the alignment
195 * is set to the erase required alignment (FLASH_SECTOR_SIZE).
196 * When flash encryption is not enabled, regular write alignment is 4 bytes.
197 */
198 size_t alignment = flash_encryption_enabled ? (erase ? FLASH_SECTOR_SIZE : 32) : 4;
199
200 if (IS_ALIGNED(dest_addr, alignment) && IS_ALIGNED((uintptr_t)src, 4) &&
201 IS_ALIGNED(size, alignment)) {
202 /* A single write operation is enough when all parameters are aligned */
203
204 if (flash_encryption_enabled && erase) {
205 if (esp_flash_erase_region(NULL, dest_addr, size) != ESP_OK) {
206 LOG_ERR("%s: Flash erase failed at 0x%08lx", __func__,
207 (uintptr_t)dest_addr);
208 return false;
209 }
210 }
211 return flash_esp32_write_check_enc(dest_addr, (void *)src, size) == ESP_OK;
212 }
213
214 LOG_DBG("%s: forcing unaligned write dest_addr: 0x%08lx src: 0x%08lx size: 0x%x erase: %c",
215 __func__, (uintptr_t)dest_addr, (uintptr_t)src, size, erase ? 't' : 'f');
216
217 size_t write_addr = dest_addr;
218 size_t bytes_remaining = size;
219 size_t src_offset = 0;
220
221 while (bytes_remaining > 0) {
222 size_t aligned_curr_addr = ROUND_DOWN(write_addr, alignment);
223 size_t curr_buf_off = write_addr - aligned_curr_addr;
224 size_t chunk_len = MIN(bytes_remaining, FLASH_SECTOR_SIZE - curr_buf_off);
225
226 /* Read data before modifying */
227 if (flash_esp32_read_check_enc(aligned_curr_addr, write_aux_buf,
228 ROUND_UP(chunk_len, alignment)) != ESP_OK) {
229 LOG_ERR("%s: Flash read failed at 0x%08lx", __func__,
230 (uintptr_t)aligned_curr_addr);
231 return false;
232 }
233
234 /* Erase if needed */
235 if (flash_encryption_enabled && erase) {
236 if (esp_flash_erase_region(NULL, aligned_curr_addr,
237 ROUND_UP(chunk_len, FLASH_SECTOR_SIZE)) !=
238 ESP_OK) {
239 LOG_ERR("%s: Flash erase failed at 0x%08lx", __func__,
240 (uintptr_t)aligned_curr_addr);
241 return false;
242 }
243 }
244
245 /* Merge data into buffer */
246 memcpy(&write_aux_buf[curr_buf_off], &((const uint8_t *)src)[src_offset],
247 chunk_len);
248
249 /* Write back aligned chunk */
250 if (flash_esp32_write_check_enc(aligned_curr_addr, write_aux_buf,
251 ROUND_UP(chunk_len, alignment)) != ESP_OK) {
252 LOG_ERR("%s: Flash write failed at 0x%08lx", __func__,
253 (uintptr_t)aligned_curr_addr);
254 return false;
255 }
256
257 write_addr += chunk_len;
258 src_offset += chunk_len;
259 bytes_remaining -= chunk_len;
260 }
261
262 return true;
263 }
264
erase_partial_sector(size_t addr,size_t sector_size,size_t erase_start,size_t erase_end)265 static bool erase_partial_sector(size_t addr, size_t sector_size, size_t erase_start,
266 size_t erase_end)
267 {
268 /* Read full sector before erasing */
269 if (flash_esp32_read_check_enc(addr, erase_aux_buf, sector_size) != ESP_OK) {
270 LOG_ERR("%s: Flash read failed at 0x%08lx", __func__, (uintptr_t)addr);
271 return false;
272 }
273 /* Erase full sector */
274 if (esp_flash_erase_region(NULL, addr, sector_size) != ESP_OK) {
275 LOG_ERR("%s: Flash erase failed at 0x%08lx", __func__, (uintptr_t)addr);
276 return false;
277 }
278 /* Write back preserved head data up to erase_start */
279 if (erase_start > 0) {
280 if (!aligned_flash_write(addr, erase_aux_buf, erase_start, false)) {
281 LOG_ERR("%s: Flash write failed at 0x%08lx", __func__, (uintptr_t)addr);
282 return false;
283 }
284 }
285 /* Write back preserved tail data from erase_end up to sector end */
286 if (erase_end < sector_size) {
287 if (!aligned_flash_write(addr + erase_end, &erase_aux_buf[erase_end],
288 sector_size - erase_end, false)) {
289 LOG_ERR("%s: Flash write failed at 0x%08lx", __func__,
290 (uintptr_t)(addr + erase_end));
291 return false;
292 }
293 }
294 return true;
295 }
296
aligned_flash_erase(size_t addr,size_t size)297 static bool aligned_flash_erase(size_t addr, size_t size)
298 {
299 if (IS_ALIGNED(addr, FLASH_SECTOR_SIZE) && IS_ALIGNED(size, FLASH_SECTOR_SIZE)) {
300 /* A single erase operation is enough when all parameters are aligned */
301 return esp_flash_erase_region(NULL, addr, size) == ESP_OK;
302 }
303
304 const size_t sector_size = FLASH_SECTOR_SIZE;
305 const size_t start_addr = ROUND_DOWN(addr, sector_size);
306 const size_t end_addr = ROUND_UP(addr + size, sector_size);
307 const size_t total_len = end_addr - start_addr;
308
309 LOG_DBG("%s: forcing unaligned erase on sector Offset: "
310 "0x%08lx Length: 0x%x total_len: 0x%x",
311 __func__, (uintptr_t)addr, (int)size, total_len);
312
313 size_t current_addr = start_addr;
314
315 while (current_addr < end_addr) {
316 bool preserve_head = (addr > current_addr);
317 bool preserve_tail = ((addr + size) < (current_addr + sector_size));
318
319 if (preserve_head || preserve_tail) {
320 size_t erase_start = preserve_head ? (addr - current_addr) : 0;
321 size_t erase_end =
322 MIN(current_addr + sector_size, addr + size) - current_addr;
323
324 LOG_DBG("%s: partial sector erase from: 0x%08lx to: 0x%08lx Length: 0x%x",
325 __func__, (uintptr_t)(current_addr + erase_start),
326 (uintptr_t)(current_addr + erase_end), erase_end - erase_start);
327
328 if (!erase_partial_sector(current_addr, sector_size, erase_start,
329 erase_end)) {
330 return false;
331 }
332
333 current_addr += sector_size;
334 } else {
335 /* Full sector erase is safe, erase the next consecutive full sectors */
336 size_t contiguous_size =
337 ROUND_DOWN(addr + size, sector_size) - current_addr;
338
339 LOG_DBG("%s: sectors erased from: 0x%08lx length: 0x%x", __func__,
340 (uintptr_t)current_addr, contiguous_size);
341
342 if (esp_flash_erase_region(NULL, current_addr, contiguous_size) != ESP_OK) {
343 LOG_ERR("%s: Flash erase failed at 0x%08lx", __func__,
344 (uintptr_t)current_addr);
345 return false;
346 }
347
348 current_addr += contiguous_size;
349 }
350 }
351
352 return true;
353 }
354 #endif /* CONFIG_ESP_FLASH_ENCRYPTION */
355 #endif /* !CONFIG_MCUBOOT */
356
357 #ifdef CONFIG_MCUBOOT
358 #define READ_BUFFER_SIZE 32
flash_esp32_is_aligned(off_t address,void * buffer,size_t length)359 static bool flash_esp32_is_aligned(off_t address, void *buffer, size_t length)
360 {
361 /* check if address, buffer pointer, and length are 4-byte aligned */
362 return ((address & 3) == 0) && (((uintptr_t)buffer & 3) == 0) && ((length & 3) == 0);
363 }
364 #endif
365
flash_esp32_read(const struct device * dev,off_t address,void * buffer,size_t length)366 static int flash_esp32_read(const struct device *dev, off_t address, void *buffer, size_t length)
367 {
368 int ret = 0;
369
370 if (length == 0U) {
371 return 0;
372 }
373
374 #ifdef CONFIG_MCUBOOT
375 uint8_t *dest_ptr = (uint8_t *)buffer;
376 size_t remaining = length;
377 size_t copy_size = 0;
378 size_t aligned_size = 0;
379 bool allow_decrypt = esp_flash_encryption_enabled();
380
381 if (flash_esp32_is_aligned(address, buffer, length)) {
382 ret = esp_rom_flash_read(address, buffer, length, allow_decrypt);
383 return (ret == ESP_OK) ? 0 : -EIO;
384 }
385
386 /* handle unaligned reading */
387 uint8_t __aligned(4) temp_buf[READ_BUFFER_SIZE + 8];
388 while (remaining > 0) {
389 size_t addr_offset = address & 3;
390 size_t buf_offset = (uintptr_t)dest_ptr & 3;
391
392 copy_size = (remaining > READ_BUFFER_SIZE) ? READ_BUFFER_SIZE : remaining;
393
394 if (addr_offset == 0 && buf_offset == 0 && copy_size >= 4) {
395 aligned_size = copy_size & ~3;
396 ret = esp_rom_flash_read(address, dest_ptr, aligned_size, allow_decrypt);
397 if (ret != ESP_OK) {
398 return -EIO;
399 }
400
401 address += aligned_size;
402 dest_ptr += aligned_size;
403 remaining -= aligned_size;
404 } else {
405 size_t start_addr = address - addr_offset;
406
407 aligned_size = (copy_size + addr_offset + 3) & ~3;
408
409 ret = esp_rom_flash_read(start_addr, temp_buf, aligned_size, allow_decrypt);
410 if (ret != ESP_OK) {
411 return -EIO;
412 }
413
414 memcpy(dest_ptr, temp_buf + addr_offset, copy_size);
415
416 address += copy_size;
417 dest_ptr += copy_size;
418 remaining -= copy_size;
419 }
420 }
421 #else
422 flash_esp32_sem_take(dev);
423 ret = flash_esp32_read_check_enc(address, buffer, length);
424 flash_esp32_sem_give(dev);
425 #endif /* CONFIG_MCUBOOT */
426
427 if (ret != 0) {
428 LOG_ERR("Flash read error: %d", ret);
429 return -EIO;
430 }
431
432 return 0;
433 }
434
flash_esp32_write(const struct device * dev,off_t address,const void * buffer,size_t length)435 static int flash_esp32_write(const struct device *dev, off_t address, const void *buffer,
436 size_t length)
437 {
438 int ret = 0;
439
440 #ifdef CONFIG_MCUBOOT
441 if (!flash_esp32_is_aligned(address, (void *)buffer, length)) {
442 LOG_ERR("Unaligned flash write is not supported");
443 return -EINVAL;
444 }
445
446 bool encrypt = esp_flash_encryption_enabled();
447
448 ret = esp_rom_flash_write(address, (void *)buffer, length, encrypt);
449 #else
450 flash_esp32_sem_take(dev);
451
452 #ifdef CONFIG_ESP_FLASH_ENCRYPTION
453 bool erase = false;
454
455 if (esp_flash_encryption_enabled()) {
456 /* Ensuring flash region has been erased before writing in order to
457 * avoid inconsistences when hardware flash encryption is enabled.
458 */
459 erase = true;
460 }
461
462 if (!aligned_flash_write(address, buffer, length, erase)) {
463 LOG_ERR("%s: Flash erase before write failed", __func__);
464 ret = -1;
465 }
466 #else
467 ret = flash_esp32_write_check_enc(address, buffer, length);
468 #endif /* CONFIG_ESP_FLASH_ENCRYPTION */
469
470 flash_esp32_sem_give(dev);
471 #endif /* CONFIG_MCUBOOT */
472
473 if (ret != 0) {
474 LOG_ERR("Flash write error: %d", ret);
475 return -EIO;
476 }
477
478 return 0;
479 }
480
flash_esp32_erase(const struct device * dev,off_t start,size_t len)481 static int flash_esp32_erase(const struct device *dev, off_t start, size_t len)
482 {
483 int ret = 0;
484
485 #ifdef CONFIG_MCUBOOT
486 ret = esp_rom_flash_erase_range(start, len);
487 #else
488 flash_esp32_sem_take(dev);
489
490 #ifdef CONFIG_ESP_FLASH_ENCRYPTION
491 if (!aligned_flash_erase(start, len)) {
492 ret = -EIO;
493 }
494
495 if (esp_flash_encryption_enabled()) {
496 uint8_t erased_val_buf[FLASH_BUFFER_SIZE];
497 uint32_t bytes_remaining = len;
498 uint32_t offset = start;
499 uint32_t bytes_written = MIN(sizeof(erased_val_buf), len);
500
501 memset(erased_val_buf,
502 flash_get_parameters(dev)->erase_value, sizeof(erased_val_buf));
503
504 /* When hardware flash encryption is enabled, force expected erased
505 * value (0xFF) into flash when erasing a region.
506 *
507 * This is handled on this implementation because MCUboot's state
508 * machine relies on erased valued data (0xFF) readed from a
509 * previously erased region that was not written yet, however when
510 * hardware flash encryption is enabled, the flash read always
511 * decrypts whats being read from flash, thus a region that was
512 * erased would not be read as what MCUboot expected (0xFF).
513 */
514 while (bytes_remaining != 0) {
515 if (!aligned_flash_write(offset, erased_val_buf, bytes_written, false)) {
516 LOG_ERR("%s: Flash erase failed", __func__);
517 return -1;
518 }
519 offset += bytes_written;
520 bytes_remaining -= bytes_written;
521 }
522 }
523 #else
524 ret = esp_flash_erase_region(NULL, start, len);
525 #endif /* CONFIG_ESP_FLASH_ENCRYPTION */
526
527 flash_esp32_sem_give(dev);
528 #endif /* CONFIG_MCUBOOT */
529
530 if (ret != 0) {
531 LOG_ERR("Flash erase error: %d", ret);
532 return -EIO;
533 }
534 return 0;
535 }
536 #endif /* CONFIG_ESP_FLASH_HOST */
537
538 #ifdef CONFIG_ESP_FLASH_ASYNC
flash_esp32_read_async(const struct device * dev,off_t address,void * buffer,size_t length)539 static IRAM_ATTR int flash_esp32_read_async(const struct device *dev, off_t address,
540 void *buffer, size_t length)
541 {
542 struct flash_esp32_dev_data *data = dev->data;
543 struct flash_req *req = &data->req;
544
545 if (k_is_in_isr()) {
546 return -EINVAL;
547 }
548 if (k_mutex_lock(&data->lock, K_TIMEOUT_ABS_SEC(CONFIG_ESP_FLASH_ASYNC_TIMEOUT))) {
549 return -ETIMEDOUT;
550 }
551 req->op = FLASH_OP_READ;
552 req->addr = address;
553 req->len = length;
554 req->buf = buffer;
555
556 k_work_submit(&data->work);
557 k_sem_take(&data->sync, FLASH_SEM_TIMEOUT);
558 k_mutex_unlock(&data->lock);
559
560 return req->result;
561 }
562
flash_esp32_write_async(const struct device * dev,off_t address,const void * buffer,size_t length)563 static IRAM_ATTR int flash_esp32_write_async(const struct device *dev, off_t address,
564 const void *buffer, size_t length)
565 {
566 struct flash_esp32_dev_data *data = dev->data;
567 struct flash_req *req = &data->req;
568
569 if (k_is_in_isr()) {
570 return -EINVAL;
571 }
572 if (k_mutex_lock(&data->lock, K_TIMEOUT_ABS_SEC(CONFIG_ESP_FLASH_ASYNC_TIMEOUT))) {
573 return -ETIMEDOUT;
574 }
575 req->op = FLASH_OP_WRITE;
576 req->addr = address;
577 req->len = length;
578 req->buf = (void *)buffer;
579
580 k_work_submit(&data->work);
581 k_sem_take(&data->sync, FLASH_SEM_TIMEOUT);
582 k_mutex_unlock(&data->lock);
583
584 return req->result;
585 }
586
flash_esp32_erase_async(const struct device * dev,off_t start,size_t length)587 static IRAM_ATTR int flash_esp32_erase_async(const struct device *dev, off_t start, size_t length)
588 {
589 struct flash_esp32_dev_data *data = dev->data;
590 struct flash_req *req = &data->req;
591
592 if (k_is_in_isr()) {
593 return -EINVAL;
594 }
595 if (k_mutex_lock(&data->lock, K_TIMEOUT_ABS_SEC(CONFIG_ESP_FLASH_ASYNC_TIMEOUT))) {
596 return -ETIMEDOUT;
597 }
598 req->op = FLASH_OP_ERASE;
599 req->addr = start;
600 req->len = length;
601 req->buf = NULL;
602
603 k_work_submit(&data->work);
604 k_sem_take(&data->sync, FLASH_SEM_TIMEOUT);
605 k_mutex_unlock(&data->lock);
606
607 return req->result;
608 }
609
610 #ifdef CONFIG_ESP_FLASH_HOST
flash_process_request(const struct device * dev,struct flash_req * req)611 static void flash_process_request(const struct device *dev, struct flash_req *req)
612 {
613 switch (req->op) {
614 case FLASH_OP_READ:
615 req->result = flash_esp32_read(dev, req->addr, req->buf, req->len);
616 break;
617 case FLASH_OP_WRITE:
618 req->result = flash_esp32_write(dev, req->addr, req->buf, req->len);
619 break;
620 case FLASH_OP_ERASE:
621 req->result = flash_esp32_erase(dev, req->addr, req->len);
622 break;
623 default:
624 req->result = -EINVAL;
625 break;
626 }
627 }
628 #endif
629
flash_worker(struct k_work * work)630 static IRAM_ATTR void flash_worker(struct k_work *work)
631 {
632 struct flash_esp32_dev_data *data = CONTAINER_OF(work, struct flash_esp32_dev_data, work);
633
634 #ifdef CONFIG_ESP_FLASH_HOST
635 if (data->req.op) {
636 flash_process_request(data->dev, &data->req);
637 data->req.op = FLASH_OP_NONE;
638 k_sem_give(&data->sync);
639 }
640 #else /* CONFIG_ESP_FLASH_REMOTE */
641 #ifdef CONFIG_ESP_FLASH_ASYNC_IPM
642 /* remote cpu -> host cpu request */
643 ipm_send(data->ipm, -1, CMD_REQUEST, &data->req, sizeof(struct flash_req));
644 #else
645 ARG_UNUSED(data);
646 #endif
647 #endif
648 }
649
650 #ifdef CONFIG_ESP_FLASH_ASYNC_IPM
651 #ifdef CONFIG_ESP_FLASH_HOST
flash_remote_worker(struct k_work * work)652 static IRAM_ATTR void flash_remote_worker(struct k_work *work)
653 {
654 struct flash_esp32_dev_data *data = CONTAINER_OF(work, struct flash_esp32_dev_data,
655 remote_work);
656 if (data->remote_req.op) {
657 /* TODO: without waiting here the subsequent IPM operations would fail */
658 k_sleep(K_USEC(1));
659 flash_process_request(data->dev, &data->remote_req);
660 data->remote_req.op = FLASH_OP_NONE;
661 /* host cpu -> remote cpu response */
662 ipm_send(data->ipm, -1, CMD_RESPONSE, &data->remote_req, sizeof(struct flash_req));
663 }
664 }
665 #endif
666
flash_cpu01_receive_cb(const struct device * ipm,void * user_data,uint32_t id,volatile void * shm)667 static void flash_cpu01_receive_cb(const struct device *ipm, void *user_data, uint32_t id,
668 volatile void *shm)
669 {
670 struct flash_esp32_dev_data *data = (struct flash_esp32_dev_data *) user_data;
671 volatile struct flash_req *req = (volatile struct flash_req *)shm;
672
673 #ifdef CONFIG_ESP_FLASH_HOST
674 if (id == CMD_REQUEST) {
675 data->remote_req = *req;
676 k_work_submit(&data->remote_work);
677 }
678 #else
679 if (id == CMD_RESPONSE) {
680 data->req.result = req->result;
681 k_sem_give(&data->sync);
682 }
683 #endif
684 }
685 #endif
686 #endif /* CONFIG_ESP_FLASH_ASYNC */
687
688 #if CONFIG_FLASH_PAGE_LAYOUT
689 static const struct flash_pages_layout flash_esp32_pages_layout = {
690 .pages_count = DT_REG_SIZE(SOC_NV_FLASH_NODE) / FLASH_ERASE_BLK_SZ,
691 .pages_size = DT_PROP(SOC_NV_FLASH_NODE, erase_block_size),
692 };
693
flash_esp32_page_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)694 void flash_esp32_page_layout(const struct device *dev,
695 const struct flash_pages_layout **layout,
696 size_t *layout_size)
697 {
698 *layout = &flash_esp32_pages_layout;
699 *layout_size = 1;
700 }
701 #endif
702
flash_esp32_get_parameters(const struct device * dev)703 static const struct flash_parameters *flash_esp32_get_parameters(const struct device *dev)
704 {
705 ARG_UNUSED(dev);
706
707 return &flash_esp32_parameters;
708 }
709
flash_esp32_init(const struct device * dev)710 static int flash_esp32_init(const struct device *dev)
711 {
712 #ifdef CONFIG_MULTITHREADING
713 struct flash_esp32_dev_data *const data = dev->data;
714
715 #ifdef CONFIG_ESP_FLASH_ASYNC
716 k_mutex_init(&data->lock);
717 k_sem_init(&data->sem, 0, 1);
718 k_sem_init(&data->sync, 0, 1);
719 k_work_init(&data->work, flash_worker);
720
721 #ifdef CONFIG_ESP_FLASH_ASYNC_WORK
722 k_work_queue_init(&esp_flash_workqueue);
723 k_work_queue_start(&esp_flash_workqueue, esp_flash_workqueue_stack,
724 K_THREAD_STACK_SIZEOF(esp_flash_workqueue_stack),
725 CONFIG_ESP_FLASH_ASYNC_WORK_PRIORITY, NULL);
726 k_work_submit_to_queue(&esp_flash_workqueue, &data->work);
727 #endif
728
729 #ifdef CONFIG_ESP_FLASH_ASYNC_IPM
730 data->ipm = DEVICE_DT_GET(DT_NODELABEL(ipm0));
731
732 if (data->ipm) {
733 ipm_register_callback(data->ipm, flash_cpu01_receive_cb, data);
734 } else {
735 LOG_ERR("Failed to get ipm0 device");
736 return -ENODEV;
737 }
738 #ifdef CONFIG_ESP_FLASH_HOST
739 k_sem_init(&data->remote_sync, 0, 1);
740 k_work_init(&data->remote_work, flash_remote_worker);
741 #endif
742 #endif
743
744 #else /* CONFIG_ESP_FLASH_ASYNC */
745
746 k_sem_init(&data->sem, 1, 1);
747
748 #endif /* CONFIG_ESP_FLASH_ASYNC */
749 #endif /* CONFIG_MULTITHREADING */
750 return 0;
751 }
752
753 static DEVICE_API(flash, flash_esp32_driver_api) = {
754 #ifdef CONFIG_ESP_FLASH_ASYNC
755 .read = flash_esp32_read_async,
756 .write = flash_esp32_write_async,
757 .erase = flash_esp32_erase_async,
758 #else
759 .read = flash_esp32_read,
760 .write = flash_esp32_write,
761 .erase = flash_esp32_erase,
762 #endif
763 .get_parameters = flash_esp32_get_parameters,
764 #ifdef CONFIG_FLASH_PAGE_LAYOUT
765 .page_layout = flash_esp32_page_layout,
766 #endif
767 };
768
769 static struct flash_esp32_dev_data flash_esp32_data;
770
771 static const struct flash_esp32_dev_config flash_esp32_config = {
772 .controller = (spi_dev_t *) DT_INST_REG_ADDR(0),
773 };
774
775 DEVICE_DT_INST_DEFINE(0, flash_esp32_init,
776 NULL,
777 &flash_esp32_data, &flash_esp32_config,
778 POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
779 &flash_esp32_driver_api);
780