1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  */
7 
8 #include "nrfx.h"
9 #if defined(NRF52833_XXAA)
10 #include "hal/nrf_ccm.h"
11 #include "hal/nrf_rtc.h"
12 #include "hal/nrf_gpio.h"
13 #include "hal/nrf_gpiote.h"
14 #include "hal/nrf_temp.h"
15 #include "hal/nrf_radio.h"
16 #include "hal/nrf_egu.h"
17 #include "hal/nrf_timer.h"
18 #include "hal/nrf_clock.h"
19 #include "hal/nrf_rng.h"
20 #include "hal/nrf_aar.h"
21 #include "hal/nrf_ppi.h"
22 #include "hal/nrf_ecb.h"
23 #include "hal/nrf_uart.h"
24 #include "hal/nrf_uarte.h"
25 #elif defined(NRF5340_XXAA_NETWORK)
26 #include "hal/nrf_aar.h"
27 #include "hal/nrf_ccm.h"
28 #include "hal/nrf_ecb.h"
29 #include "hal/nrf_ipc.h"
30 #include "hal/nrf_radio.h"
31 #include "hal/nrf_rng.h"
32 #include "hal/nrf_temp.h"
33 
34 #include "hal/nrf_clock.h"
35 #include "hal/nrf_dppi.h"
36 #include "hal/nrf_egu.h"
37 #include "hal/nrf_gpiote.h"
38 #include "hal/nrf_ipc.h"
39 #include "hal/nrf_rtc.h"
40 #include "hal/nrf_timer.h"
41 #include "hal/nrf_uarte.h"
42 #elif defined(NRF5340_XXAA_APPLICATION)
43 #include "hal/nrf_clock.h"
44 #include "hal/nrf_dppi.h"
45 #include "hal/nrf_egu.h"
46 #include "hal/nrf_gpiote.h"
47 #include "hal/nrf_ipc.h"
48 #include "hal/nrf_rtc.h"
49 #include "hal/nrf_timer.h"
50 #include "hal/nrf_uarte.h"
51 #elif defined(NRF54L15_XXAA)
52 #include "hal/nrf_aar.h"
53 #include "hal/nrf_ccm.h"
54 #include "hal/nrf_clock.h"
55 #include "hal/nrf_ecb.h"
56 #include "hal/nrf_egu.h"
57 #include "hal/nrf_dppi.h"
58 #include "hal/nrf_gpiote.h"
59 #include "hal/nrf_grtc.h"
60 //#include "hal/nrf_pdm.h" //Pending support in real HAL
61 #include "hal/nrf_ppib.h"
62 #include "hal/nrf_pwm.h"
63 #include "hal/nrf_radio.h"
64 #include "hal/nrf_timer.h"
65 #include "hal/nrf_temp.h"
66 #include "hal/nrf_uarte.h"
67 #endif
68 
69 #include "bs_tracing.h"
70 
71 #define PERIPHERAL_REG_BASE(per, nbr, post) \
72     (void*)NRF_##per##nbr##post##_BASE
73 
74 #define IS_PERIPHERAL_REG(p, per, nbr, post) \
75     (p >= PERIPHERAL_REG_BASE(per, nbr, post)) && \
76     ((uintptr_t)p < (uintptr_t)PERIPHERAL_REG_BASE(per, nbr, post) + sizeof(NRF_##per##_Type))
77 
78 typedef void (*subscribe_set_f)(void *, int , uint8_t);
79 typedef void (*subscribe_clear_f)(void *, int);
80 typedef void (*task_trigger_f)(void *, int);
81 
82 /*
83  * Given a peripheral task/event (task_event) value (A value of a nrf_<peri>_task_t or nrf_<peri>_event_t)
84  * return true if it is a task, or false if it is an event
85  */
nrf_hack_is_task(int task_event)86 static bool nrf_hack_is_task(int task_event) {
87   /*
88    * In the NRF peripherals:
89    *  [0x000..0x080) are tasks
90    *  [0x080..0x100) are subscribe registers
91    *  [0x100..0x180) are events
92    *  [0x180..0x200) are publish registers
93    *  Note: For the nrf54 RADIO, each group is twice as big, but tasks are still < 0x100
94    */
95   if (task_event < 0x100) {
96     return true;
97   } else {
98     return false;
99   }
100 }
101 
102 /*
103  * Given a pointer to a task or event register in an unknown peripheral
104  * Get
105  *  **p_reg: A pointer to the register base address
106  *  *set_f/clear_f: pointers to the HAL subscribe set and clear functions that correspond to that peripheral
107  *  *trigger_f: pointer to the HAL task trigger function corresponding to that peripheral
108  * The task/event *offset* corresponding to that subscribe register (input to most nrf HAL functions)
109  */
nrf_hack_get_task_from_ptr(void * task_reg,void ** p_reg,subscribe_set_f * set_f,subscribe_clear_f * clear_f,task_trigger_f * trigger_f,int * task)110 static void nrf_hack_get_task_from_ptr(void *task_reg,
111                                        void **p_reg,
112                                        subscribe_set_f *set_f,
113                                        subscribe_clear_f *clear_f,
114                                        task_trigger_f *trigger_f,
115                                        int *task) {
116 
117 #if defined(DPPI_PRESENT)
118 #define IF_PER(per, nbr, post, lname)                            \
119   if (IS_PERIPHERAL_REG(task_reg, per, nbr, post)) {             \
120     *p_reg = PERIPHERAL_REG_BASE(per, nbr, post);                \
121     *task = (intptr_t)task_reg - (intptr_t)*p_reg;               \
122     *set_f = (subscribe_set_f)nrf_##lname##_subscribe_set;       \
123     *clear_f = (subscribe_clear_f)nrf_##lname##_subscribe_clear; \
124     *trigger_f = (task_trigger_f)nrf_##lname##_task_trigger;\
125     return;
126 #else
127 #define IF_PER(per, nbr, post, lname)                            \
128   if (IS_PERIPHERAL_REG(task_reg, per, nbr, post)) {             \
129     *p_reg = PERIPHERAL_REG_BASE(per, nbr, post);                \
130     *task = (intptr_t)task_reg - (intptr_t)*p_reg;               \
131     *set_f = NULL;                                               \
132     *clear_f = NULL;                                             \
133     *trigger_f = (task_trigger_f)nrf_##lname##_task_trigger;\
134     return;
135 #endif
136 
137 #if defined(NRF52833_XXAA)
138   IF_PER(CLOCK, , , clock)
139   } else IF_PER(RADIO, , , radio)
140   } else IF_PER(UART, 0, , uart)
141   } else IF_PER(UARTE, 0, , uarte)
142   } else IF_PER(UARTE, 1, , uarte)
143   } else IF_PER(RNG, , , rng)
144   } else IF_PER(GPIOTE, , , gpiote)
145   } else IF_PER(TIMER, 0, , timer)
146   } else IF_PER(TIMER, 1, , timer)
147   } else IF_PER(TIMER, 2, , timer)
148   } else IF_PER(TIMER, 3, , timer)
149   } else IF_PER(TIMER, 4, , timer)
150   } else IF_PER(ECB, , , ecb)
151   } else IF_PER(AAR, , , aar)
152   } else IF_PER(CCM, , , ccm)
153   } else IF_PER(PPI, , , ppi)
154   } else IF_PER(EGU, 0, , egu)
155   } else IF_PER(EGU, 1, , egu)
156   } else IF_PER(EGU, 2, , egu)
157   } else IF_PER(EGU, 3, , egu)
158   } else IF_PER(EGU, 4, , egu)
159   } else IF_PER(EGU, 5, , egu)
160   } else IF_PER(RTC, 0, , rtc)
161   } else IF_PER(RTC, 1, , rtc)
162   } else IF_PER(RTC, 2, , rtc)
163   } else IF_PER(TEMP, , , temp)
164   } else {
165     bs_trace_error_time_line("Tried to look for a task register not known to these HW models\n");
166     return; /* unreachable */
167   }
168 #elif defined(NRF5340_XXAA_NETWORK)
169   /*IF_PER(POWER, , _NS, power)
170   } else*/ IF_PER(CLOCK, , _NS, clock)
171   } else IF_PER(RADIO, , _NS, radio)
172   } else IF_PER(RNG, , _NS, rng)
173   } else IF_PER(GPIOTE, , _NS, gpiote)
174   /* 11 WDT */
175   } else IF_PER(TIMER, 0, _NS, timer)
176   } else IF_PER(ECB, , _NS, ecb)
177   } else IF_PER(AAR, , _NS, aar)
178   } else IF_PER(CCM, , _NS, ccm)
179   } else IF_PER(DPPIC, , _NS, dppi)
180   } else IF_PER(TEMP, , _NS, temp)
181   } else IF_PER(RTC, 0, _NS, rtc)
182   } else IF_PER(IPC, , _NS, ipc)
183   } else IF_PER(UARTE, 0, _NS, uarte)
184   } else IF_PER(EGU, 0, _NS, egu)
185   } else IF_PER(RTC, 1, _NS, rtc)
186   } else IF_PER(TIMER, 1, _NS, timer)
187   } else IF_PER(TIMER, 2, _NS, timer)
188   } else {
189     bs_trace_error_time_line("Tried to look for a task register not known to these HW models\n");
190     return; /* unreachable */
191   }
192 #elif defined(NRF5340_XXAA_APPLICATION)
193   /*IF_PER(DCNF, , _NS, dcnf)
194   } else IF_PER(FPU, , _NS, fpu)
195   } else IF_PER(CACHE, , _NS, cache)
196   } else IF_PER(SPU, , _NS, spu)
197   } else IF_PER(OSCILLARTORS, , _NS, oscillators)
198   } else IF_PER(REGULATORS, , _NS, regulators)
199   } else */ IF_PER(CLOCK, , _NS, clock)
200   /*} else IF_PER(POWER, , _NS, power)
201   } else IF_PER(RESET, , _NS, reset)
202   } else IF_PER(CTRLAP, , _NS, ctrlap)
203   } else IF_PER(SPIM, 0, _NS, spi) */
204   } else IF_PER(UARTE, 0, _NS, uarte)
205   /*} else IF_PER(SPIM, 1, _NS, spi)*/
206   } else IF_PER(UARTE, 1, _NS, uarte)
207   /*} else IF_PER(SPIM, 4, _NS, spi)
208   } else IF_PER(SPIM, 2, _NS, spi)*/
209   } else IF_PER(UARTE, 2, _NS, uarte)
210   /*} else IF_PER(SPIM, 3, _NS, spi) */
211   } else IF_PER(UARTE, 3, _NS, uarte)
212   } else IF_PER(GPIOTE, 0, _S, gpiote)
213   /*} else IF_PER(SAADC, , _NS, saadc)*/
214   } else IF_PER(TIMER, 0, _NS, timer)
215   } else IF_PER(TIMER, 1, _NS, timer)
216   } else IF_PER(TIMER, 2, _NS, timer)
217   } else IF_PER(RTC, 0, _NS, rtc)
218   } else IF_PER(RTC, 1, _NS, rtc)
219   } else IF_PER(DPPIC, , _NS, dppi)
220   /*} else IF_PER(WDT0, , _NS, dppi)
221   } else IF_PER(WDT1, , _NS, dppi)
222   } else IF_PER(COMP, , _NS, dppi)*/
223   } else IF_PER(EGU, 0, _NS, egu)
224   } else IF_PER(EGU, 1, _NS, egu)
225   } else IF_PER(EGU, 2, _NS, egu)
226   } else IF_PER(EGU, 3, _NS, egu)
227   } else IF_PER(EGU, 4, _NS, egu)
228   } else IF_PER(EGU, 5, _NS, egu)
229   /*} else IF_PER(PWM0, , _NS, dppi)
230   } else IF_PER(PWM1, , _NS, dppi)
231   } else IF_PER(PWM2, , _NS, dppi)
232   } else IF_PER(PWM3, , _NS, dppi)
233   } else IF_PER(PDM0, , _NS, dppi)
234   } else IF_PER(I2S0, , _NS, dppi)*/
235   } else IF_PER(IPC, , _NS, ipc)
236   /* QSPI, NFCT */
237   } else {
238     bs_trace_error_time_line("Tried to look for a task register not known to these HW models\n");
239     return; /* unreachable */
240   }
241 #elif defined(NRF54L15_XXAA)
242   /*IF_PER(SPU, 00, _S, spu)
243   } else IF_PER(MPC, 00, _S, mpc)
244   } else*/ IF_PER(DPPIC, 00, _S, dppi)
245   //} else IF_PER(PPIB, 00, _S, ppib)
246   //} else IF_PER(KMU, , _S, kmu)
247   } else IF_PER(AAR, 00, _S, aar)
248   } else IF_PER(CCM, 00, _S, ccm)
249   } else IF_PER(ECB, 00, _S, ecb)
250   //} else IF_PER(CRCEN, , _S, cracen)
251   //} else IF_PER(SPIM, 00, _S, spi)
252   } else IF_PER(UARTE, 00, _S, uarte)
253   //} else IF_PER(GLITCHDET, , _S, glitchdet)
254   //} else IF_PER(RRAMC, , _S, rramc)
255   //} else IF_PER(VPR, 00 , _S, vpr)
256   //} else IF_PER(CTRLAP, , _S, ctrlap)
257   } else IF_PER(TIMER, 00, _S, timer)
258   //} else IF_PER(SPU, 10, _S, spu)
259   } else IF_PER(DPPIC, 10, _S, dppi)
260   //} else IF_PER(PPIB, 10, _S, ppib)
261   //} else IF_PER(PPIB, 11, _S, ppib)
262   } else IF_PER(TIMER, 10, _S, timer)
263   } else IF_PER(EGU, 10, _S, egu)
264   } else IF_PER(RADIO, , _S, radio)
265   //} else IF_PER(SPU, 20, _S, spu)
266   } else IF_PER(DPPIC, 20, _S, dppi)
267   //} else IF_PER(PPIB, 20, _S, ppib)
268   //} else IF_PER(PPIB, 21, _S, ppib)
269   //} else IF_PER(PPIB, 22, _S, ppib)
270   //} else IF_PER(SPIM, 20, _S, spi)
271   //} else IF_PER(TWIM, 20, _S, twi)
272   } else IF_PER(UARTE, 20, _S, uarte)
273   //} else IF_PER(SPIM, 21, _S, spi)
274   //} else IF_PER(TWIM, 21, _S, twi)
275   } else IF_PER(UARTE, 21, _S, uarte)
276   //} else IF_PER(SPIM, 22, _S, spi)
277   //} else IF_PER(TWIM, 22, _S, twi)
278   } else IF_PER(UARTE, 22, _S, uarte)
279   } else IF_PER(EGU, 20, _S, egu)
280   } else IF_PER(TIMER, 20, _S, timer)
281   } else IF_PER(TIMER, 21, _S, timer)
282   } else IF_PER(TIMER, 22, _S, timer)
283   } else IF_PER(TIMER, 23, _S, timer)
284   } else IF_PER(TIMER, 24, _S, timer)
285   //} else IF_PER(MEMCONF, , _S, memconf)
286   //} else IF_PER(PDM, 20, _S, pdm)
287   //} else IF_PER(PDM, 21, _S, pdm)
288   //} else IF_PER(PWM, 20, _S, pwm)
289   //} else IF_PER(PWM, 21, _S, pwm)
290   //} else IF_PER(PWM, 22, _S, pwm)
291   //} else IF_PER(SAADC, , _S, saadc)
292   //} else IF_PER(NFCT, , _S, nfct)
293   } else IF_PER(TEMP, , _S, temp)
294   } else IF_PER(GPIOTE, 20, _S, gpiote)
295   //} else IF_PER(TAMPC, , _S, tamp)
296   //} else IF_PER(I2S, 20, _S, i2s)
297   //} else IF_PER(QDEC, 20, _S, qdec)
298   //} else IF_PER(QDEC, 21, _S, qdec)
299   } else IF_PER(GRTC, , _S, grtc)
300   //} else IF_PER(SPU, 30, _S, spu)
301   } else IF_PER(DPPIC, 30, _S, dppi)
302   //} else IF_PER(PPIB, 30, _S, ppib)
303   //} else IF_PER(SPIM, 30, _S, spi)
304   //} else IF_PER(TWIM, 30, _S, twi)
305   } else IF_PER(UARTE, 30, _S, uarte)
306   //} else IF_PER(COMP, , _S, comp)
307   //} else IF_PER(LPCOMP, , _S, lpcomp)
308   //} else IF_PER(WDT, 30, _S, wdt)
309   //} else IF_PER(WDT, 31, _S, wdt)
310   } else IF_PER(GPIOTE, 30, _S, gpiote)
311   } else IF_PER(CLOCK, , _NS, clock)
312   //} else IF_PER(POWER, , _NS, power)
313   //} else IF_PER(RESET, , _NS, reset)
314   //} else IF_PER(OSCILLARTORS, , _NS, oscillators)
315   //} else IF_PER(REGULATORS, , _NS, regulators)
316   } else {
317     bs_trace_error_time_line("Tried to look for a task register not known to these HW models\n");
318     return; /* unreachable */
319   }
320 #endif
321 
322 #undef IF_PER
323 }
324 
325 #if defined(DPPI_PRESENT)
326 /*
327  * Given a *<subscribe>* register (NOT a task register),
328  * set it to be enabled and connected to <channel>, by calling the appropriate
329  * HAL set replacement function.
330  *
331  * This function provides the backend for the NRF_DPPI_ENDPOINT_SETUP HAL macro
332  * for simulation.
333  *
334  * Note: This function also accepts publish registers, but ignores them
335  * (so as to be callable from NRF_DPPI_ENDPOINT_SETUP() without any check)
336  */
337 void nrf_dppi_hack_subscribe_set(void *sub_reg, unsigned int channel)
338 {
339   void *p_reg;
340   int task;
341   subscribe_set_f set_f;
342   subscribe_clear_f clear_f;
343   task_trigger_f task_trigger_f;
344 
345   intptr_t task_reg_pr = (intptr_t)sub_reg - NRF_SUBSCRIBE_PUBLISH_OFFSET((uintptr_t)sub_reg);
346 
347   nrf_hack_get_task_from_ptr((void *)task_reg_pr, &p_reg, &set_f, &clear_f, &task_trigger_f, &task);
348   if (nrf_hack_is_task(task)) {
349     set_f(p_reg, task, channel);
350   }
351 }
352 
353 /*
354  * Given a *<subscribe>* register (NOT a task register),
355  * clear it/set it to be disabled, by calling the appropriate
356  * HAL clear replacement function.
357  *
358  * This function provides the backend for the NRF_DPPI_ENDPOINT_CLEAR HAL macro
359  * for simulation.
360  *
361  * Note: This function also accepts publish registers, but ignores them
362  * (so as to be callable from NRF_DPPI_ENDPOINT_SETUP() without any check)
363  */
364 void nrf_dppi_hack_subscribe_clear(void *sub_reg)
365 {
366   void *p_reg;
367   int task;
368   subscribe_set_f set_f;
369   subscribe_clear_f clear_f;
370   task_trigger_f trigger_f;
371 
372   intptr_t task_reg_pr = (intptr_t)sub_reg - NRF_SUBSCRIBE_PUBLISH_OFFSET((uintptr_t)sub_reg);
373 
374   nrf_hack_get_task_from_ptr((void *)task_reg_pr, &p_reg, &set_f, &clear_f, &trigger_f, &task);
375   if (nrf_hack_is_task(task)) {
376     clear_f(p_reg, task);
377   }
378 }
379 
380 #endif /* DPPI_PRESENT */
381 
382 /*
383  * Given a task register address for an unspecified peripheral,
384  * trigger the corresponding task in the hardware model.
385  */
386 void nrf_hack_trigger_task_address(void *task_reg)
387 {
388   void *p_reg;
389   int task;
390   subscribe_set_f set_f;
391   subscribe_clear_f clear_f;
392   task_trigger_f trigger_f;
393 
394   nrf_hack_get_task_from_ptr(task_reg, &p_reg, &set_f, &clear_f, &trigger_f, &task);
395 
396   if (nrf_hack_is_task(task)) {
397      trigger_f(p_reg, task);
398   }
399 }
400