1 /*
2 * Copyright (c) 2015 - 2023, Nordic Semiconductor ASA
3 *
4 * Modifications to the GPIOTE HAL to use with simulation models
5 *
6 * Code which is not copied from the nRFx HAL is licensed as:
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Most of the code below is taken from the NRFx HAL with minor
10 * modifications. For that code, the original license applies:
11 *
12 * SPDX-License-Identifier: BSD-3-Clause
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright notice, this
18 * list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * 3. Neither the name of the copyright holder nor the names of its
25 * contributors may be used to endorse or promote products derived from this
26 * software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include <stdint.h>
42 #include "NHW_config.h"
43 #include "NRF_GPIOTE.h"
44 #include "hal/nrf_gpiote.h"
45 #include "bs_tracing.h"
46
gpiote_number_from_ptr(NRF_GPIOTE_Type const * p_reg)47 static int gpiote_number_from_ptr(NRF_GPIOTE_Type const * p_reg){
48 int i = ( (int)p_reg - (int)&NRF_GPIOTE_regs[0] ) / sizeof(NRF_GPIOTE_Type);
49 return i;
50 }
51
nrf_gpiote_task_trigger(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task)52 void nrf_gpiote_task_trigger(NRF_GPIOTE_Type * p_reg, nrf_gpiote_task_t task)
53 {
54 uint32_t *reg = (uint32_t *)((uintptr_t)p_reg + task);
55 *(volatile uint32_t *)reg = 0x1UL;
56
57 uint inst = gpiote_number_from_ptr(p_reg);
58
59 if ((reg >= &NRF_GPIOTE_regs[inst].TASKS_OUT[0])
60 && (reg<= &NRF_GPIOTE_regs[inst].TASKS_OUT[NHW_GPIOTE_MAX_CHANNELS])) {
61 nrf_gpiote_regw_sideeffects_TASKS_OUT(inst, reg - &NRF_GPIOTE_regs[inst].TASKS_OUT[0]);
62 } else if ((reg >= &NRF_GPIOTE_regs[inst].TASKS_SET[0])
63 && (reg<= &NRF_GPIOTE_regs[inst].TASKS_SET[NHW_GPIOTE_MAX_CHANNELS])) {
64 nrf_gpiote_regw_sideeffects_TASKS_SET(inst, reg - &NRF_GPIOTE_regs[inst].TASKS_SET[0]);
65 } else if ((reg >= &NRF_GPIOTE_regs[inst].TASKS_CLR[0])
66 && (reg<= &NRF_GPIOTE_regs[inst].TASKS_CLR[NHW_GPIOTE_MAX_CHANNELS])) {
67 nrf_gpiote_regw_sideeffects_TASKS_CLR(inst, reg - &NRF_GPIOTE_regs[inst].TASKS_CLR[0]);
68 } else {
69 bs_trace_error_time_line("%s: Unknown GPIOTE tasks %i\n",task); /* LCOV_EXCL_LINE */
70 }
71 }
72
nrf_gpiote_event_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_event_t event)73 void nrf_gpiote_event_clear(NRF_GPIOTE_Type * p_reg, nrf_gpiote_event_t event)
74 {
75 uint32_t *reg = (uint32_t *)((uintptr_t)p_reg + event);
76 *(volatile uint32_t *)reg = 0;
77
78 uint inst = gpiote_number_from_ptr(p_reg);
79
80 if ((reg >= &NRF_GPIOTE_regs[inst].EVENTS_IN[0])
81 && (reg <= &NRF_GPIOTE_regs[inst].EVENTS_IN[NHW_GPIOTE_MAX_CHANNELS])) {
82 nrf_gpiote_regw_sideeffects_EVENTS_IN(inst, reg - &NRF_GPIOTE_regs[inst].EVENTS_IN[0]);
83 #if !NHW_GPIOTE_IS_54
84 } else if (reg == &NRF_GPIOTE_regs[inst].EVENTS_PORT) {
85 nrf_gpiote_regw_sideeffects_EVENTS_PORT(inst);
86 #else
87 } else if ((reg == &NRF_GPIOTE_regs[inst].EVENTS_PORT[0].NONSECURE)
88 || (reg == &NRF_GPIOTE_regs[inst].EVENTS_PORT[0].SECURE)) {
89 nrf_gpiote_regw_sideeffects_EVENTS_PORT(inst);
90 #endif
91 } else {
92 bs_trace_error_time_line("%s: Unknown GPIOTE event %i\n",event); /* LCOV_EXCL_LINE */
93 }
94 }
95
96 #if defined(GPIOTE_IRQ_GROUP)
97 #define DEFAULT_IRQ_LINE NRF_GPIOTE_IRQ_GROUP
98 #else
99 #define DEFAULT_IRQ_LINE 0
100 #endif
101
nrf_gpiote_int_enable(NRF_GPIOTE_Type * p_reg,uint32_t mask)102 void nrf_gpiote_int_enable(NRF_GPIOTE_Type * p_reg, uint32_t mask)
103 {
104 uint inst = gpiote_number_from_ptr(p_reg);
105 p_reg->NRFX_CONCAT_2(INTENSET, NRF_GPIOTE_IRQ_GROUP) = mask;
106 nrf_gpiote_regw_sideeffects_INTENSET(inst, DEFAULT_IRQ_LINE);
107
108 }
109
nrf_gpiote_int_disable(NRF_GPIOTE_Type * p_reg,uint32_t mask)110 void nrf_gpiote_int_disable(NRF_GPIOTE_Type * p_reg, uint32_t mask)
111 {
112 uint inst = gpiote_number_from_ptr(p_reg);
113 p_reg->NRFX_CONCAT_2(INTENCLR, NRF_GPIOTE_IRQ_GROUP) = mask;
114 nrf_gpiote_regw_sideeffects_INTENCLR(inst, DEFAULT_IRQ_LINE);
115 }
116
nrf_gpiote_event_enable(NRF_GPIOTE_Type * p_reg,uint32_t idx)117 void nrf_gpiote_event_enable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
118 {
119 uint inst = gpiote_number_from_ptr(p_reg);
120 p_reg->CONFIG[idx] |= GPIOTE_CONFIG_MODE_Event;
121 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
122 }
123
nrf_gpiote_event_disable(NRF_GPIOTE_Type * p_reg,uint32_t idx)124 void nrf_gpiote_event_disable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
125 {
126 uint inst = gpiote_number_from_ptr(p_reg);
127 p_reg->CONFIG[idx] &= ~GPIOTE_CONFIG_MODE_Msk;
128 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
129 }
130
131 #if NRF_GPIOTE_HAS_INT_GROUPS
nrf_gpiote_int_group_enable(NRF_GPIOTE_Type * p_reg,uint8_t group_idx,uint32_t mask)132 void nrf_gpiote_int_group_enable(NRF_GPIOTE_Type * p_reg,
133 uint8_t group_idx,
134 uint32_t mask)
135 {
136 switch (group_idx)
137 {
138 case 0:
139 p_reg->INTENSET0 = mask;
140 break;
141 case 1:
142 p_reg->INTENSET1 = mask;
143 break;
144 #if defined(GPIOTE_INTENSET2_IN0_Msk)
145 case 2:
146 p_reg->INTENSET2 = mask;
147 break;
148 #endif
149 #if defined(GPIOTE_INTENSET3_IN0_Msk)
150 case 3:
151 p_reg->INTENSET3 = mask;
152 break;
153 #endif
154 #if defined(GPIOTE_INTENSET4_IN0_Msk)
155 case 4:
156 p_reg->INTENSET4 = mask;
157 break;
158 #endif
159 #if defined(GPIOTE_INTENSET5_IN0_Msk)
160 case 5:
161 p_reg->INTENSET5 = mask;
162 break;
163 #endif
164 #if defined(GPIOTE_INTENSET6_IN0_Msk)
165 case 6:
166 p_reg->INTENSET6 = mask;
167 break;
168 #endif
169 default:
170 NRFX_ASSERT(false);
171 break;
172 }
173 uint inst = gpiote_number_from_ptr(p_reg);
174 nrf_gpiote_regw_sideeffects_INTENSET(inst, group_idx);
175 }
176
nrf_gpiote_int_group_disable(NRF_GPIOTE_Type * p_reg,uint8_t group_idx,uint32_t mask)177 void nrf_gpiote_int_group_disable(NRF_GPIOTE_Type * p_reg,
178 uint8_t group_idx,
179 uint32_t mask)
180 {
181 switch (group_idx)
182 {
183 case 0:
184 p_reg->INTENCLR0 = mask;
185 break;
186 case 1:
187 p_reg->INTENCLR1 = mask;
188 break;
189 #if defined(GPIOTE_INTENCLR2_IN0_Msk)
190 case 2:
191 p_reg->INTENCLR2 = mask;
192 break;
193 #endif
194 #if defined(GPIOTE_INTENCLR3_IN0_Msk)
195 case 3:
196 p_reg->INTENCLR3 = mask;
197 break;
198 #endif
199 #if defined(GPIOTE_INTENCLR4_IN0_Msk)
200 case 4:
201 p_reg->INTENCLR4 = mask;
202 break;
203 #endif
204 #if defined(GPIOTE_INTENCLR5_IN0_Msk)
205 case 5:
206 p_reg->INTENCLR5 = mask;
207 break;
208 #endif
209 #if defined(GPIOTE_INTENCLR6_IN0_Msk)
210 case 6:
211 p_reg->INTENCLR6 = mask;
212 break;
213 #endif
214 default:
215 NRFX_ASSERT(false);
216 break;
217 }
218 uint inst = gpiote_number_from_ptr(p_reg);
219 nrf_gpiote_regw_sideeffects_INTENCLR(inst, group_idx);
220 }
221 #endif
222
nrf_gpiote_event_configure(NRF_GPIOTE_Type * p_reg,uint32_t idx,uint32_t pin,nrf_gpiote_polarity_t polarity)223 void nrf_gpiote_event_configure(NRF_GPIOTE_Type * p_reg,
224 uint32_t idx,
225 uint32_t pin,
226 nrf_gpiote_polarity_t polarity)
227 {
228 uint inst = gpiote_number_from_ptr(p_reg);
229 p_reg->CONFIG[idx] &= ~(GPIOTE_CONFIG_PORT_PIN_Msk | GPIOTE_CONFIG_POLARITY_Msk);
230 p_reg->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk) |
231 ((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk);
232 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
233 }
234
nrf_gpiote_task_enable(NRF_GPIOTE_Type * p_reg,uint32_t idx)235 void nrf_gpiote_task_enable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
236 {
237 uint inst = gpiote_number_from_ptr(p_reg);
238 uint32_t final_config = p_reg->CONFIG[idx] | GPIOTE_CONFIG_MODE_Task;
239 p_reg->CONFIG[idx] = final_config;
240 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
241 }
242
nrf_gpiote_task_disable(NRF_GPIOTE_Type * p_reg,uint32_t idx)243 void nrf_gpiote_task_disable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
244 {
245 uint inst = gpiote_number_from_ptr(p_reg);
246 p_reg->CONFIG[idx] &= ~GPIOTE_CONFIG_MODE_Msk;
247 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
248 }
249
nrf_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)250 void nrf_gpiote_task_configure(NRF_GPIOTE_Type * p_reg,
251 uint32_t idx,
252 uint32_t pin,
253 nrf_gpiote_polarity_t polarity,
254 nrf_gpiote_outinit_t init_val)
255 {
256 uint inst = gpiote_number_from_ptr(p_reg);
257 p_reg->CONFIG[idx] &= ~(GPIOTE_CONFIG_PORT_PIN_Msk |
258 GPIOTE_CONFIG_POLARITY_Msk |
259 GPIOTE_CONFIG_OUTINIT_Msk);
260
261 p_reg->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PORT_PIN_Msk) |
262 ((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk) |
263 ((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk);
264
265 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
266 }
267
nrf_gpiote_task_force(NRF_GPIOTE_Type * p_reg,uint32_t idx,nrf_gpiote_outinit_t init_val)268 void nrf_gpiote_task_force(NRF_GPIOTE_Type * p_reg,
269 uint32_t idx,
270 nrf_gpiote_outinit_t init_val)
271 {
272 uint inst = gpiote_number_from_ptr(p_reg);
273 p_reg->CONFIG[idx] = (p_reg->CONFIG[idx] & ~GPIOTE_CONFIG_OUTINIT_Msk) |
274 ((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk);
275 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
276 }
277
nrf_gpiote_te_default(NRF_GPIOTE_Type * p_reg,uint32_t idx)278 void nrf_gpiote_te_default(NRF_GPIOTE_Type * p_reg, uint32_t idx)
279 {
280 uint inst = gpiote_number_from_ptr(p_reg);
281 p_reg->CONFIG[idx] = 0;
282 #if !defined(NRF51_SERIES) && !defined(NRF52_SERIES)
283 p_reg->CONFIG[idx] = 0;
284 #endif
285 nrf_gpiote_regw_sideeffects_CONFIG(inst, idx);
286 }
287
288 #if defined(DPPI_PRESENT)
nrf_gpiote_subscribe_common(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task)289 static void nrf_gpiote_subscribe_common(NRF_GPIOTE_Type * p_reg,
290 nrf_gpiote_task_t task)
291 {
292 uint inst = gpiote_number_from_ptr(p_reg);
293 int task_nbr;
294
295 if ((task >= NRF_GPIOTE_TASK_OUT_0) && (task < NRF_GPIOTE_TASK_SET_0)) {
296 task_nbr = (task - NRF_GPIOTE_TASK_OUT_0)/sizeof(uint32_t);
297 nhw_gpiote_regw_sideeffects_SUBSCRIBE_OUT(inst, task_nbr);
298 } else if ((task >= NRF_GPIOTE_TASK_SET_0) && (task < NRF_GPIOTE_TASK_CLR_0)) {
299 task_nbr = (task - NRF_GPIOTE_TASK_SET_0)/sizeof(uint32_t);
300 nhw_gpiote_regw_sideeffects_SUBSCRIBE_SET(inst, task_nbr );
301 } else if (task >= NRF_GPIOTE_TASK_CLR_0) {
302 task_nbr = (task - NRF_GPIOTE_TASK_CLR_0)/sizeof(uint32_t);
303 nhw_gpiote_regw_sideeffects_SUBSCRIBE_CLR(inst, task_nbr);
304 } else {
305 bs_trace_error_line_time("Attempted to subscribe to a not-supported task in the nrf_timer (%i)\n",
306 task);
307 }
308 }
309
nrf_gpiote_subscribe_set(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task,uint8_t channel)310 void nrf_gpiote_subscribe_set(NRF_GPIOTE_Type * p_reg,
311 nrf_gpiote_task_t task,
312 uint8_t channel)
313 {
314 *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) =
315 ((uint32_t)channel | NRF_SUBSCRIBE_PUBLISH_ENABLE);
316 nrf_gpiote_subscribe_common(p_reg, task);
317 }
318
nrf_gpiote_subscribe_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task)319 void nrf_gpiote_subscribe_clear(NRF_GPIOTE_Type * p_reg, nrf_gpiote_task_t task)
320 {
321 *((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) = 0;
322 nrf_gpiote_subscribe_common(p_reg, task);
323 }
324 #endif // defined(DPPI_PRESENT)
325