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