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