1 /*
2 * Copyright (c) 2023 - 2025, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_RRAMC_ENABLED)
37
38 #include <nrfx_rramc.h>
39 #include <hal/nrf_ficr.h>
40
41 #define NRFX_LOG_MODULE RRAMC
42 #include <nrfx_log.h>
43
44 // Control block - driver instance local data.
45 typedef struct
46 {
47 nrfx_rramc_evt_handler_t handler;
48 nrfx_drv_state_t state;
49 } rramc_control_block_t;
50 static rramc_control_block_t m_cb;
51
rram_variant_get(NRF_FICR_Type const * p_reg)52 NRFX_STATIC_INLINE uint32_t rram_variant_get(NRF_FICR_Type const * p_reg)
53 {
54 return p_reg->INFO.RRAM;
55 }
56
total_memory_size_get(void)57 NRFX_STATIC_INLINE uint32_t total_memory_size_get(void)
58 {
59 uint32_t size = rram_variant_get(NRF_FICR);
60
61 if (size == FICR_INFO_RRAM_RRAM_Unspecified)
62 {
63 return (uint32_t)FICR_INFO_RRAM_RRAM_Unspecified;
64 }
65
66 return (size * 1024UL);
67 }
68
is_valid_address(uint32_t addr,bool uicr_allowed)69 NRFX_STATIC_INLINE bool is_valid_address(uint32_t addr, bool uicr_allowed)
70 {
71 if ((addr - NRFY_RRAMC_RRAM_BASE_ADDRESS) < total_memory_size_get())
72 {
73 return true;
74 }
75 #if !defined(NRF_TRUSTZONE_NONSECURE)
76 if (uicr_allowed && (addr - (uint32_t)NRF_UICR) < sizeof(NRF_UICR_Type))
77 {
78 return true;
79 }
80 #else
81 (void)uicr_allowed;
82 #endif
83
84 return false;
85 }
86
fit_in_memory(uint32_t addr,bool uicr_allowed,uint32_t bytes)87 NRFX_STATIC_INLINE bool fit_in_memory(uint32_t addr, bool uicr_allowed, uint32_t bytes)
88 {
89 if ((addr - NRFY_RRAMC_RRAM_BASE_ADDRESS + bytes) < total_memory_size_get())
90 {
91 return true;
92 }
93 #if !defined(NRF_TRUSTZONE_NONSECURE)
94 if (uicr_allowed && (addr - (uint32_t)NRF_UICR + bytes) < sizeof(NRF_UICR_Type))
95 {
96 return true;
97 }
98 #else
99 (void)uicr_allowed;
100 #endif
101
102 return false;
103 }
104
nrfx_rramc_all_erase(void)105 void nrfx_rramc_all_erase(void)
106 {
107 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
108
109 nrfy_rramc_erase_all_set(NRF_RRAMC);
110 while (!nrfy_rramc_erase_all_check(NRF_RRAMC))
111 {}
112 }
113
nrfx_rramc_byte_write(uint32_t address,uint8_t value)114 void nrfx_rramc_byte_write(uint32_t address, uint8_t value)
115 {
116 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
117 NRFX_ASSERT(is_valid_address(address, true));
118 NRFX_ASSERT(fit_in_memory(address, true, 1));
119
120 nrfy_rramc_byte_write(NRF_RRAMC, address, value);
121 }
122
nrfx_rramc_bytes_write(uint32_t address,void const * src,uint32_t num_bytes)123 void nrfx_rramc_bytes_write(uint32_t address, void const * src, uint32_t num_bytes)
124 {
125 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
126 NRFX_ASSERT(src);
127 NRFX_ASSERT(is_valid_address(address, true));
128 NRFX_ASSERT(fit_in_memory(address, true, num_bytes));
129
130 nrfy_rramc_bytes_write(NRF_RRAMC, address, src, num_bytes);
131 }
132
nrfx_rramc_word_write(uint32_t address,uint32_t value)133 void nrfx_rramc_word_write(uint32_t address, uint32_t value)
134 {
135 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
136 NRFX_ASSERT(is_valid_address(address, true));
137 NRFX_ASSERT(fit_in_memory(address, true, NRFY_RRAMC_BYTES_IN_WORD));
138 NRFX_ASSERT(nrfx_is_word_aligned((void const *)address));
139
140 nrfy_rramc_word_write(NRF_RRAMC, address, value);
141 }
142
nrfx_rramc_words_write(uint32_t address,void const * src,uint32_t num_words)143 void nrfx_rramc_words_write(uint32_t address, void const * src, uint32_t num_words)
144 {
145 NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
146 NRFX_ASSERT(src);
147 NRFX_ASSERT(is_valid_address(address, true));
148 NRFX_ASSERT(fit_in_memory(address, true, (num_words * NRFY_RRAMC_BYTES_IN_WORD)));
149 NRFX_ASSERT(nrfx_is_word_aligned((void const *)address));
150 NRFX_ASSERT(nrfx_is_word_aligned(src));
151
152 nrfy_rramc_words_write(NRF_RRAMC, address, src, num_words);
153 }
154
nrfx_rramc_write_enable_set(bool enable,uint32_t write_buff_size)155 void nrfx_rramc_write_enable_set(bool enable, uint32_t write_buff_size)
156 {
157 nrf_rramc_config_t rramc_config = {
158 .mode_write = enable,
159 .write_buff_size = (uint8_t)write_buff_size,
160 };
161 nrfy_rramc_config_set(NRF_RRAMC, &rramc_config);
162 }
163
nrfx_rramc_write_enable_check(void)164 bool nrfx_rramc_write_enable_check(void)
165 {
166 nrf_rramc_config_t rramc_config;
167 nrfy_rramc_config_get(NRF_RRAMC, &rramc_config);
168
169 return (rramc_config.mode_write == true);
170 }
171
rramc_configure(nrfx_rramc_config_t const * p_config)172 static nrfx_err_t rramc_configure(nrfx_rramc_config_t const * p_config)
173 {
174 nrfy_rramc_config_t nrfy_config =
175 {
176 .config = {
177 .mode_write = p_config->mode_write,
178 .write_buff_size = p_config->write_buff_size,
179 },
180 .preload_timeout = {
181 .value = p_config->preload_timeout,
182 .enable = p_config->preload_timeout_enable,
183 },
184 .power = {
185 .access_timeout = p_config->access_timeout,
186 .abort_on_pof = p_config->abort_on_pof,
187 },
188 };
189 nrfy_rramc_configure(NRF_RRAMC, &nrfy_config);
190
191 if (m_cb.handler)
192 {
193 nrfy_rramc_int_init(NRF_RRAMC, NRF_RRAMC_ALL_INTS_MASK, p_config->irq_priority, false);
194 }
195 return NRFX_SUCCESS;
196 }
197
nrfx_rramc_init(nrfx_rramc_config_t const * p_config,nrfx_rramc_evt_handler_t handler)198 nrfx_err_t nrfx_rramc_init(nrfx_rramc_config_t const * p_config,
199 nrfx_rramc_evt_handler_t handler)
200 {
201 NRFX_ASSERT(p_config);
202
203 nrfx_err_t err_code = NRFX_SUCCESS;
204
205 if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
206 {
207 err_code = NRFX_ERROR_ALREADY;
208 NRFX_LOG_WARNING("Function: %s, error code: %s.",
209 __func__,
210 NRFX_LOG_ERROR_STRING_GET(err_code));
211 return err_code;
212 }
213
214 m_cb.handler = handler;
215
216 err_code = rramc_configure(p_config);
217 if (err_code != NRFX_SUCCESS)
218 {
219 return err_code;
220 }
221
222 m_cb.state = NRFX_DRV_STATE_INITIALIZED;
223
224 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
225 return err_code;
226 }
227
nrfx_rramc_reconfigure(nrfx_rramc_config_t const * p_config)228 nrfx_err_t nrfx_rramc_reconfigure(nrfx_rramc_config_t const * p_config)
229 {
230 NRFX_ASSERT(p_config);
231 nrfx_err_t err_code;
232
233 if (m_cb.state == NRFX_DRV_STATE_UNINITIALIZED)
234 {
235 err_code = NRFX_ERROR_INVALID_STATE;
236 NRFX_LOG_WARNING("Function: %s, error code: %s.",
237 __func__,
238 NRFX_LOG_ERROR_STRING_GET(err_code));
239 return err_code;
240 }
241
242 return rramc_configure(p_config);
243 }
244
nrfx_rramc_uninit(void)245 void nrfx_rramc_uninit(void)
246 {
247 NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
248
249 nrfy_rramc_int_uninit(NRF_RRAMC);
250 if (m_cb.handler)
251 {
252 nrfy_rramc_int_disable(NRF_RRAMC, NRF_RRAMC_ALL_INTS_MASK);
253 }
254
255 m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
256 NRFX_LOG_INFO("Uninitialized.");
257 }
258
nrfx_rramc_memory_size_get(void)259 uint32_t nrfx_rramc_memory_size_get(void)
260 {
261 return total_memory_size_get();
262 }
263
nrfx_rramc_irq_handler(void)264 void nrfx_rramc_irq_handler(void)
265 {
266 NRFX_ASSERT(m_cb.handler);
267
268 uint32_t evts = nrfy_rramc_events_process(NRF_RRAMC, NRF_RRAMC_ALL_INTS_MASK);
269
270 if (evts & NRF_RRAMC_INT_ERROR_ACCESS_MASK)
271 {
272 NRFX_LOG_DEBUG("Event: NRF_RRAMC_EVENT_ERROR_ACCESS.");
273 m_cb.handler(NRF_RRAMC_EVENT_ERROR_ACCESS);
274 }
275
276 if (evts & NRF_RRAMC_INT_READY_MASK)
277 {
278 NRFX_LOG_DEBUG("Event: NRF_RRAMC_EVENT_READY.");
279 m_cb.handler(NRF_RRAMC_EVENT_READY);
280 }
281
282 if (evts & NRF_RRAMC_INT_READY_NEXT_MASK)
283 {
284 NRFX_LOG_DEBUG("Event: NRF_RRAMC_EVENT_READY_NEXT.");
285 m_cb.handler(NRF_RRAMC_EVENT_READY_NEXT);
286 }
287
288 if (evts & NRF_RRAMC_INT_WOKENUP_MASK)
289 {
290 NRFX_LOG_DEBUG("Event: NRF_RRAMC_EVENT_WOKENUP.");
291 m_cb.handler(NRF_RRAMC_EVENT_WOKENUP);
292 }
293 }
294
295 #endif // NRFX_CHECK(NRFX_RRAMC_ENABLED)
296