99#include <nrfx_gpiote.h>
1010#include <string.h>
1111#include <zephyr/drivers/gpio.h>
12+ #include <zephyr/drivers/gpio/gpio_nrf.h>
1213#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
1314#include <zephyr/irq.h>
1415#include <zephyr/pm/device.h>
4243#define GPIOTE_FLAG_FIXED_CHAN BIT(1)
4344#endif
4445
46+ #define GPIOTE_INST_ENUM (i ) DT_CAT3(NRFX_GPIOTE, i, _INST_IDX)
47+ #define GPIOTE_INST_ENUM_NODE (node_id ) GPIOTE_INST_ENUM(DT_PROP(node_id, instance))
48+
49+ #define GPIOTE_NRFX_INST_DEF (index , reg ) [index] = NRFX_GPIOTE_INSTANCE(reg),
50+ #define GPIOTE_NRFX_INST (node_id ) \
51+ GPIOTE_NRFX_INST_DEF(GPIOTE_INST_ENUM_NODE(node_id), DT_REG_ADDR(node_id))
52+
4553struct gpio_nrfx_data {
4654 /* gpio_driver_data needs to be first */
4755 struct gpio_driver_data common ;
56+ nrfx_gpiote_t * gpiote ;
4857 sys_slist_t callbacks ;
4958};
5059
5160struct gpio_nrfx_cfg {
5261 /* gpio_driver_config needs to be first */
5362 struct gpio_driver_config common ;
63+ void (* irq_connect )(void );
5464 NRF_GPIO_Type * port ;
5565 uint32_t edge_sense ;
5666 uint8_t port_num ;
57- nrfx_gpiote_t gpiote ;
67+ uint8_t gpiote_num ;
5868#if GPIO_HAS_PAD_GROUP
5969 const struct device * pad_group ;
6070#endif
@@ -63,6 +73,19 @@ struct gpio_nrfx_cfg {
6373#endif
6474};
6575
76+ static nrfx_gpiote_t gpiote_nrfx [] = {
77+ DT_FOREACH_STATUS_OKAY (nordic_nrf_gpiote , GPIOTE_NRFX_INST )
78+ };
79+
80+ void * gpio_nrf_gpiote_by_idx_get (uint8_t idx )
81+ {
82+ if (idx >= ARRAY_SIZE (gpiote_nrfx )) {
83+ return NULL ;
84+ }
85+
86+ return & gpiote_nrfx [idx ];
87+ }
88+
6689static inline struct gpio_nrfx_data * get_port_data (const struct device * port )
6790{
6891 return port -> data ;
@@ -73,9 +96,9 @@ static inline const struct gpio_nrfx_cfg *get_port_cfg(const struct device *port
7396 return port -> config ;
7497}
7598
76- static bool has_gpiote (const struct gpio_nrfx_cfg * cfg )
99+ static bool has_gpiote (const struct gpio_nrfx_data * data )
77100{
78- return cfg -> gpiote . p_reg != NULL ;
101+ return data -> gpiote != NULL ;
79102}
80103
81104static nrf_gpio_pin_pull_t get_pull (gpio_flags_t flags )
@@ -93,10 +116,11 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
93116 gpio_flags_t flags )
94117{
95118 int ret = 0 ;
96- nrfx_err_t err = NRFX_SUCCESS ;
119+ int err = 0 ;
97120 uint8_t ch ;
98121 bool free_ch = false;
99122 const struct gpio_nrfx_cfg * cfg = get_port_cfg (port );
123+ struct gpio_nrfx_data * data = get_port_data (port );
100124 nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP (cfg -> port_num , pin );
101125 nrf_gpio_pin_pull_t pull = get_pull (flags );
102126 nrf_gpio_pin_drive_t drive ;
@@ -142,7 +166,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
142166 nrf_gpio_port_out_clear (cfg -> port , BIT (pin ));
143167 }
144168
145- if (!has_gpiote (cfg )) {
169+ if (!has_gpiote (data )) {
146170 nrf_gpio_pin_dir_t dir = (flags & GPIO_OUTPUT )
147171 ? NRF_GPIO_PIN_DIR_OUTPUT
148172 : NRF_GPIO_PIN_DIR_INPUT ;
@@ -159,13 +183,13 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
159183 * to be freed when the pin is reconfigured or disconnected.
160184 */
161185 if (IS_ENABLED (CONFIG_GPIO_NRFX_INTERRUPT )) {
162- err = nrfx_gpiote_channel_get (& cfg -> gpiote , abs_pin , & ch );
163- free_ch = (err == NRFX_SUCCESS );
186+ err = nrfx_gpiote_channel_get (data -> gpiote , abs_pin , & ch );
187+ free_ch = (err == 0 );
164188 }
165189
166190 if ((flags & (GPIO_INPUT | GPIO_OUTPUT )) == GPIO_DISCONNECTED ) {
167191 /* Ignore the error code. The pin may not have been used. */
168- (void )nrfx_gpiote_pin_uninit (& cfg -> gpiote , abs_pin );
192+ (void )nrfx_gpiote_pin_uninit (data -> gpiote , abs_pin );
169193 } else {
170194 /* Remove previously configured trigger when pin is reconfigured. */
171195 if (IS_ENABLED (CONFIG_GPIO_NRFX_INTERRUPT )) {
@@ -176,11 +200,9 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
176200 .p_trigger_config = & trigger_config ,
177201 };
178202
179- err = nrfx_gpiote_input_configure (& cfg -> gpiote ,
203+ err = nrfx_gpiote_input_configure (data -> gpiote ,
180204 abs_pin , & input_pin_config );
181- if (err != NRFX_SUCCESS ) {
182- ret = - EINVAL ;
183-
205+ if (err < 0 ) {
184206 goto end ;
185207 }
186208 }
@@ -194,19 +216,18 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
194216 .pull = pull ,
195217 };
196218
197- err = nrfx_gpiote_output_configure (& cfg -> gpiote ,
219+ err = nrfx_gpiote_output_configure (data -> gpiote ,
198220 abs_pin , & output_config , NULL );
199221 } else {
200222 nrfx_gpiote_input_pin_config_t input_pin_config = {
201223 .p_pull_config = & pull ,
202224 };
203225
204- err = nrfx_gpiote_input_configure (& cfg -> gpiote ,
226+ err = nrfx_gpiote_input_configure (data -> gpiote ,
205227 abs_pin , & input_pin_config );
206228 }
207229
208- if (err != NRFX_SUCCESS ) {
209- ret = - EINVAL ;
230+ if (err < 0 ) {
210231 goto end ;
211232 }
212233 }
@@ -218,8 +239,8 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
218239 goto end ;
219240 }
220241#endif
221- err = nrfx_gpiote_channel_free (& cfg -> gpiote , ch );
222- __ASSERT_NO_MSG (err == NRFX_SUCCESS );
242+ err = nrfx_gpiote_channel_free (data -> gpiote , ch );
243+ __ASSERT_NO_MSG (err == 0 );
223244 }
224245
225246end :
@@ -393,7 +414,7 @@ static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode,
393414 NRFX_GPIOTE_TRIGGER_LOTOHI ;
394415}
395416
396- static nrfx_err_t chan_alloc (const struct gpio_nrfx_cfg * cfg , gpio_pin_t pin , uint8_t * ch )
417+ static int chan_alloc (struct gpio_nrfx_data * data , gpio_pin_t pin , uint8_t * ch )
397418{
398419#ifdef GPIOTE_FEATURE_FLAG
399420 if (cfg -> flags & GPIOTE_FLAG_FIXED_CHAN ) {
@@ -403,25 +424,25 @@ static nrfx_err_t chan_alloc(const struct gpio_nrfx_cfg *cfg, gpio_pin_t pin, ui
403424 * - P1: channel => pin - 4, e.g. P1.4 => channel 0, P1.5 => channel 1
404425 * - P2: channel => pin % 8, e.g. P2.0 => channel 0, P2.8 => channel 0
405426 */
406- nrfx_err_t err = NRFX_SUCCESS ;
427+ int err = 0 ;
407428
408429 if (cfg -> port_num == 1 ) {
409430 if (pin < 4 ) {
410- err = NRFX_ERROR_INVALID_PARAM ;
431+ err = - EINVAL ;
411432 } else {
412433 * ch = pin - 4 ;
413434 }
414435 } else if (cfg -> port_num == 2 ) {
415436 * ch = pin & 0x7 ;
416437 } else {
417- err = NRFX_ERROR_INVALID_PARAM ;
438+ err = - EINVAL ;
418439 }
419440
420441 return err ;
421442 }
422443#endif
423444
424- return nrfx_gpiote_channel_alloc (& cfg -> gpiote , ch );
445+ return nrfx_gpiote_channel_alloc (data -> gpiote , ch );
425446}
426447
427448static int gpio_nrfx_pin_interrupt_configure (const struct device * port ,
@@ -430,16 +451,17 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
430451 enum gpio_int_trig trig )
431452{
432453 const struct gpio_nrfx_cfg * cfg = get_port_cfg (port );
454+ struct gpio_nrfx_data * data = get_port_data (port );
433455 uint32_t abs_pin = NRF_GPIO_PIN_MAP (cfg -> port_num , pin );
434- nrfx_err_t err ;
456+ int err ;
435457 uint8_t ch ;
436458
437- if (!has_gpiote (cfg )) {
459+ if (!has_gpiote (data )) {
438460 return - ENOTSUP ;
439461 }
440462
441463 if (mode == GPIO_INT_MODE_DISABLED ) {
442- nrfx_gpiote_trigger_disable (& cfg -> gpiote , abs_pin );
464+ nrfx_gpiote_trigger_disable (data -> gpiote , abs_pin );
443465
444466 return 0 ;
445467 }
@@ -457,11 +479,11 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
457479 if (!(BIT (pin ) & cfg -> edge_sense ) &&
458480 (mode == GPIO_INT_MODE_EDGE ) &&
459481 (nrf_gpio_pin_dir_get (abs_pin ) == NRF_GPIO_PIN_DIR_INPUT )) {
460- err = nrfx_gpiote_channel_get (& cfg -> gpiote , abs_pin , & ch );
461- if (err == NRFX_ERROR_INVALID_PARAM ) {
462- err = chan_alloc (cfg , pin , & ch );
463- if (err != NRFX_SUCCESS ) {
464- return - ENOMEM ;
482+ err = nrfx_gpiote_channel_get (data -> gpiote , abs_pin , & ch );
483+ if (err == - EINVAL ) {
484+ err = chan_alloc (data , pin , & ch );
485+ if (err < 0 ) {
486+ return err ;
465487 }
466488 }
467489
@@ -475,19 +497,19 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
475497 /* If edge mode with channel was previously used and we are changing to sense or
476498 * level triggered, we must free the channel.
477499 */
478- err = nrfx_gpiote_channel_get (& cfg -> gpiote , abs_pin , & ch );
479- if (err == NRFX_SUCCESS ) {
480- err = nrfx_gpiote_channel_free (& cfg -> gpiote , ch );
481- __ASSERT_NO_MSG (err == NRFX_SUCCESS );
500+ err = nrfx_gpiote_channel_get (data -> gpiote , abs_pin , & ch );
501+ if (err == 0 ) {
502+ err = nrfx_gpiote_channel_free (data -> gpiote , ch );
503+ __ASSERT_NO_MSG (err == 0 );
482504 }
483505 }
484506
485- err = nrfx_gpiote_input_configure (& cfg -> gpiote , abs_pin , & input_pin_config );
486- if (err != NRFX_SUCCESS ) {
487- return - EINVAL ;
507+ err = nrfx_gpiote_input_configure (data -> gpiote , abs_pin , & input_pin_config );
508+ if (err < 0 ) {
509+ return err ;
488510 }
489511
490- nrfx_gpiote_trigger_enable (& cfg -> gpiote , abs_pin , true);
512+ nrfx_gpiote_trigger_enable (data -> gpiote , abs_pin , true);
491513
492514 return 0 ;
493515}
@@ -577,8 +599,8 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin,
577599#endif /* CONFIG_GPIO_NRFX_INTERRUPT */
578600
579601#define GPIOTE_IRQ_HANDLER_CONNECT (node_id ) \
580- IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_isr , \
581- NRFX_CONCAT(nrfx_gpiote_, DT_PROP(node_id, instance), _irq_handler) , 0);
602+ IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_gpiote_irq_handler , \
603+ , 0);
582604
583605static int gpio_nrfx_pm_suspend (const struct device * port )
584606{
@@ -626,24 +648,27 @@ static int gpio_nrfx_pm_hook(const struct device *port, enum pm_device_action ac
626648static int gpio_nrfx_init (const struct device * port )
627649{
628650 const struct gpio_nrfx_cfg * cfg = get_port_cfg (port );
629- nrfx_err_t err ;
651+ struct gpio_nrfx_data * data = get_port_data (port );
652+ int err ;
630653
631- if (!has_gpiote (cfg )) {
654+ data -> gpiote = gpio_nrf_gpiote_by_idx_get (cfg -> gpiote_num );
655+
656+ if (!has_gpiote (data )) {
632657 goto pm_init ;
633658 }
634659
635- if (nrfx_gpiote_init_check (& cfg -> gpiote )) {
660+ if (nrfx_gpiote_init_check (data -> gpiote )) {
636661 goto pm_init ;
637662 }
638663
639- err = nrfx_gpiote_init (& cfg -> gpiote , 0 /*not used*/ );
640- if (err != NRFX_SUCCESS ) {
664+ err = nrfx_gpiote_init (data -> gpiote , 0 /*not used*/ );
665+ if (err != 0 ) {
641666 return - EIO ;
642667 }
643668
644669#ifdef CONFIG_GPIO_NRFX_INTERRUPT
645- nrfx_gpiote_global_callback_set (& cfg -> gpiote , nrfx_gpio_handler , NULL );
646- DT_FOREACH_STATUS_OKAY ( nordic_nrf_gpiote , GPIOTE_IRQ_HANDLER_CONNECT );
670+ nrfx_gpiote_global_callback_set (data -> gpiote , nrfx_gpio_handler , NULL );
671+ get_port_cfg ( port ) -> irq_connect ( );
647672#endif /* CONFIG_GPIO_NRFX_INTERRUPT */
648673
649674pm_init :
@@ -669,42 +694,55 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
669694#endif
670695};
671696
672- #define GPIOTE_INST (id ) DT_PROP(GPIOTE_PHANDLE(id), instance)
673-
674- #define GPIOTE_INSTANCE (id ) \
675- COND_CODE_1(DT_INST_NODE_HAS_PROP(id, gpiote_instance), \
676- (NRFX_GPIOTE_INSTANCE(GPIOTE_INST(id))), \
677- ({ .p_reg = NULL }))
678-
679697/* Device instantiation is done with node labels because 'port_num' is
680698 * the peripheral number by SoC numbering. We therefore cannot use
681699 * DT_INST APIs here without wider changes.
682700 */
683701
702+ #define HAS_GPIOTE (id ) DT_INST_NODE_HAS_PROP(id, gpiote_instance)
703+
684704#define GPIOTE_CHECK (id ) \
685- COND_CODE_1(DT_INST_NODE_HAS_PROP (id, gpiote_instance), \
686- (BUILD_ASSERT(DT_NODE_HAS_STATUS_OKAY(GPIOTE_PHANDLE(id)), \
705+ COND_CODE_1(HAS_GPIOTE (id), \
706+ (BUILD_ASSERT(DT_NODE_HAS_STATUS_OKAY(GPIOTE_PHANDLE(id)), \
687707 "Please enable GPIOTE instance for used GPIO port!")), \
688708 ())
689709
710+ #define GPIOTE_IRQ (id ) \
711+ COND_CODE_1(HAS_GPIOTE(id), \
712+ (static void irq_connect##id(void) \
713+ { \
714+ IRQ_CONNECT(DT_IRQN(GPIOTE_PHANDLE(id)), \
715+ DT_IRQ(GPIOTE_PHANDLE(id), priority), \
716+ nrfx_gpiote_irq_handler, &gpio_nrfx_p##id##_data.gpiote, 0); \
717+ }),())
718+
690719#if GPIO_HAS_PAD_GROUP
691720#define GPIO_NRF_PAD_GROUP_INIT (id ) \
692721 .pad_group = DEVICE_DT_GET(DT_INST_CHILD(id, pad_group)),
693722#else
694723#define GPIO_NRF_PAD_GROUP_INIT (id )
695724#endif
696725
726+ #define GPIOTE_IDX (id ) \
727+ COND_CODE_1(HAS_GPIOTE(id), \
728+ (GPIOTE_INST_ENUM_NODE(GPIOTE_PHANDLE(id))), \
729+ (GPIO_NRF_GPIOTE_IDX_INVALID))
730+
697731#define GPIO_NRF_DEVICE (id ) \
698732 GPIOTE_CHECK(id); \
733+ static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
734+ GPIOTE_IRQ(id) \
699735 static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
700736 .common = { \
701737 .port_pin_mask = \
702738 GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
703739 }, \
740+ .irq_connect = \
741+ COND_CODE_1(HAS_GPIOTE(id), (irq_connect##id), (NULL)), \
704742 .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
705- .port_num = DT_INST_PROP(id, port), \
706743 .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
707- .gpiote = GPIOTE_INSTANCE(id), \
744+ .port_num = DT_INST_PROP(id, port), \
745+ .gpiote_num = GPIOTE_IDX(id), \
708746 GPIO_NRF_PAD_GROUP_INIT(id) \
709747 IF_ENABLED(GPIOTE_FEATURE_FLAG, \
710748 (.flags = \
@@ -715,8 +753,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
715753 ) \
716754 }; \
717755 \
718- static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
719- \
720756 PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
721757 \
722758 DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
0 commit comments