20
20
#include <nrf/gpd.h>
21
21
#endif
22
22
23
+ #define GPIOTE_PHANDLE (id ) DT_INST_PHANDLE(id, gpiote_instance)
24
+ #define GPIOTE_PROP (idx , prop ) DT_PROP(GPIOTE(idx), prop)
25
+
26
+ #define IS_NO_PORT_INSTANCE (id ) DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ||
27
+ #define IS_FIXED_CH_INSTANCE (id ) DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ||
28
+
29
+ #if DT_INST_FOREACH_STATUS_OKAY (IS_NO_PORT_INSTANCE ) 0
30
+ #define GPIOTE_NO_PORT_EVT_SUPPORT 1
31
+ #endif
32
+
33
+ #if DT_INST_FOREACH_STATUS_OKAY (IS_FIXED_CH_INSTANCE ) 0
34
+ #define GPIOTE_FIXED_CH_SUPPORT 1
35
+ #endif
36
+
37
+ #if defined(GPIOTE_NO_PORT_EVT_SUPPORT ) || defined(GPIOTE_FIXED_CH_SUPPORT )
38
+ #define GPIOTE_FEATURE_FLAG 1
39
+ #define GPIOTE_FLAG_NO_PORT_EVT BIT(0)
40
+ #define GPIOTE_FLAG_FIXED_CHAN BIT(1)
41
+ #endif
42
+
23
43
struct gpio_nrfx_data {
24
44
/* gpio_driver_data needs to be first */
25
45
struct gpio_driver_data common ;
@@ -33,6 +53,9 @@ struct gpio_nrfx_cfg {
33
53
uint32_t edge_sense ;
34
54
uint8_t port_num ;
35
55
nrfx_gpiote_t gpiote ;
56
+ #if defined(GPIOTE_FEATURE_FLAG )
57
+ uint32_t flags ;
58
+ #endif
36
59
#ifdef CONFIG_SOC_NRF54H20_GPD
37
60
uint8_t pad_pd ;
38
61
#endif
@@ -180,6 +203,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
180
203
abs_pin , & input_pin_config );
181
204
if (err != NRFX_SUCCESS ) {
182
205
ret = - EINVAL ;
206
+
183
207
goto end ;
184
208
}
185
209
}
@@ -211,13 +235,21 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
211
235
}
212
236
213
237
if (IS_ENABLED (CONFIG_GPIO_NRFX_INTERRUPT ) && free_ch ) {
238
+ #ifdef GPIOTE_FEATURE_FLAG
239
+ /* Fixed channel was used, no need to free. */
240
+ if (cfg -> flags & GPIOTE_FLAG_FIXED_CHAN ) {
241
+ goto end ;
242
+ }
243
+ #endif
214
244
err = nrfx_gpiote_channel_free (& cfg -> gpiote , ch );
215
245
__ASSERT_NO_MSG (err == NRFX_SUCCESS );
216
246
}
217
247
218
248
end :
219
249
gpio_nrfx_gpd_retain_set (port , BIT (pin ));
220
- return pm_device_runtime_put (port );
250
+ int pm_ret = pm_device_runtime_put (port );
251
+
252
+ return (ret != 0 ) ? ret : pm_ret ;
221
253
}
222
254
223
255
#ifdef CONFIG_GPIO_GET_CONFIG
@@ -393,6 +425,37 @@ static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode,
393
425
NRFX_GPIOTE_TRIGGER_LOTOHI ;
394
426
}
395
427
428
+ static nrfx_err_t chan_alloc (const struct gpio_nrfx_cfg * cfg , gpio_pin_t pin , uint8_t * ch )
429
+ {
430
+ #ifdef GPIOTE_FEATURE_FLAG
431
+ if (cfg -> flags & GPIOTE_FLAG_FIXED_CHAN ) {
432
+ /* Currently fixed channel relation is only present in one instance (GPIOTE0 on
433
+ * cpurad). The rules are following:
434
+ * - GPIOTE0 can only be used with P1 (pins 4-11) and P2 (pins (0-11))
435
+ * - P1: channel => pin - 4, e.g. P1.4 => channel 0, P1.5 => channel 1
436
+ * - P2: channel => pin % 8, e.g. P2.0 => channel 0, P2.8 => channel 0
437
+ */
438
+ nrfx_err_t err = NRFX_SUCCESS ;
439
+
440
+ if (cfg -> port_num == 1 ) {
441
+ if (pin < 4 ) {
442
+ err = NRFX_ERROR_INVALID_PARAM ;
443
+ } else {
444
+ * ch = pin - 4 ;
445
+ }
446
+ } else if (cfg -> port_num == 2 ) {
447
+ * ch = pin & 0x7 ;
448
+ } else {
449
+ err = NRFX_ERROR_INVALID_PARAM ;
450
+ }
451
+
452
+ return err ;
453
+ }
454
+ #endif
455
+
456
+ return nrfx_gpiote_channel_alloc (& cfg -> gpiote , ch );
457
+ }
458
+
396
459
static int gpio_nrfx_pin_interrupt_configure (const struct device * port ,
397
460
gpio_pin_t pin ,
398
461
enum gpio_int_mode mode ,
@@ -428,14 +491,19 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
428
491
(nrf_gpio_pin_dir_get (abs_pin ) == NRF_GPIO_PIN_DIR_INPUT )) {
429
492
err = nrfx_gpiote_channel_get (& cfg -> gpiote , abs_pin , & ch );
430
493
if (err == NRFX_ERROR_INVALID_PARAM ) {
431
- err = nrfx_gpiote_channel_alloc ( & cfg -> gpiote , & ch );
494
+ err = chan_alloc ( cfg , pin , & ch );
432
495
if (err != NRFX_SUCCESS ) {
433
496
return - ENOMEM ;
434
497
}
435
498
}
436
499
437
500
trigger_config .p_in_channel = & ch ;
438
501
} else {
502
+ #ifdef GPIOTE_FEATURE_FLAG
503
+ if (cfg -> flags & GPIOTE_FLAG_NO_PORT_EVT ) {
504
+ return - ENOTSUP ;
505
+ }
506
+ #endif
439
507
/* If edge mode with channel was previously used and we are changing to sense or
440
508
* level triggered, we must free the channel.
441
509
*/
@@ -641,7 +709,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
641
709
#endif
642
710
};
643
711
644
- #define GPIOTE_PHANDLE (id ) DT_INST_PHANDLE(id, gpiote_instance)
645
712
#define GPIOTE_INST (id ) DT_PROP(GPIOTE_PHANDLE(id), instance)
646
713
647
714
#define GPIOTE_INSTANCE (id ) \
@@ -668,30 +735,37 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
668
735
#define PAD_PD (inst )
669
736
#endif
670
737
671
- #define GPIO_NRF_DEVICE (id ) \
672
- GPIOTE_CHECK(id); \
673
- static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
674
- .common = { \
675
- .port_pin_mask = \
676
- GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
677
- }, \
678
- .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
679
- .port_num = DT_INST_PROP(id, port), \
680
- .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
681
- .gpiote = GPIOTE_INSTANCE(id), \
682
- PAD_PD(id) \
683
- }; \
684
- \
685
- static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
686
- \
687
- PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
688
- \
689
- DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
690
- PM_DEVICE_DT_INST_GET(id), \
691
- &gpio_nrfx_p##id##_data, \
692
- &gpio_nrfx_p##id##_cfg, \
693
- PRE_KERNEL_1, \
694
- CONFIG_GPIO_INIT_PRIORITY, \
738
+ #define GPIO_NRF_DEVICE (id ) \
739
+ GPIOTE_CHECK(id); \
740
+ static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
741
+ .common = { \
742
+ .port_pin_mask = \
743
+ GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
744
+ }, \
745
+ .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
746
+ .port_num = DT_INST_PROP(id, port), \
747
+ .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
748
+ .gpiote = GPIOTE_INSTANCE(id), \
749
+ IF_ENABLED(GPIOTE_FEATURE_FLAG, \
750
+ (.flags = \
751
+ (DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \
752
+ GPIOTE_FLAG_NO_PORT_EVT : 0) | \
753
+ (DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ? \
754
+ GPIOTE_FLAG_FIXED_CHAN : 0),) \
755
+ ) \
756
+ PAD_PD(id) \
757
+ }; \
758
+ \
759
+ static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
760
+ \
761
+ PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
762
+ \
763
+ DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
764
+ PM_DEVICE_DT_INST_GET(id), \
765
+ &gpio_nrfx_p##id##_data, \
766
+ &gpio_nrfx_p##id##_cfg, \
767
+ PRE_KERNEL_1, \
768
+ CONFIG_GPIO_INIT_PRIORITY, \
695
769
&gpio_nrfx_drv_api_funcs);
696
770
697
771
DT_INST_FOREACH_STATUS_OKAY (GPIO_NRF_DEVICE )
0 commit comments