1 /*
2  * Copyright (c) 2017-2024 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Linaro Limited
4  * Copyright (c) 2016 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <errno.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/init.h>
14 #include <soc.h>
15 #include <zephyr/drivers/flash.h>
16 #include <string.h>
17 #include <nrfx_nvmc.h>
18 #include <nrf_erratas.h>
19 
20 #include "soc_flash_nrf.h"
21 
22 #define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
23 #include <zephyr/logging/log.h>
24 LOG_MODULE_REGISTER(flash_nrf);
25 
26 #if DT_NODE_HAS_STATUS_OKAY(DT_INST(0, nordic_nrf51_flash_controller))
27 #define DT_DRV_COMPAT nordic_nrf51_flash_controller
28 #elif DT_NODE_HAS_STATUS_OKAY(DT_INST(0, nordic_nrf52_flash_controller))
29 #define DT_DRV_COMPAT nordic_nrf52_flash_controller
30 #elif DT_NODE_HAS_STATUS_OKAY(DT_INST(0, nordic_nrf53_flash_controller))
31 #define DT_DRV_COMPAT nordic_nrf53_flash_controller
32 #elif DT_NODE_HAS_STATUS_OKAY(DT_INST(0, nordic_nrf91_flash_controller))
33 #define DT_DRV_COMPAT nordic_nrf91_flash_controller
34 #else
35 #error No matching compatible for soc_flash_nrf.c
36 #endif
37 
38 #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
39 
40 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
41 #define FLASH_SLOT_WRITE     7500
42 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE)
43 #define FLASH_SLOT_ERASE (MAX(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE_MS * 1000, \
44 			      7500))
45 #else
46 #define FLASH_SLOT_ERASE FLASH_PAGE_ERASE_MAX_TIME_US
47 #endif /* CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE */
48 
49 static int write_op(void *context); /* instance of flash_op_handler_t */
50 static int write_synchronously(off_t addr, const void *data, size_t len);
51 
52 static int erase_op(void *context); /* instance of flash_op_handler_t */
53 static int erase_synchronously(uint32_t addr, uint32_t size);
54 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
55 
56 static const struct flash_parameters flash_nrf_parameters = {
57 #if defined(CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS)
58 	.write_block_size = 1,
59 #else
60 	.write_block_size = 4,
61 #endif
62 	.erase_value = 0xff,
63 };
64 
65 #if defined(CONFIG_MULTITHREADING)
66 /* semaphore for locking flash resources (tickers) */
67 static struct k_sem sem_lock;
68 #define SYNC_INIT() k_sem_init(&sem_lock, 1, 1)
69 #define SYNC_LOCK() k_sem_take(&sem_lock, K_FOREVER)
70 #define SYNC_UNLOCK() k_sem_give(&sem_lock)
71 #else
72 #define SYNC_INIT()
73 #define SYNC_LOCK()
74 #define SYNC_UNLOCK()
75 #endif
76 
77 #if NRF52_ERRATA_242_PRESENT
78 #include <hal/nrf_power.h>
79 static int suspend_pofwarn(void);
80 static void restore_pofwarn(void);
81 
82 #define SUSPEND_POFWARN() suspend_pofwarn()
83 #define RESUME_POFWARN()  restore_pofwarn()
84 #else
85 #define SUSPEND_POFWARN() 0
86 #define RESUME_POFWARN()
87 #endif /* NRF52_ERRATA_242_PRESENT */
88 
89 static int write(off_t addr, const void *data, size_t len);
90 static int erase(uint32_t addr, uint32_t size);
91 
is_aligned_32(uint32_t data)92 static inline bool is_aligned_32(uint32_t data)
93 {
94 	return (data & 0x3) ? false : true;
95 }
96 
is_within_bounds(off_t addr,size_t len,off_t boundary_start,size_t boundary_size)97 static inline bool is_within_bounds(off_t addr, size_t len, off_t boundary_start,
98 				    size_t boundary_size)
99 {
100 	return (addr >= boundary_start &&
101 			(addr < (boundary_start + boundary_size)) &&
102 			(len <= (boundary_start + boundary_size - addr)));
103 }
104 
is_regular_addr_valid(off_t addr,size_t len)105 static inline bool is_regular_addr_valid(off_t addr, size_t len)
106 {
107 	return is_within_bounds(addr, len, 0, nrfx_nvmc_flash_size_get());
108 }
109 
is_uicr_addr_valid(off_t addr,size_t len)110 static inline bool is_uicr_addr_valid(off_t addr, size_t len)
111 {
112 #ifdef CONFIG_SOC_FLASH_NRF_UICR
113 	return is_within_bounds(addr, len, (off_t)NRF_UICR, sizeof(*NRF_UICR));
114 #else
115 	return false;
116 #endif /* CONFIG_SOC_FLASH_NRF_UICR */
117 }
118 
119 #if CONFIG_SOC_FLASH_NRF_UICR && IS_ENABLED(NRF91_ERRATA_7_ENABLE_WORKAROUND)
nrf91_errata_7_enter(void)120 static inline void nrf91_errata_7_enter(void)
121 {
122 	__disable_irq();
123 }
124 
nrf91_errata_7_exit(void)125 static inline void nrf91_errata_7_exit(void)
126 {
127 	__DSB();
128 	__enable_irq();
129 }
130 
nrf_buffer_read_91_uicr(void * data,off_t addr,size_t len)131 static void nrf_buffer_read_91_uicr(void *data, off_t addr, size_t len)
132 {
133 	nrf91_errata_7_enter();
134 	nrf_nvmc_buffer_read(data, (uint32_t)addr, len);
135 	nrf91_errata_7_exit();
136 }
137 #endif
138 
nvmc_wait_ready(void)139 static void nvmc_wait_ready(void)
140 {
141 	while (!nrfx_nvmc_write_done_check()) {
142 	}
143 }
144 
flash_nrf_read(const struct device * dev,off_t addr,void * data,size_t len)145 static int flash_nrf_read(const struct device *dev, off_t addr,
146 			    void *data, size_t len)
147 {
148 	const bool within_uicr = is_uicr_addr_valid(addr, len);
149 
150 	if (is_regular_addr_valid(addr, len)) {
151 		addr += DT_REG_ADDR(SOC_NV_FLASH_NODE);
152 	} else if (!within_uicr) {
153 		LOG_ERR("invalid address: 0x%08lx:%zu",
154 				(unsigned long)addr, len);
155 		return -EINVAL;
156 	}
157 
158 	if (!len) {
159 		return 0;
160 	}
161 
162 #if CONFIG_SOC_FLASH_NRF_UICR && IS_ENABLED(NRF91_ERRATA_7_ENABLE_WORKAROUND)
163 	if (within_uicr) {
164 		nrf_buffer_read_91_uicr(data, (uint32_t)addr, len);
165 		return 0;
166 	}
167 #endif
168 
169 	nrf_nvmc_buffer_read(data, (uint32_t)addr, len);
170 
171 	return 0;
172 }
173 
flash_nrf_write(const struct device * dev,off_t addr,const void * data,size_t len)174 static int flash_nrf_write(const struct device *dev, off_t addr,
175 			     const void *data, size_t len)
176 {
177 	int ret;
178 
179 	if (is_regular_addr_valid(addr, len)) {
180 		addr += DT_REG_ADDR(SOC_NV_FLASH_NODE);
181 	} else if (!is_uicr_addr_valid(addr, len)) {
182 		LOG_ERR("invalid address: 0x%08lx:%zu",
183 				(unsigned long)addr, len);
184 		return -EINVAL;
185 	}
186 
187 #if !defined(CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS)
188 	if (!is_aligned_32(addr) || (len % sizeof(uint32_t))) {
189 		LOG_ERR("not word-aligned: 0x%08lx:%zu",
190 				(unsigned long)addr, len);
191 		return -EINVAL;
192 	}
193 #endif
194 
195 	if (!len) {
196 		return 0;
197 	}
198 
199 	SYNC_LOCK();
200 
201 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
202 	if (nrf_flash_sync_is_required()) {
203 		ret = write_synchronously(addr, data, len);
204 	} else
205 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
206 	{
207 		ret = write(addr, data, len);
208 	}
209 
210 	SYNC_UNLOCK();
211 
212 	return ret;
213 }
214 
flash_nrf_erase(const struct device * dev,off_t addr,size_t size)215 static int flash_nrf_erase(const struct device *dev, off_t addr, size_t size)
216 {
217 	uint32_t pg_size = nrfx_nvmc_flash_page_size_get();
218 	uint32_t n_pages = size / pg_size;
219 	int ret;
220 
221 	if (is_regular_addr_valid(addr, size)) {
222 		/* Erase can only be done per page */
223 		if (((addr % pg_size) != 0) || ((size % pg_size) != 0)) {
224 			LOG_ERR("unaligned address: 0x%08lx:%zu",
225 					(unsigned long)addr, size);
226 			return -EINVAL;
227 		}
228 
229 		if (!n_pages) {
230 			return 0;
231 		}
232 
233 		addr += DT_REG_ADDR(SOC_NV_FLASH_NODE);
234 #ifdef CONFIG_SOC_FLASH_NRF_UICR
235 	} else if (addr != (off_t)NRF_UICR || size != sizeof(*NRF_UICR)) {
236 		LOG_ERR("invalid address: 0x%08lx:%zu",
237 				(unsigned long)addr, size);
238 		return -EINVAL;
239 	}
240 #else
241 	} else {
242 		LOG_ERR("invalid address: 0x%08lx:%zu",
243 				(unsigned long)addr, size);
244 		return -EINVAL;
245 	}
246 #endif /* CONFIG_SOC_FLASH_NRF_UICR */
247 
248 	SYNC_LOCK();
249 
250 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
251 	if (nrf_flash_sync_is_required()) {
252 		ret = erase_synchronously(addr, size);
253 	} else
254 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
255 	{
256 		ret = erase(addr, size);
257 	}
258 
259 	SYNC_UNLOCK();
260 
261 	return ret;
262 }
263 
flash_nrf_get_size(const struct device * dev,uint64_t * size)264 static int flash_nrf_get_size(const struct device *dev, uint64_t *size)
265 {
266 	ARG_UNUSED(dev);
267 
268 	*size = (uint64_t)nrfx_nvmc_flash_size_get();
269 
270 	return 0;
271 }
272 
273 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
274 static struct flash_pages_layout dev_layout;
275 
flash_nrf_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)276 static void flash_nrf_pages_layout(const struct device *dev,
277 				     const struct flash_pages_layout **layout,
278 				     size_t *layout_size)
279 {
280 	*layout = &dev_layout;
281 	*layout_size = 1;
282 }
283 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
284 
285 static const struct flash_parameters *
flash_nrf_get_parameters(const struct device * dev)286 flash_nrf_get_parameters(const struct device *dev)
287 {
288 	ARG_UNUSED(dev);
289 
290 	return &flash_nrf_parameters;
291 }
292 
293 static DEVICE_API(flash, flash_nrf_api) = {
294 	.read = flash_nrf_read,
295 	.write = flash_nrf_write,
296 	.erase = flash_nrf_erase,
297 	.get_parameters = flash_nrf_get_parameters,
298 	.get_size = flash_nrf_get_size,
299 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
300 	.page_layout = flash_nrf_pages_layout,
301 #endif
302 };
303 
nrf_flash_init(const struct device * dev)304 static int nrf_flash_init(const struct device *dev)
305 {
306 	SYNC_INIT();
307 
308 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
309 	nrf_flash_sync_init();
310 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
311 
312 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
313 	dev_layout.pages_count = nrfx_nvmc_flash_page_count_get();
314 	dev_layout.pages_size = nrfx_nvmc_flash_page_size_get();
315 #endif
316 
317 	return 0;
318 }
319 
320 DEVICE_DT_INST_DEFINE(0, nrf_flash_init, NULL,
321 		 NULL, NULL,
322 		 POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
323 		 &flash_nrf_api);
324 
325 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
326 
erase_synchronously(uint32_t addr,uint32_t size)327 static int erase_synchronously(uint32_t addr, uint32_t size)
328 {
329 	struct flash_context context = {
330 		.flash_addr = addr,
331 		.len = size,
332 		.enable_time_limit = 1, /* enable time limit */
333 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE)
334 		.flash_addr_next = addr
335 #endif
336 	};
337 
338 	struct flash_op_desc flash_op_desc = {
339 		.handler = erase_op,
340 		.context = &context
341 	};
342 
343 	nrf_flash_sync_set_context(FLASH_SLOT_ERASE);
344 	return nrf_flash_sync_exe(&flash_op_desc);
345 }
346 
write_synchronously(off_t addr,const void * data,size_t len)347 static int write_synchronously(off_t addr, const void *data, size_t len)
348 {
349 	struct flash_context context = {
350 		.data_addr = (uint32_t) data,
351 		.flash_addr = addr,
352 		.len = len,
353 		.enable_time_limit = 1 /* enable time limit */
354 	};
355 
356 	struct flash_op_desc flash_op_desc = {
357 		.handler = write_op,
358 		.context = &context
359 	};
360 
361 	nrf_flash_sync_set_context(FLASH_SLOT_WRITE);
362 	return nrf_flash_sync_exe(&flash_op_desc);
363 }
364 
365 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
366 
erase_op(void * context)367 static int erase_op(void *context)
368 {
369 	uint32_t pg_size = nrfx_nvmc_flash_page_size_get();
370 	struct flash_context *e_ctx = context;
371 
372 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
373 	uint32_t i = 0U;
374 
375 	if (e_ctx->enable_time_limit) {
376 		nrf_flash_sync_get_timestamp_begin();
377 	}
378 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
379 
380 #ifdef CONFIG_SOC_FLASH_NRF_UICR
381 	if (e_ctx->flash_addr == (off_t)NRF_UICR) {
382 		if (SUSPEND_POFWARN()) {
383 			return -ECANCELED;
384 		}
385 
386 		(void)nrfx_nvmc_uicr_erase();
387 		RESUME_POFWARN();
388 		return FLASH_OP_DONE;
389 	}
390 #endif
391 
392 	do {
393 		if (SUSPEND_POFWARN()) {
394 			return -ECANCELED;
395 		}
396 
397 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE)
398 		if (e_ctx->flash_addr == e_ctx->flash_addr_next) {
399 			nrfx_nvmc_page_partial_erase_init(e_ctx->flash_addr,
400 				CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE_MS);
401 			e_ctx->flash_addr_next += pg_size;
402 		}
403 
404 		if (nrfx_nvmc_page_partial_erase_continue()) {
405 			e_ctx->len -= pg_size;
406 			e_ctx->flash_addr += pg_size;
407 		}
408 #else
409 		(void)nrfx_nvmc_page_erase(e_ctx->flash_addr);
410 		e_ctx->len -= pg_size;
411 		e_ctx->flash_addr += pg_size;
412 #endif /* CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE */
413 
414 		RESUME_POFWARN();
415 
416 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
417 		i++;
418 
419 		if (e_ctx->enable_time_limit) {
420 			if (nrf_flash_sync_check_time_limit(i)) {
421 				break;
422 			}
423 
424 		}
425 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
426 
427 	} while (e_ctx->len > 0);
428 
429 	return (e_ctx->len > 0) ? FLASH_OP_ONGOING : FLASH_OP_DONE;
430 }
431 
shift_write_context(uint32_t shift,struct flash_context * w_ctx)432 static void shift_write_context(uint32_t shift, struct flash_context *w_ctx)
433 {
434 	w_ctx->flash_addr += shift;
435 	w_ctx->data_addr += shift;
436 	w_ctx->len -= shift;
437 }
438 
write_op(void * context)439 static int write_op(void *context)
440 {
441 	struct flash_context *w_ctx = context;
442 
443 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
444 	uint32_t i = 1U;
445 
446 	if (w_ctx->enable_time_limit) {
447 		nrf_flash_sync_get_timestamp_begin();
448 	}
449 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
450 #if defined(CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS)
451 	/* If not aligned, write unaligned beginning */
452 	if (!is_aligned_32(w_ctx->flash_addr)) {
453 		uint32_t count = sizeof(uint32_t) - (w_ctx->flash_addr & 0x3);
454 
455 		if (count > w_ctx->len) {
456 			count = w_ctx->len;
457 		}
458 
459 		if (SUSPEND_POFWARN()) {
460 			return -ECANCELED;
461 		}
462 
463 		nrfx_nvmc_bytes_write(w_ctx->flash_addr,
464 				      (const void *)w_ctx->data_addr,
465 				      count);
466 
467 		RESUME_POFWARN();
468 		shift_write_context(count, w_ctx);
469 
470 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
471 		if (w_ctx->enable_time_limit) {
472 			if (nrf_flash_sync_check_time_limit(1)) {
473 				nvmc_wait_ready();
474 				return FLASH_OP_ONGOING;
475 			}
476 		}
477 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
478 	}
479 #endif /* CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS */
480 	/* Write all the 4-byte aligned data */
481 	while (w_ctx->len >= sizeof(uint32_t)) {
482 		if (SUSPEND_POFWARN()) {
483 			return -ECANCELED;
484 		}
485 
486 		nrfx_nvmc_word_write(w_ctx->flash_addr,
487 				     UNALIGNED_GET((uint32_t *)w_ctx->data_addr));
488 		RESUME_POFWARN();
489 		shift_write_context(sizeof(uint32_t), w_ctx);
490 
491 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
492 		i++;
493 
494 		if (w_ctx->enable_time_limit) {
495 			if (nrf_flash_sync_check_time_limit(i)) {
496 				nvmc_wait_ready();
497 				return FLASH_OP_ONGOING;
498 			}
499 		}
500 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
501 	}
502 #if defined(CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS)
503 	/* Write remaining unaligned data */
504 	if (w_ctx->len) {
505 		if (SUSPEND_POFWARN()) {
506 			return -ECANCELED;
507 		}
508 
509 		nrfx_nvmc_bytes_write(w_ctx->flash_addr,
510 				      (const void *)w_ctx->data_addr,
511 				      w_ctx->len);
512 		RESUME_POFWARN();
513 		shift_write_context(w_ctx->len, w_ctx);
514 	}
515 #endif /* CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS */
516 	nvmc_wait_ready();
517 
518 	return FLASH_OP_DONE;
519 }
520 
erase(uint32_t addr,uint32_t size)521 static int erase(uint32_t addr, uint32_t size)
522 {
523 	struct flash_context context = {
524 		.flash_addr = addr,
525 		.len = size,
526 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
527 		.enable_time_limit = 0, /* disable time limit */
528 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
529 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE)
530 		.flash_addr_next = addr
531 #endif
532 	};
533 
534 	return	erase_op(&context);
535 }
536 
write(off_t addr,const void * data,size_t len)537 static int write(off_t addr, const void *data, size_t len)
538 {
539 	struct flash_context context = {
540 		.data_addr = (uint32_t) data,
541 		.flash_addr = addr,
542 		.len = len,
543 #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
544 		.enable_time_limit = 0 /* disable time limit */
545 #endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
546 	};
547 
548 	return write_op(&context);
549 }
550 
551 #if NRF52_ERRATA_242_PRESENT
552 /* Disable POFWARN by writing POFCON before a write or erase operation.
553  * Do not attempt to write or erase if EVENTS_POFWARN is already asserted.
554  */
555 static bool pofcon_enabled;
556 
suspend_pofwarn(void)557 static int suspend_pofwarn(void)
558 {
559 	if (!nrf52_errata_242()) {
560 		return 0;
561 	}
562 
563 	bool enabled;
564 	nrf_power_pof_thr_t pof_thr;
565 
566 	pof_thr = nrf_power_pofcon_get(NRF_POWER, &enabled);
567 
568 	if (enabled) {
569 		nrf_power_pofcon_set(NRF_POWER, false, pof_thr);
570 
571 		/* This check need to be reworked once POFWARN event will be
572 		 * served by zephyr.
573 		 */
574 		if (nrf_power_event_check(NRF_POWER, NRF_POWER_EVENT_POFWARN)) {
575 			nrf_power_pofcon_set(NRF_POWER, true, pof_thr);
576 			return -ECANCELED;
577 		}
578 
579 		pofcon_enabled = enabled;
580 	}
581 
582 	return 0;
583 }
584 
restore_pofwarn(void)585 static void restore_pofwarn(void)
586 {
587 	nrf_power_pof_thr_t pof_thr;
588 
589 	if (pofcon_enabled) {
590 		pof_thr = nrf_power_pofcon_get(NRF_POWER, NULL);
591 
592 		nrf_power_pofcon_set(NRF_POWER, true, pof_thr);
593 		pofcon_enabled = false;
594 	}
595 }
596 #endif  /* NRF52_ERRATA_242_PRESENT */
597