1 /*
2  * Copyright (c) 2021 - 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 #ifndef NRFY_GPIOTE_H__
35 #define NRFY_GPIOTE_H__
36 
37 #include <nrfx.h>
38 #include <hal/nrf_gpiote.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 NRFY_STATIC_INLINE void __nrfy_internal_gpiote_event_enabled_clear(NRF_GPIOTE_Type *  p_reg,
45                                                                    uint32_t           mask,
46                                                                    nrf_gpiote_event_t event);
47 
48 NRFY_STATIC_INLINE bool __nrfy_internal_gpiote_event_handle(NRF_GPIOTE_Type *  p_reg,
49                                                             uint32_t           mask,
50                                                             nrf_gpiote_event_t event,
51                                                             uint32_t *         p_evt_mask);
52 
53 NRFY_STATIC_INLINE uint32_t __nrfy_internal_gpiote_events_process(NRF_GPIOTE_Type * p_reg,
54                                                                   uint32_t          mask,
55                                                                   uint32_t          channels_number);
56 
57 /**
58  * @defgroup nrfy_gpiote GPIOTE HALY
59  * @{
60  * @ingroup nrf_gpiote
61  * @brief   Hardware access layer with cache and barrier support for managing the GPIOTE peripheral.
62  */
63 
64 #if NRF_GPIOTE_HAS_LATENCY || defined(__NRFX_DOXYGEN__)
65 /** @refhal{NRF_GPIOTE_HAS_LATENCY} */
66 #define NRFY_GPIOTE_HAS_LATENCY 1
67 #else
68 #define NRFY_GPIOTE_HAS_LATENCY 0
69 #endif
70 
71 /**
72  * @brief Function for initializing the specified GPIOTE interrupts.
73  *
74  * @param[in] p_reg           Pointer to the structure of registers of the peripheral.
75  * @param[in] mask            Mask of interrupts to be initialized.
76  * @param[in] irq_priority    Interrupt priority.
77  * @param[in] enable          True if the interrupts are to be enabled, false otherwise.
78  * @param[in] channels_number Number of channels for specified GPIOTE peripheral.
79  */
nrfy_gpiote_int_init(NRF_GPIOTE_Type * p_reg,uint32_t mask,uint8_t irq_priority,bool enable,uint32_t channels_number)80 NRFY_STATIC_INLINE void nrfy_gpiote_int_init(NRF_GPIOTE_Type * p_reg,
81                                              uint32_t          mask,
82                                              uint8_t           irq_priority,
83                                              bool              enable,
84                                              uint32_t          channels_number)
85 {
86     for (uint32_t i = 0; i < channels_number; i++)
87     {
88         __nrfy_internal_gpiote_event_enabled_clear(p_reg,
89                                                    mask,
90                                                    nrf_gpiote_in_event_get((uint8_t)i));
91     }
92 
93     __nrfy_internal_gpiote_event_enabled_clear(p_reg, mask, NRF_GPIOTE_EVENT_PORT);
94 
95 #if defined(NRF_GPIOTE_IRQn_EXT)
96     IRQn_Type irqn = NRF_GPIOTE_IRQn_EXT;
97 #elif defined(NRF_GPIOTE130)
98     IRQn_Type irqn = GPIOTE130_IRQn;
99 #elif defined(LUMOS_XXAA) && defined(NRF_APPLICATION) && !defined(NRF_TRUSTZONE_NONSECURE)
100     IRQn_Type irqn = (IRQn_Type)(nrfx_get_irq_number(p_reg) + 1);
101 #else
102     IRQn_Type irqn = nrfx_get_irq_number(p_reg);
103 #endif
104     NRFX_IRQ_PRIORITY_SET(irqn, irq_priority);
105     NRFX_IRQ_ENABLE(irqn);
106     if (enable)
107     {
108         nrf_gpiote_int_enable(p_reg, mask);
109     }
110     nrf_barrier_w();
111 }
112 
113 /**
114  * @brief Function for processing the specified GPIOTE events.
115  *
116  * @param[in] p_reg           Pointer to the structure of registers of the peripheral.
117  * @param[in] mask            Mask of events to be processed, created by @ref NRFY_EVENT_TO_INT_BITMASK().
118  * @param[in] channels_number Number of channels for specified GPIOTE peripheral.
119  *
120  * @return Mask of events that were generated and processed.
121  *         To be checked against the result of @ref NRFY_EVENT_TO_INT_BITMASK().
122  */
nrfy_gpiote_events_process(NRF_GPIOTE_Type * p_reg,uint32_t mask,uint32_t channels_number)123 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_events_process(NRF_GPIOTE_Type * p_reg,
124                                                        uint32_t          mask,
125                                                        uint32_t          channels_number)
126 {
127     uint32_t evt_mask = __nrfy_internal_gpiote_events_process(p_reg, mask, channels_number);
128     nrf_barrier_w();
129     return evt_mask;
130 }
131 
132 /** @refhal{nrf_gpiote_task_trigger} */
nrfy_gpiote_task_trigger(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task)133 NRFY_STATIC_INLINE void nrfy_gpiote_task_trigger(NRF_GPIOTE_Type * p_reg, nrf_gpiote_task_t task)
134 {
135     nrf_gpiote_task_trigger(p_reg, task);
136     nrf_barrier_w();
137 }
138 
139 /** @refhal{nrf_gpiote_task_address_get} */
nrfy_gpiote_task_address_get(NRF_GPIOTE_Type const * p_reg,nrf_gpiote_task_t task)140 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_task_address_get(NRF_GPIOTE_Type const * p_reg,
141                                                          nrf_gpiote_task_t       task)
142 {
143     return nrf_gpiote_task_address_get(p_reg, task);
144 }
145 
146 /** @refhal{nrf_gpiote_event_check} */
nrfy_gpiote_event_check(NRF_GPIOTE_Type const * p_reg,nrf_gpiote_event_t event)147 NRFY_STATIC_INLINE bool nrfy_gpiote_event_check(NRF_GPIOTE_Type const * p_reg,
148                                                 nrf_gpiote_event_t      event)
149 {
150     nrf_barrier_r();
151     bool evt = nrf_gpiote_event_check(p_reg, event);
152     nrf_barrier_r();
153     return evt;
154 }
155 
156 /** @refhal{nrf_gpiote_event_clear} */
nrfy_gpiote_event_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_event_t event)157 NRFY_STATIC_INLINE void nrfy_gpiote_event_clear(NRF_GPIOTE_Type * p_reg, nrf_gpiote_event_t event)
158 {
159     nrf_gpiote_event_clear(p_reg, event);
160     nrf_barrier_w();
161 }
162 
163 /** @refhal{nrf_gpiote_event_address_get} */
nrfy_gpiote_event_address_get(NRF_GPIOTE_Type const * p_reg,nrf_gpiote_event_t event)164 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_event_address_get(NRF_GPIOTE_Type const * p_reg,
165                                                           nrf_gpiote_event_t      event)
166 {
167     return nrf_gpiote_event_address_get(p_reg, event);
168 }
169 
170 /** @refhal{nrf_gpiote_int_enable} */
nrfy_gpiote_int_enable(NRF_GPIOTE_Type * p_reg,uint32_t mask)171 NRFY_STATIC_INLINE void nrfy_gpiote_int_enable(NRF_GPIOTE_Type * p_reg, uint32_t mask)
172 {
173     nrf_gpiote_int_enable(p_reg, mask);
174     nrf_barrier_w();
175 }
176 
177 /** @refhal{nrf_gpiote_int_disable} */
nrfy_gpiote_int_disable(NRF_GPIOTE_Type * p_reg,uint32_t mask)178 NRFY_STATIC_INLINE void nrfy_gpiote_int_disable(NRF_GPIOTE_Type * p_reg, uint32_t mask)
179 {
180     nrf_gpiote_int_disable(p_reg, mask);
181     nrf_barrier_w();
182 }
183 
184 /** @refhal{nrf_gpiote_int_enable_check} */
nrfy_gpiote_int_enable_check(NRF_GPIOTE_Type const * p_reg,uint32_t mask)185 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_int_enable_check(NRF_GPIOTE_Type const * p_reg,
186                                                          uint32_t                mask)
187 {
188     nrf_barrier_rw();
189     uint32_t enable = nrf_gpiote_int_enable_check(p_reg, mask);
190     nrf_barrier_r();
191     return enable;
192 }
193 
194 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
195 /** @refhal{nrf_gpiote_subscribe_set} */
nrfy_gpiote_subscribe_set(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task,uint8_t channel)196 NRFY_STATIC_INLINE void nrfy_gpiote_subscribe_set(NRF_GPIOTE_Type * p_reg,
197                                                   nrf_gpiote_task_t task,
198                                                   uint8_t           channel)
199 {
200     nrf_gpiote_subscribe_set(p_reg, task, channel);
201     nrf_barrier_w();
202 }
203 
204 /** @refhal{nrf_gpiote_subscribe_clear} */
nrfy_gpiote_subscribe_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task)205 NRFY_STATIC_INLINE void nrfy_gpiote_subscribe_clear(NRF_GPIOTE_Type * p_reg,
206                                                     nrf_gpiote_task_t task)
207 {
208     nrf_gpiote_subscribe_clear(p_reg, task);
209     nrf_barrier_w();
210 }
211 
212 /** @refhal{nrf_gpiote_publish_set} */
nrfy_gpiote_publish_set(NRF_GPIOTE_Type * p_reg,nrf_gpiote_event_t event,uint8_t channel)213 NRFY_STATIC_INLINE void nrfy_gpiote_publish_set(NRF_GPIOTE_Type *  p_reg,
214                                                 nrf_gpiote_event_t event,
215                                                 uint8_t            channel)
216 {
217     nrf_gpiote_publish_set(p_reg, event, channel);
218     nrf_barrier_w();
219 }
220 
221 /** @refhal{nrf_gpiote_publish_clear} */
nrfy_gpiote_publish_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_event_t event)222 NRFY_STATIC_INLINE void nrfy_gpiote_publish_clear(NRF_GPIOTE_Type *  p_reg,
223                                                   nrf_gpiote_event_t event)
224 {
225     nrf_gpiote_publish_clear(p_reg, event);
226     nrf_barrier_w();
227 }
228 #endif
229 
230 /** @refhal{nrf_gpiote_event_enable} */
nrfy_gpiote_event_enable(NRF_GPIOTE_Type * p_reg,uint32_t idx)231 NRFY_STATIC_INLINE void nrfy_gpiote_event_enable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
232 {
233     nrf_gpiote_event_enable(p_reg, idx);
234     nrf_barrier_w();
235 }
236 
237 /** @refhal{nrf_gpiote_event_disable} */
nrfy_gpiote_event_disable(NRF_GPIOTE_Type * p_reg,uint32_t idx)238 NRFY_STATIC_INLINE void nrfy_gpiote_event_disable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
239 {
240     nrf_gpiote_event_disable(p_reg, idx);
241     nrf_barrier_w();
242 }
243 
244 /** @refhal{nrf_gpiote_event_configure} */
nrfy_gpiote_event_configure(NRF_GPIOTE_Type * p_reg,uint32_t idx,uint32_t pin,nrf_gpiote_polarity_t polarity)245 NRFY_STATIC_INLINE void nrfy_gpiote_event_configure(NRF_GPIOTE_Type *     p_reg,
246                                                     uint32_t              idx,
247                                                     uint32_t              pin,
248                                                     nrf_gpiote_polarity_t polarity)
249 {
250     nrf_gpiote_event_configure(p_reg, idx, pin, polarity);
251     nrf_barrier_w();
252 }
253 
254 /** @refhal{nrf_gpiote_event_pin_get} */
nrfy_gpiote_event_pin_get(NRF_GPIOTE_Type const * p_reg,uint32_t idx)255 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_event_pin_get(NRF_GPIOTE_Type const * p_reg, uint32_t idx)
256 {
257     nrf_barrier_rw();
258     uint32_t pin = nrf_gpiote_event_pin_get(p_reg, idx);
259     nrf_barrier_r();
260     return pin;
261 }
262 
263 /** @refhal{nrf_gpiote_event_polarity_get} */
264 NRFY_STATIC_INLINE
nrfy_gpiote_event_polarity_get(NRF_GPIOTE_Type const * p_reg,uint32_t idx)265 nrf_gpiote_polarity_t nrfy_gpiote_event_polarity_get(NRF_GPIOTE_Type const * p_reg,
266                                                      uint32_t                idx)
267 {
268     nrf_barrier_rw();
269     nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(p_reg, idx);
270     nrf_barrier_r();
271     return polarity;
272 }
273 
274 /** @refhal{nrf_gpiote_task_enable} */
nrfy_gpiote_task_enable(NRF_GPIOTE_Type * p_reg,uint32_t idx)275 NRFY_STATIC_INLINE void nrfy_gpiote_task_enable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
276 {
277     nrf_gpiote_task_enable(p_reg, idx);
278     nrf_barrier_w();
279 }
280 
281 /** @refhal{nrf_gpiote_task_disable} */
nrfy_gpiote_task_disable(NRF_GPIOTE_Type * p_reg,uint32_t idx)282 NRFY_STATIC_INLINE void nrfy_gpiote_task_disable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
283 {
284     nrf_gpiote_task_disable(p_reg, idx);
285     nrf_barrier_w();
286 }
287 
288 /** @refhal{nrf_gpiote_task_configure} */
nrfy_gpiote_task_configure(NRF_GPIOTE_Type * p_reg,uint32_t idx,uint32_t pin,nrf_gpiote_polarity_t polarity,nrf_gpiote_outinit_t init_val)289 NRFY_STATIC_INLINE void nrfy_gpiote_task_configure(NRF_GPIOTE_Type *     p_reg,
290                                                    uint32_t              idx,
291                                                    uint32_t              pin,
292                                                    nrf_gpiote_polarity_t polarity,
293                                                    nrf_gpiote_outinit_t  init_val)
294 {
295     nrf_gpiote_task_configure(p_reg, idx, pin, polarity, init_val);
296     nrf_barrier_w();
297 }
298 
299 /** @refhal{nrf_gpiote_task_force} */
nrfy_gpiote_task_force(NRF_GPIOTE_Type * p_reg,uint32_t idx,nrf_gpiote_outinit_t init_val)300 NRFY_STATIC_INLINE void nrfy_gpiote_task_force(NRF_GPIOTE_Type *    p_reg,
301                                                uint32_t             idx,
302                                                nrf_gpiote_outinit_t init_val)
303 {
304     nrf_gpiote_task_force(p_reg, idx, init_val);
305     nrf_barrier_w();
306 }
307 
308 /** @refhal{nrf_gpiote_te_default} */
nrfy_gpiote_te_default(NRF_GPIOTE_Type * p_reg,uint32_t idx)309 NRFY_STATIC_INLINE void nrfy_gpiote_te_default(NRF_GPIOTE_Type * p_reg, uint32_t idx)
310 {
311     nrf_gpiote_te_default(p_reg, idx);
312     nrf_barrier_w();
313 }
314 
315 /** @refhal{nrf_gpiote_te_is_enabled} */
nrfy_gpiote_te_is_enabled(NRF_GPIOTE_Type const * p_reg,uint32_t idx)316 NRFY_STATIC_INLINE bool nrfy_gpiote_te_is_enabled(NRF_GPIOTE_Type const * p_reg, uint32_t idx)
317 {
318     nrf_barrier_rw();
319     bool enabled = nrf_gpiote_te_is_enabled(p_reg, idx);
320     nrf_barrier_r();
321     return enabled;
322 }
323 
324 /** @refhal{nrf_gpiote_out_task_get} */
nrfy_gpiote_out_task_get(uint8_t index)325 NRFY_STATIC_INLINE nrf_gpiote_task_t nrfy_gpiote_out_task_get(uint8_t index)
326 {
327     return nrf_gpiote_out_task_get(index);
328 }
329 
330 #if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
331 /** @refhal{nrf_gpiote_set_task_get} */
nrfy_gpiote_set_task_get(uint8_t index)332 NRFY_STATIC_INLINE nrf_gpiote_task_t nrfy_gpiote_set_task_get(uint8_t index)
333 {
334     return nrf_gpiote_set_task_get(index);
335 }
336 #endif
337 
338 #if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
339 /** @refhal{nrf_gpiote_clr_task_get} */
nrfy_gpiote_clr_task_get(uint8_t index)340 NRFY_STATIC_INLINE nrf_gpiote_task_t nrfy_gpiote_clr_task_get(uint8_t index)
341 {
342     return nrf_gpiote_clr_task_get(index);
343 }
344 #endif
345 
346 /** @refhal{nrf_gpiote_in_event_get} */
nrfy_gpiote_in_event_get(uint8_t index)347 NRFY_STATIC_INLINE nrf_gpiote_event_t nrfy_gpiote_in_event_get(uint8_t index)
348 {
349     return nrf_gpiote_in_event_get(index);
350 }
351 
352 #if NRFY_GPIOTE_HAS_LATENCY
353 /** @refhal{nrf_gpiote_latency_set} */
nrfy_gpiote_latency_set(NRF_GPIOTE_Type * p_reg,nrf_gpiote_latency_t latency)354 NRFY_STATIC_INLINE void nrfy_gpiote_latency_set(NRF_GPIOTE_Type *    p_reg,
355                                                 nrf_gpiote_latency_t latency)
356 {
357     nrf_gpiote_latency_set(p_reg, latency);
358     nrf_barrier_w();
359 }
360 
361 /** @refhal{nrf_gpiote_latency_get} */
nrfy_gpiote_latency_get(NRF_GPIOTE_Type const * p_reg)362 NRFY_STATIC_INLINE nrf_gpiote_latency_t nrfy_gpiote_latency_get(NRF_GPIOTE_Type const * p_reg)
363 {
364     nrf_barrier_rw();
365     nrf_gpiote_latency_t latency = nrf_gpiote_latency_get(p_reg);
366     nrf_barrier_r();
367     return latency;
368 }
369 #endif
370 
371 /** @} */
372 
__nrfy_internal_gpiote_event_enabled_clear(NRF_GPIOTE_Type * p_reg,uint32_t mask,nrf_gpiote_event_t event)373 NRFY_STATIC_INLINE void __nrfy_internal_gpiote_event_enabled_clear(NRF_GPIOTE_Type *  p_reg,
374                                                                    uint32_t           mask,
375                                                                    nrf_gpiote_event_t event)
376 {
377     if (mask & NRFY_EVENT_TO_INT_BITMASK(event))
378     {
379         nrf_gpiote_event_clear(p_reg, event);
380     }
381 }
382 
__nrfy_internal_gpiote_event_handle(NRF_GPIOTE_Type * p_reg,uint32_t mask,nrf_gpiote_event_t event,uint32_t * p_evt_mask)383 NRFY_STATIC_INLINE bool __nrfy_internal_gpiote_event_handle(NRF_GPIOTE_Type *  p_reg,
384                                                             uint32_t           mask,
385                                                             nrf_gpiote_event_t event,
386                                                             uint32_t *         p_evt_mask)
387 {
388     if ((mask & NRFY_EVENT_TO_INT_BITMASK(event)) && nrf_gpiote_event_check(p_reg, event))
389     {
390         nrf_gpiote_event_clear(p_reg, event);
391         if (p_evt_mask)
392         {
393             *p_evt_mask |= NRFY_EVENT_TO_INT_BITMASK(event);
394         }
395         return true;
396     }
397     return false;
398 }
399 
__nrfy_internal_gpiote_events_process(NRF_GPIOTE_Type * p_reg,uint32_t mask,uint32_t channels_number)400 NRFY_STATIC_INLINE uint32_t __nrfy_internal_gpiote_events_process(NRF_GPIOTE_Type * p_reg,
401                                                                   uint32_t          mask,
402                                                                   uint32_t          channels_number)
403 {
404     uint32_t event_mask = 0;
405 
406     nrf_barrier_r();
407     for (uint32_t i = 0; i < channels_number; i++)
408     {
409         (void)__nrfy_internal_gpiote_event_handle(p_reg,
410                                                   mask,
411                                                   nrf_gpiote_in_event_get((uint8_t)i),
412                                                   &event_mask);
413     }
414 
415     (void)__nrfy_internal_gpiote_event_handle(p_reg, mask, NRF_GPIOTE_EVENT_PORT, &event_mask);
416 
417     return event_mask;
418 }
419 
420 #ifdef __cplusplus
421 }
422 #endif
423 
424 #endif // NRFY_GPIOTE_H__
425