1 /*
2 * Copyright (c) 2021, Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #define DT_DRV_COMPAT nordic_nrf_gpio
7
8 #include <nrfx_gpiote.h>
9 #include <string.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
12 #include <zephyr/irq.h>
13
14 #include <zephyr/drivers/gpio/gpio_utils.h>
15
16 struct gpio_nrfx_data {
17 /* gpio_driver_data needs to be first */
18 struct gpio_driver_data common;
19 sys_slist_t callbacks;
20 };
21
22 struct gpio_nrfx_cfg {
23 /* gpio_driver_config needs to be first */
24 struct gpio_driver_config common;
25 NRF_GPIO_Type *port;
26 uint32_t edge_sense;
27 uint8_t port_num;
28 };
29
get_port_data(const struct device * port)30 static inline struct gpio_nrfx_data *get_port_data(const struct device *port)
31 {
32 return port->data;
33 }
34
get_port_cfg(const struct device * port)35 static inline const struct gpio_nrfx_cfg *get_port_cfg(const struct device *port)
36 {
37 return port->config;
38 }
39
get_drive(gpio_flags_t flags,nrf_gpio_pin_drive_t * drive)40 static int get_drive(gpio_flags_t flags, nrf_gpio_pin_drive_t *drive)
41 {
42 switch (flags & (NRF_GPIO_DRIVE_MSK | GPIO_OPEN_DRAIN)) {
43 case NRF_GPIO_DRIVE_S0S1:
44 *drive = NRF_GPIO_PIN_S0S1;
45 break;
46 case NRF_GPIO_DRIVE_S0H1:
47 *drive = NRF_GPIO_PIN_S0H1;
48 break;
49 case NRF_GPIO_DRIVE_H0S1:
50 *drive = NRF_GPIO_PIN_H0S1;
51 break;
52 case NRF_GPIO_DRIVE_H0H1:
53 *drive = NRF_GPIO_PIN_H0H1;
54 break;
55 case NRF_GPIO_DRIVE_S0 | GPIO_OPEN_DRAIN:
56 *drive = NRF_GPIO_PIN_S0D1;
57 break;
58 case NRF_GPIO_DRIVE_H0 | GPIO_OPEN_DRAIN:
59 *drive = NRF_GPIO_PIN_H0D1;
60 break;
61 case NRF_GPIO_DRIVE_S1 | GPIO_OPEN_SOURCE:
62 *drive = NRF_GPIO_PIN_D0S1;
63 break;
64 case NRF_GPIO_DRIVE_H1 | GPIO_OPEN_SOURCE:
65 *drive = NRF_GPIO_PIN_D0H1;
66 break;
67 default:
68 return -EINVAL;
69 }
70
71 return 0;
72 }
73
get_pull(gpio_flags_t flags)74 static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags)
75 {
76 if (flags & GPIO_PULL_UP) {
77 return NRF_GPIO_PIN_PULLUP;
78 } else if (flags & GPIO_PULL_DOWN) {
79 return NRF_GPIO_PIN_PULLDOWN;
80 }
81
82 return NRF_GPIO_PIN_NOPULL;
83 }
84
gpio_nrfx_pin_configure(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)85 static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
86 gpio_flags_t flags)
87 {
88 nrfx_err_t err = NRFX_SUCCESS;
89 uint8_t ch;
90 bool free_ch = false;
91 const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
92 nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin);
93
94 /* Get the GPIOTE channel associated with this pin, if any. It needs
95 * to be freed when the pin is reconfigured or disconnected.
96 */
97 if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT)) {
98 err = nrfx_gpiote_channel_get(abs_pin, &ch);
99 free_ch = (err == NRFX_SUCCESS);
100 }
101
102 if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) {
103 /* Ignore the error code. The pin may not have been used. */
104 (void)nrfx_gpiote_pin_uninit(abs_pin);
105
106 if (free_ch) {
107 err = nrfx_gpiote_channel_free(ch);
108 __ASSERT_NO_MSG(err == NRFX_SUCCESS);
109 }
110
111 return 0;
112 }
113
114 if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT)) {
115 nrfx_gpiote_trigger_config_t trigger_config = {
116 .trigger = NRFX_GPIOTE_TRIGGER_NONE
117 };
118
119 /* Remove previously configured trigger when pin is reconfigured. */
120 err = nrfx_gpiote_input_configure(abs_pin, NULL, &trigger_config, NULL);
121 if (err != NRFX_SUCCESS) {
122 return -EINVAL;
123 }
124
125 if (free_ch) {
126 err = nrfx_gpiote_channel_free(ch);
127 __ASSERT_NO_MSG(err == NRFX_SUCCESS);
128 }
129 }
130
131 if (flags & GPIO_OUTPUT) {
132 nrf_gpio_pin_drive_t drive;
133 int rv = get_drive(flags, &drive);
134
135 if (rv != 0) {
136 return rv;
137 }
138
139 nrfx_gpiote_output_config_t output_config = {
140 .drive = drive,
141 .input_connect = (flags & GPIO_INPUT) ?
142 NRF_GPIO_PIN_INPUT_CONNECT :
143 NRF_GPIO_PIN_INPUT_DISCONNECT,
144 .pull = get_pull(flags)
145 };
146
147
148 if (flags & GPIO_OUTPUT_INIT_HIGH) {
149 nrf_gpio_port_out_set(cfg->port, BIT(pin));
150 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
151 nrf_gpio_port_out_clear(cfg->port, BIT(pin));
152 }
153
154 err = nrfx_gpiote_output_configure(abs_pin, &output_config, NULL);
155 return (err != NRFX_SUCCESS) ? -EINVAL : 0;
156 }
157
158 nrfx_gpiote_input_config_t input_config = {
159 .pull = get_pull(flags)
160 };
161
162 err = nrfx_gpiote_input_configure(abs_pin, &input_config, NULL, NULL);
163
164 return (err != NRFX_SUCCESS) ? -EINVAL : 0;
165 }
166
gpio_nrfx_port_get_raw(const struct device * port,gpio_port_value_t * value)167 static int gpio_nrfx_port_get_raw(const struct device *port,
168 gpio_port_value_t *value)
169 {
170 NRF_GPIO_Type *reg = get_port_cfg(port)->port;
171
172 *value = nrf_gpio_port_in_read(reg);
173
174 return 0;
175 }
176
gpio_nrfx_port_set_masked_raw(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t value)177 static int gpio_nrfx_port_set_masked_raw(const struct device *port,
178 gpio_port_pins_t mask,
179 gpio_port_value_t value)
180 {
181 NRF_GPIO_Type *reg = get_port_cfg(port)->port;
182
183 const uint32_t set_mask = value & mask;
184 const uint32_t clear_mask = (~set_mask) & mask;
185
186 nrf_gpio_port_out_set(reg, set_mask);
187 nrf_gpio_port_out_clear(reg, clear_mask);
188
189 return 0;
190 }
191
gpio_nrfx_port_set_bits_raw(const struct device * port,gpio_port_pins_t mask)192 static int gpio_nrfx_port_set_bits_raw(const struct device *port,
193 gpio_port_pins_t mask)
194 {
195 NRF_GPIO_Type *reg = get_port_cfg(port)->port;
196
197 nrf_gpio_port_out_set(reg, mask);
198
199 return 0;
200 }
201
gpio_nrfx_port_clear_bits_raw(const struct device * port,gpio_port_pins_t mask)202 static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
203 gpio_port_pins_t mask)
204 {
205 NRF_GPIO_Type *reg = get_port_cfg(port)->port;
206
207 nrf_gpio_port_out_clear(reg, mask);
208
209 return 0;
210 }
211
gpio_nrfx_port_toggle_bits(const struct device * port,gpio_port_pins_t mask)212 static int gpio_nrfx_port_toggle_bits(const struct device *port,
213 gpio_port_pins_t mask)
214 {
215 NRF_GPIO_Type *reg = get_port_cfg(port)->port;
216 const uint32_t value = nrf_gpio_port_out_read(reg) ^ mask;
217 const uint32_t set_mask = value & mask;
218 const uint32_t clear_mask = (~value) & mask;
219
220 nrf_gpio_port_out_set(reg, set_mask);
221 nrf_gpio_port_out_clear(reg, clear_mask);
222
223 return 0;
224 }
225
226 #ifdef CONFIG_GPIO_NRFX_INTERRUPT
get_trigger(enum gpio_int_mode mode,enum gpio_int_trig trig)227 static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode,
228 enum gpio_int_trig trig)
229 {
230 if (mode == GPIO_INT_MODE_LEVEL) {
231 return trig == GPIO_INT_TRIG_LOW ? NRFX_GPIOTE_TRIGGER_LOW :
232 NRFX_GPIOTE_TRIGGER_HIGH;
233 }
234
235 return trig == GPIO_INT_TRIG_BOTH ? NRFX_GPIOTE_TRIGGER_TOGGLE :
236 trig == GPIO_INT_TRIG_LOW ? NRFX_GPIOTE_TRIGGER_HITOLO :
237 NRFX_GPIOTE_TRIGGER_LOTOHI;
238 }
239
gpio_nrfx_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)240 static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
241 gpio_pin_t pin,
242 enum gpio_int_mode mode,
243 enum gpio_int_trig trig)
244 {
245 uint32_t abs_pin = NRF_GPIO_PIN_MAP(get_port_cfg(port)->port_num, pin);
246 nrfx_err_t err;
247 uint8_t ch;
248
249 if (mode == GPIO_INT_MODE_DISABLED) {
250 nrfx_gpiote_trigger_disable(abs_pin);
251
252 return 0;
253 }
254
255 nrfx_gpiote_trigger_config_t trigger_config = {
256 .trigger = get_trigger(mode, trig),
257 };
258
259 /* If edge mode is to be used and pin is not configured to use sense for
260 * edge use IN event.
261 */
262 if (!(BIT(pin) & get_port_cfg(port)->edge_sense) &&
263 (mode == GPIO_INT_MODE_EDGE) &&
264 (nrf_gpio_pin_dir_get(abs_pin) == NRF_GPIO_PIN_DIR_INPUT)) {
265 err = nrfx_gpiote_channel_get(abs_pin, &ch);
266 if (err == NRFX_ERROR_INVALID_PARAM) {
267 err = nrfx_gpiote_channel_alloc(&ch);
268 if (err != NRFX_SUCCESS) {
269 return -ENOMEM;
270 }
271 }
272
273 trigger_config.p_in_channel = &ch;
274 }
275
276 err = nrfx_gpiote_input_configure(abs_pin, NULL, &trigger_config, NULL);
277 if (err != NRFX_SUCCESS) {
278 return -EINVAL;
279 }
280
281 nrfx_gpiote_trigger_enable(abs_pin, true);
282
283 return 0;
284 }
285
gpio_nrfx_manage_callback(const struct device * port,struct gpio_callback * callback,bool set)286 static int gpio_nrfx_manage_callback(const struct device *port,
287 struct gpio_callback *callback,
288 bool set)
289 {
290 return gpio_manage_callback(&get_port_data(port)->callbacks,
291 callback, set);
292 }
293 #endif /* CONFIG_GPIO_NRFX_INTERRUPT */
294
295 #ifdef CONFIG_GPIO_GET_DIRECTION
gpio_nrfx_port_get_direction(const struct device * port,gpio_port_pins_t map,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)296 static int gpio_nrfx_port_get_direction(const struct device *port,
297 gpio_port_pins_t map,
298 gpio_port_pins_t *inputs,
299 gpio_port_pins_t *outputs)
300 {
301 const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
302 NRF_GPIO_Type *reg = cfg->port;
303
304 map &= cfg->common.port_pin_mask;
305
306 if (outputs != NULL) {
307 *outputs = map & nrf_gpio_port_dir_read(cfg->port);
308 }
309
310 if (inputs != NULL) {
311 *inputs = 0;
312 while (map) {
313 uint32_t pin = NRF_CTZ(map);
314 uint32_t pin_cnf = reg->PIN_CNF[pin];
315
316 /* Check if the pin has its input buffer connected. */
317 if (((pin_cnf & GPIO_PIN_CNF_INPUT_Msk) >>
318 GPIO_PIN_CNF_INPUT_Pos) ==
319 GPIO_PIN_CNF_INPUT_Connect) {
320 *inputs |= BIT(pin);
321 }
322
323 map &= ~BIT(pin);
324 }
325 }
326
327 return 0;
328 }
329 #endif /* CONFIG_GPIO_GET_DIRECTION */
330
331 #ifdef CONFIG_GPIO_NRFX_INTERRUPT
332 /* Get port device from port id. */
get_dev(uint32_t port_id)333 static const struct device *get_dev(uint32_t port_id)
334 {
335 const struct device *dev = NULL;
336
337 #define GPIO_NRF_GET_DEV(i) \
338 else if (DT_INST_PROP(i, port) == port_id) { \
339 dev = DEVICE_DT_INST_GET(i); \
340 }
341
342 if (0) {
343 } /* Followed by else if from FOREACH macro. Done to avoid return statement in macro. */
344 DT_INST_FOREACH_STATUS_OKAY(GPIO_NRF_GET_DEV)
345 #undef GPIO_NRF_GET_DEV
346
347 return dev;
348 }
349
nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin,nrfx_gpiote_trigger_t trigger,void * context)350 static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin,
351 nrfx_gpiote_trigger_t trigger,
352 void *context)
353 {
354 uint32_t pin = abs_pin;
355 uint32_t port_id = nrf_gpio_pin_port_number_extract(&pin);
356 const struct device *port = get_dev(port_id);
357
358 /* If given port is handled directly by nrfx driver it might not be enabled in DT. */
359 if (port == NULL) {
360 return;
361 }
362
363 struct gpio_nrfx_data *data = get_port_data(port);
364 sys_slist_t *list = &data->callbacks;
365
366 gpio_fire_callbacks(list, port, BIT(pin));
367 }
368 #endif /* CONFIG_GPIO_NRFX_INTERRUPT */
369
370 #define GPIOTE_NODE DT_INST(0, nordic_nrf_gpiote)
371
gpio_nrfx_init(const struct device * port)372 static int gpio_nrfx_init(const struct device *port)
373 {
374 nrfx_err_t err;
375
376 if (nrfx_gpiote_is_init()) {
377 return 0;
378 }
379
380 err = nrfx_gpiote_init(0/*not used*/);
381 if (err != NRFX_SUCCESS) {
382 return -EIO;
383 }
384
385 #ifdef CONFIG_GPIO_NRFX_INTERRUPT
386 nrfx_gpiote_global_callback_set(nrfx_gpio_handler, NULL);
387
388 IRQ_CONNECT(DT_IRQN(GPIOTE_NODE), DT_IRQ(GPIOTE_NODE, priority),
389 nrfx_isr, nrfx_gpiote_irq_handler, 0);
390 #endif /* CONFIG_GPIO_NRFX_INTERRUPT */
391
392 return 0;
393 }
394
395 static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = {
396 .pin_configure = gpio_nrfx_pin_configure,
397 .port_get_raw = gpio_nrfx_port_get_raw,
398 .port_set_masked_raw = gpio_nrfx_port_set_masked_raw,
399 .port_set_bits_raw = gpio_nrfx_port_set_bits_raw,
400 .port_clear_bits_raw = gpio_nrfx_port_clear_bits_raw,
401 .port_toggle_bits = gpio_nrfx_port_toggle_bits,
402 #ifdef CONFIG_GPIO_NRFX_INTERRUPT
403 .pin_interrupt_configure = gpio_nrfx_pin_interrupt_configure,
404 .manage_callback = gpio_nrfx_manage_callback,
405 #endif
406 #ifdef CONFIG_GPIO_GET_DIRECTION
407 .port_get_direction = gpio_nrfx_port_get_direction,
408 #endif
409 };
410
411 /* Device instantiation is done with node labels because 'port_num' is
412 * the peripheral number by SoC numbering. We therefore cannot use
413 * DT_INST APIs here without wider changes.
414 */
415
416 #define GPIO_NRF_DEVICE(id) \
417 static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
418 .common = { \
419 .port_pin_mask = \
420 GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
421 }, \
422 .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
423 .port_num = DT_INST_PROP(id, port), \
424 .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0) \
425 }; \
426 \
427 static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
428 \
429 DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
430 NULL, \
431 &gpio_nrfx_p##id##_data, \
432 &gpio_nrfx_p##id##_cfg, \
433 PRE_KERNEL_1, \
434 CONFIG_GPIO_INIT_PRIORITY, \
435 &gpio_nrfx_drv_api_funcs);
436
437 DT_INST_FOREACH_STATUS_OKAY(GPIO_NRF_DEVICE)
438