22
22
#define GPIO_HAS_PAD_GROUP 0
23
23
#endif
24
24
25
+ #define GPIOTE_PHANDLE (id ) DT_INST_PHANDLE(id, gpiote_instance)
26
+ #define GPIOTE_PROP (idx , prop ) DT_PROP(GPIOTE(idx), prop)
27
+
28
+ #define IS_NO_PORT_INSTANCE (id ) DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ||
29
+ #define IS_FIXED_CH_INSTANCE (id ) DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ||
30
+
31
+ #if DT_INST_FOREACH_STATUS_OKAY (IS_NO_PORT_INSTANCE ) 0
32
+ #define GPIOTE_NO_PORT_EVT_SUPPORT 1
33
+ #endif
34
+
35
+ #if DT_INST_FOREACH_STATUS_OKAY (IS_FIXED_CH_INSTANCE ) 0
36
+ #define GPIOTE_FIXED_CH_SUPPORT 1
37
+ #endif
38
+
39
+ #if defined(GPIOTE_NO_PORT_EVT_SUPPORT ) || defined(GPIOTE_FIXED_CH_SUPPORT )
40
+ #define GPIOTE_FEATURE_FLAG 1
41
+ #define GPIOTE_FLAG_NO_PORT_EVT BIT(0)
42
+ #define GPIOTE_FLAG_FIXED_CHAN BIT(1)
43
+ #endif
44
+
25
45
struct gpio_nrfx_data {
26
46
/* gpio_driver_data needs to be first */
27
47
struct gpio_driver_data common ;
@@ -38,6 +58,9 @@ struct gpio_nrfx_cfg {
38
58
#if GPIO_HAS_PAD_GROUP
39
59
const struct device * pad_group ;
40
60
#endif
61
+ #if defined(GPIOTE_FEATURE_FLAG )
62
+ uint32_t flags ;
63
+ #endif
41
64
};
42
65
43
66
static inline struct gpio_nrfx_data * get_port_data (const struct device * port )
@@ -77,6 +100,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
77
100
nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP (cfg -> port_num , pin );
78
101
nrf_gpio_pin_pull_t pull = get_pull (flags );
79
102
nrf_gpio_pin_drive_t drive ;
103
+ int pm_ret ;
80
104
81
105
switch (flags & (NRF_GPIO_DRIVE_MSK | GPIO_OPEN_DRAIN )) {
82
106
case NRF_GPIO_DRIVE_S0S1 :
@@ -156,6 +180,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
156
180
abs_pin , & input_pin_config );
157
181
if (err != NRFX_SUCCESS ) {
158
182
ret = - EINVAL ;
183
+
159
184
goto end ;
160
185
}
161
186
}
@@ -187,12 +212,20 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
187
212
}
188
213
189
214
if (IS_ENABLED (CONFIG_GPIO_NRFX_INTERRUPT ) && free_ch ) {
215
+ #ifdef GPIOTE_FEATURE_FLAG
216
+ /* Fixed channel was used, no need to free. */
217
+ if (cfg -> flags & GPIOTE_FLAG_FIXED_CHAN ) {
218
+ goto end ;
219
+ }
220
+ #endif
190
221
err = nrfx_gpiote_channel_free (& cfg -> gpiote , ch );
191
222
__ASSERT_NO_MSG (err == NRFX_SUCCESS );
192
223
}
193
224
194
225
end :
195
- return pm_device_runtime_put (port );
226
+ pm_ret = pm_device_runtime_put (port );
227
+
228
+ return (ret != 0 ) ? ret : pm_ret ;
196
229
}
197
230
198
231
#ifdef CONFIG_GPIO_GET_CONFIG
@@ -360,6 +393,37 @@ static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode,
360
393
NRFX_GPIOTE_TRIGGER_LOTOHI ;
361
394
}
362
395
396
+ static nrfx_err_t chan_alloc (const struct gpio_nrfx_cfg * cfg , gpio_pin_t pin , uint8_t * ch )
397
+ {
398
+ #ifdef GPIOTE_FEATURE_FLAG
399
+ if (cfg -> flags & GPIOTE_FLAG_FIXED_CHAN ) {
400
+ /* Currently fixed channel relation is only present in one instance (GPIOTE0 on
401
+ * cpurad). The rules are following:
402
+ * - GPIOTE0 can only be used with P1 (pins 4-11) and P2 (pins (0-11))
403
+ * - P1: channel => pin - 4, e.g. P1.4 => channel 0, P1.5 => channel 1
404
+ * - P2: channel => pin % 8, e.g. P2.0 => channel 0, P2.8 => channel 0
405
+ */
406
+ nrfx_err_t err = NRFX_SUCCESS ;
407
+
408
+ if (cfg -> port_num == 1 ) {
409
+ if (pin < 4 ) {
410
+ err = NRFX_ERROR_INVALID_PARAM ;
411
+ } else {
412
+ * ch = pin - 4 ;
413
+ }
414
+ } else if (cfg -> port_num == 2 ) {
415
+ * ch = pin & 0x7 ;
416
+ } else {
417
+ err = NRFX_ERROR_INVALID_PARAM ;
418
+ }
419
+
420
+ return err ;
421
+ }
422
+ #endif
423
+
424
+ return nrfx_gpiote_channel_alloc (& cfg -> gpiote , ch );
425
+ }
426
+
363
427
static int gpio_nrfx_pin_interrupt_configure (const struct device * port ,
364
428
gpio_pin_t pin ,
365
429
enum gpio_int_mode mode ,
@@ -395,14 +459,19 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
395
459
(nrf_gpio_pin_dir_get (abs_pin ) == NRF_GPIO_PIN_DIR_INPUT )) {
396
460
err = nrfx_gpiote_channel_get (& cfg -> gpiote , abs_pin , & ch );
397
461
if (err == NRFX_ERROR_INVALID_PARAM ) {
398
- err = nrfx_gpiote_channel_alloc ( & cfg -> gpiote , & ch );
462
+ err = chan_alloc ( cfg , pin , & ch );
399
463
if (err != NRFX_SUCCESS ) {
400
464
return - ENOMEM ;
401
465
}
402
466
}
403
467
404
468
trigger_config .p_in_channel = & ch ;
405
469
} else {
470
+ #ifdef GPIOTE_FEATURE_FLAG
471
+ if (cfg -> flags & GPIOTE_FLAG_NO_PORT_EVT ) {
472
+ return - ENOTSUP ;
473
+ }
474
+ #endif
406
475
/* If edge mode with channel was previously used and we are changing to sense or
407
476
* level triggered, we must free the channel.
408
477
*/
@@ -600,7 +669,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
600
669
#endif
601
670
};
602
671
603
- #define GPIOTE_PHANDLE (id ) DT_INST_PHANDLE(id, gpiote_instance)
604
672
#define GPIOTE_INST (id ) DT_PROP(GPIOTE_PHANDLE(id), instance)
605
673
606
674
#define GPIOTE_INSTANCE (id ) \
@@ -626,30 +694,37 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
626
694
#define GPIO_NRF_PAD_GROUP_INIT (id )
627
695
#endif
628
696
629
- #define GPIO_NRF_DEVICE (id ) \
630
- GPIOTE_CHECK(id); \
631
- static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
632
- .common = { \
633
- .port_pin_mask = \
634
- GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
635
- }, \
636
- .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
637
- .port_num = DT_INST_PROP(id, port), \
638
- .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
639
- .gpiote = GPIOTE_INSTANCE(id), \
640
- GPIO_NRF_PAD_GROUP_INIT(id) \
641
- }; \
642
- \
643
- static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
644
- \
645
- PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
646
- \
647
- DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
648
- PM_DEVICE_DT_INST_GET(id), \
649
- &gpio_nrfx_p##id##_data, \
650
- &gpio_nrfx_p##id##_cfg, \
651
- PRE_KERNEL_1, \
652
- CONFIG_GPIO_INIT_PRIORITY, \
697
+ #define GPIO_NRF_DEVICE (id ) \
698
+ GPIOTE_CHECK(id); \
699
+ static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
700
+ .common = { \
701
+ .port_pin_mask = \
702
+ GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
703
+ }, \
704
+ .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
705
+ .port_num = DT_INST_PROP(id, port), \
706
+ .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
707
+ .gpiote = GPIOTE_INSTANCE(id), \
708
+ GPIO_NRF_PAD_GROUP_INIT(id) \
709
+ IF_ENABLED(GPIOTE_FEATURE_FLAG, \
710
+ (.flags = \
711
+ (DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \
712
+ GPIOTE_FLAG_NO_PORT_EVT : 0) | \
713
+ (DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ? \
714
+ GPIOTE_FLAG_FIXED_CHAN : 0),) \
715
+ ) \
716
+ }; \
717
+ \
718
+ static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
719
+ \
720
+ PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
721
+ \
722
+ DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
723
+ PM_DEVICE_DT_INST_GET(id), \
724
+ &gpio_nrfx_p##id##_data, \
725
+ &gpio_nrfx_p##id##_cfg, \
726
+ PRE_KERNEL_1, \
727
+ CONFIG_GPIO_INIT_PRIORITY, \
653
728
&gpio_nrfx_drv_api_funcs);
654
729
655
730
DT_INST_FOREACH_STATUS_OKAY (GPIO_NRF_DEVICE )
0 commit comments