1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * Template code (macros) for the most typical/repetitive
9  * code of the HW models
10  *
11  * The _si versions are for peripheral which can only have one instance
12  */
13 #ifndef _NRF_HW_MODEL_NHW_TEMPLATES_H
14 #define _NRF_HW_MODEL_NHW_TEMPLATES_H
15 
16 #include "NHW_config.h"
17 
18 /*
19  * TASKS register write side-effects
20  * (just calls thru to the task)
21  */
22 #define NHW_SIDEEFFECTS_TASKS_si(peri, task) \
23   void nhw_##peri##_regw_sideeffects_TASKS_##task(void) { \
24     if ( NRF_##peri##_regs.TASKS_##task ) { \
25       NRF_##peri##_regs.TASKS_##task = 0; \
26       nhw_##peri##_TASK_##task(); \
27     } \
28   }
29 
30 #define NHW_SIDEEFFECTS_TASKS(peri, peri_regs, task) \
31   void nhw_##peri##_regw_sideeffects_TASKS_##task(unsigned int inst) { \
32     if ( peri_regs TASKS_##task ) { \
33       peri_regs TASKS_##task = 0; \
34       nhw_##peri##_TASK_##task(inst); \
35     } \
36   }
37 
38 /*
39  * SUBSCRIBE register write side-effects
40  */
41 #define NHW_SIDEEFFECTS_SUBSCRIBE_si(peri, task) \
42   void nhw_##peri##_regw_sideeffects_SUBSCRIBE_##task(unsigned int inst) { \
43     static struct nhw_subsc_mem task##_subscribed[NHW_##peri##_TOTAL_INST]; \
44     nhw_dppi_common_subscribe_sideeffect(nhw_##peri##_dppi_map[inst], \
45         NRF_##peri##_regs.SUBSCRIBE_##task, \
46         &task##_subscribed[inst], \
47         (dppi_callback_t)nhw_##peri##_TASK_##task, \
48         DPPI_CB_NO_PARAM); \
49   }
50 
51 /*
52  * Any EVENT register write side-effect
53  */
54 #define NHW_SIDEEFFECTS_EVENTS(peri) \
55   void nhw_##peri##_regw_sideeffects_EVENTS_all(unsigned int inst) { \
56     nhw_##peri##_eval_interrupt(inst); \
57   }
58 
59 
60 #if (NHW_HAS_PPI)
61   #define _NHW_XPPI_EVENT(peri, peri_regs, inst, event)    \
62     nrf_ppi_event(peri##_EVENTS_##event)
63 #elif (NHW_HAS_DPPI)
64   #define _NHW_XPPI_EVENT(peri, peri_regs, inst, event)    \
65      nhw_dppi_event_signal_if(nhw_##peri##_dppi_map[inst], \
66                               peri_regs PUBLISH_##event)
67 #endif /* (NHW_HAS_PPI) / (NHW_HAS_DPPI)*/
68 
69 
70 #define _NHW_SIGNAL_EVENT_body(peri, peri_regs, event) \
71   { \
72     peri_regs EVENTS_##event = 1; \
73     nhw_##peri##_eval_interrupt(inst); \
74     _NHW_XPPI_EVENT(peri, peri_regs, inst, event); \
75   }
76 
77 /*
78  * Signal an event:
79  *  * Set the corresponding event register
80  *  * Cause level interrupts to be reevaluated
81  *  * Send the event either to the PPI or DPPI (if enabled)
82  *
83  * NOTE: Cannot be used for events with shortcuts
84  * NOTE: Cannot be used for multi-instance peripherals connected to the PPI
85  */
86 #define NHW_SIGNAL_EVENT(peri, peri_regs, event) \
87   void nhw_##peri##_signal_EVENTS_##event(unsigned int inst) \
88     _NHW_SIGNAL_EVENT_body(peri, peri_regs, event)
89 
90 /*
91  * Signal an event. Like NHW_SIGNAL_EVENT()
92  * but when the event has shortcuts.
93  *
94  * NOTE: Cannot be used for multi-instance peripherals connected to the PPI
95  */
96 #define NHW_SIGNAL_EVENT_ns(peri, peri_regs, event) \
97   void nhw_##peri##_signal_EVENTS_##event##_noshort(unsigned int inst) \
98     _NHW_SIGNAL_EVENT_body(peri, peri_regs, event)
99 
100 #define NHW_SIGNAL_EVENT_si(peri, event) \
101     NHW_SIGNAL_EVENT(peri, NRF_##peri##_regs. , event)
102 
103 #define NHW_SIGNAL_EVENT_ns_si(peri, event) \
104     NHW_SIGNAL_EVENT_ns(peri, NRF_##peri##_regs. , event)
105 
106 #define NHW_SIDEEFFECTS_INTSET_si(peri, peri_regs, inten)\
107   void nhw_##peri##_regw_sideeffects_INTENSET(void) { \
108     if ( peri_regs INTENSET ){ /* LCOV_EXCL_BR_LINE */\
109       inten |= peri_regs INTENSET;                    \
110       peri_regs INTENSET = inten;                     \
111       nhw_##peri##_eval_interrupt(0);                \
112     }                                                 \
113   }
114 
115 #define NHW_SIDEEFFECTS_INTCLR_si(peri, peri_regs, inten) \
116   void nhw_##peri##_regw_sideeffects_INTENCLR(void) { \
117     if ( peri_regs INTENCLR ){/* LCOV_EXCL_BR_LINE */ \
118        inten &= ~(peri_regs INTENCLR);                \
119        peri_regs INTENSET = inten;                    \
120        peri_regs INTENCLR = 0;                        \
121        nhw_##peri## _eval_interrupt(0);               \
122     }                                                 \
123   }
124 
125 #define NHW_SIDEEFFECTS_INTSET(peri, peri_regs, inten) \
126   void nhw_##peri##_regw_sideeffects_INTENSET(uint inst) { \
127     if ( peri_regs INTENSET ){ /* LCOV_EXCL_BR_LINE */\
128       inten |= peri_regs INTENSET;                    \
129       peri_regs INTENSET = inten;                     \
130       nhw_##peri##_eval_interrupt(inst);              \
131     }                                                 \
132   }
133 
134 #define NHW_SIDEEFFECTS_INTEN(peri, peri_regs, inten) \
135   void nhw_##peri##_regw_sideeffects_INTEN(uint inst) { \
136     peri_regs INTENSET = inten;                     \
137     nhw_##peri##_eval_interrupt(inst);              \
138   }
139 
140 #define NHW_SIDEEFFECTS_INTCLR(peri, peri_regs, inten) \
141   void nhw_##peri##_regw_sideeffects_INTENCLR(uint inst) { \
142     if ( peri_regs INTENCLR ){/* LCOV_EXCL_BR_LINE */ \
143        inten &= ~(peri_regs INTENCLR);                \
144        peri_regs INTENSET = inten;                    \
145        peri_regs INTENCLR = 0;                        \
146        nhw_##peri## _eval_interrupt(inst);            \
147     }                                                 \
148   }
149 
150 #define NHW_CHECK_INTERRUPT(peri, peri_regs, event, inten) \
151   if (peri_regs EVENTS_##event && (inten &  peri##_INTENSET_##event##_Msk)){ \
152     new_int_line = true; \
153   }
154 
155 #define NHW_CHECK_INTERRUPT_si(peri, event, inten) \
156   if (NRF_##peri##_regs.EVENTS_##event && (inten &  peri##_INTENSET_##event##_Msk)){ \
157     new_int_line = true; \
158   }
159 
160 #define NHW_SHORT_si(peri, event, task) \
161   if (NRF_##peri##_regs.SHORTS & peri##_SHORTS_##event##_##task##_Msk) { \
162     nhw_##peri##_TASK_##task(); \
163   }
164 
165 #define NHW_SHORT(peri, inst, peri_regs, event, task) \
166   if (peri_regs SHORTS & peri##_SHORTS_##event##_##task##_Msk) { \
167     nhw_##peri##_TASK_##task(inst); \
168   }
169 
170 #endif /* _NRF_HW_MODEL_NHW_TEMPLATES_H */
171