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