1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Note that the function prototypes are taken from the NRFx HAL
7 */
8
9 #include "hal/nrf_nvmc.h"
10 #include "bs_tracing.h"
11 #include "bs_utils.h"
12 #include "NHW_NVMC.h"
13 #include <nrfx_glue.h>
14
nvmc_number_from_ptr(NRF_NVMC_Type * p_reg)15 static int nvmc_number_from_ptr(NRF_NVMC_Type * p_reg)
16 {
17 int i = ((intptr_t)p_reg - (intptr_t)NRF_NVMC_regs_p[0]) / sizeof(NRF_NVMC_Type);
18 return i;
19 }
20
nrf_nvmc_page_erase_start(NRF_NVMC_Type * p_reg,uint32_t page_addr)21 void nrf_nvmc_page_erase_start(NRF_NVMC_Type * p_reg, uint32_t page_addr)
22 {
23 int i = nvmc_number_from_ptr(p_reg);
24
25 #if defined(NRF52_SERIES)
26 p_reg->ERASEPAGE = page_addr;
27 nhw_nvmc_regw_sideeffects_ERASEPAGE(i);
28 #elif defined(NRF53_SERIES) || defined(NRF91_SERIES)
29 nhw_nvmc_erase_page(i, page_addr);
30 #endif
31 }
32
33 #if defined(NVMC_ERASEUICR_ERASEUICR_Msk)
nrf_nvmc_uicr_erase_start(NRF_NVMC_Type * p_reg)34 void nrf_nvmc_uicr_erase_start(NRF_NVMC_Type * p_reg)
35 {
36 int i = nvmc_number_from_ptr(p_reg);
37
38 p_reg->ERASEUICR = 1;
39 nhw_nvmc_regw_sideeffects_ERASEUICR(i);
40 }
41 #endif
42
nrf_nvmc_erase_all_start(NRF_NVMC_Type * p_reg)43 void nrf_nvmc_erase_all_start(NRF_NVMC_Type * p_reg)
44 {
45 int i = nvmc_number_from_ptr(p_reg);
46
47 p_reg->ERASEALL = 1;
48 nhw_nvmc_regw_sideeffects_ERASEALL(i);
49 }
50
nrf_nvmc_page_partial_erase_start(NRF_NVMC_Type * p_reg,uint32_t page_addr)51 void nrf_nvmc_page_partial_erase_start(NRF_NVMC_Type * p_reg, uint32_t page_addr)
52 {
53 int i = nvmc_number_from_ptr(p_reg);
54
55 #if defined(NVMC_ERASEPAGEPARTIAL_ERASEPAGEPARTIAL_Msk)
56 p_reg->ERASEPAGEPARTIAL = page_addr;
57 nhw_nvmc_regw_sideeffects_ERASEPAGEPARTIAL(i);
58 #elif defined(NRF53_SERIES) || defined(NRF91_SERIES)
59 nhw_nvmc_erase_page_partial(i, page_addr);
60 #endif
61 }
62
nrf_nvmc_byte_read(uint32_t addr)63 uint8_t nrf_nvmc_byte_read(uint32_t addr)
64 {
65 return nhw_nmvc_read_byte(addr);
66 }
67
nrf_nvmc_halfword_read(uint32_t addr)68 uint16_t nrf_nvmc_halfword_read(uint32_t addr)
69 {
70 return nhw_nmvc_read_halfword(addr);
71 }
72
nrf_nvmc_word_read(uint32_t addr)73 uint32_t nrf_nvmc_word_read(uint32_t addr)
74 {
75 return nhw_nmvc_read_word(addr);
76 }
77
nrf_nvmc_word_write(uint32_t addr,uint32_t value)78 void nrf_nvmc_word_write(uint32_t addr, uint32_t value)
79 {
80 nhw_nmvc_write_word(addr, value);
81 }
82
nrf_nvmc_buffer_read(void * dest,uint32_t addr,size_t n)83 void nrf_nvmc_buffer_read(void *dest, uint32_t addr, size_t n)
84 {
85 nhw_nmvc_read_buffer(dest, addr, n);
86 }
87
88 /*
89 * The nvmc driver uses the HAL ready checks in quite a few places
90 * in busy wait loops. Some of the driver maintainers were
91 * not keen on adding conditionally compiled delays on those
92 * so we hide the delay here.
93 * Under the assumption that the ready_check functions
94 * are used only in such busy wait loops until ready,
95 * we actually wait more or less time depending on the pending
96 * time.
97 */
nrf_nvmc_ready_wait(unsigned int inst)98 static void nrf_nvmc_ready_wait(unsigned int inst)
99 {
100 #if defined(NRFX_DELAY_US) && !defined(NO_NVMC_READY_AUTO_DELAY)
101 bs_time_t wait = nhw_nvmc_time_to_ready(inst) + 1;
102 wait = BS_MAX(BS_MIN(wait,100),1);
103 NRFX_DELAY_US(wait);
104 #endif
105 }
106
nrf_nvmc_ready_check(NRF_NVMC_Type const * p_reg)107 bool nrf_nvmc_ready_check(NRF_NVMC_Type const * p_reg)
108 {
109 bool ready = (bool)(p_reg->READY & NVMC_READY_READY_Msk);
110 if (!ready) {
111 int i = nvmc_number_from_ptr((NRF_NVMC_Type *)p_reg);
112 nrf_nvmc_ready_wait(i);
113 }
114 return ready;
115 }
116
nrf_nvmc_write_ready_check(NRF_NVMC_Type const * p_reg)117 bool nrf_nvmc_write_ready_check(NRF_NVMC_Type const * p_reg)
118 {
119 return nrf_nvmc_ready_check(p_reg);
120 }
121