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
@@ -189,6 +212,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
189
212
abs_pin , & input_pin_config );
190
213
if (err != NRFX_SUCCESS ) {
191
214
ret = - EINVAL ;
215
+
192
216
goto end ;
193
217
}
194
218
}
@@ -220,13 +244,21 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
220
244
}
221
245
222
246
if (IS_ENABLED (CONFIG_GPIO_NRFX_INTERRUPT ) && free_ch ) {
247
+ #ifdef GPIOTE_FEATURE_FLAG
248
+ /* Fixed channel was used, no need to free. */
249
+ if (cfg -> flags & GPIOTE_FLAG_FIXED_CHAN ) {
250
+ goto end ;
251
+ }
252
+ #endif
223
253
err = nrfx_gpiote_channel_free (& cfg -> gpiote , ch );
224
254
__ASSERT_NO_MSG (err == NRFX_SUCCESS );
225
255
}
226
256
227
257
end :
228
258
gpio_nrfx_gpd_retain_set (port , BIT (pin ), flags );
229
- return pm_device_runtime_put (port );
259
+ int pm_ret = pm_device_runtime_put (port );
260
+
261
+ return (ret != 0 ) ? ret : pm_ret ;
230
262
}
231
263
232
264
#ifdef CONFIG_GPIO_GET_CONFIG
@@ -402,6 +434,37 @@ static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode,
402
434
NRFX_GPIOTE_TRIGGER_LOTOHI ;
403
435
}
404
436
437
+ static nrfx_err_t chan_alloc (const struct gpio_nrfx_cfg * cfg , gpio_pin_t pin , uint8_t * ch )
438
+ {
439
+ #ifdef GPIOTE_FEATURE_FLAG
440
+ if (cfg -> flags & GPIOTE_FLAG_FIXED_CHAN ) {
441
+ /* Currently fixed channel relation is only present in one instance (GPIOTE0 on
442
+ * cpurad). The rules are following:
443
+ * - GPIOTE0 can only be used with P1 (pins 4-11) and P2 (pins (0-11))
444
+ * - P1: channel => pin - 4, e.g. P1.4 => channel 0, P1.5 => channel 1
445
+ * - P2: channel => pin % 8, e.g. P2.0 => channel 0, P2.8 => channel 0
446
+ */
447
+ nrfx_err_t err = NRFX_SUCCESS ;
448
+
449
+ if (cfg -> port_num == 1 ) {
450
+ if (pin < 4 ) {
451
+ err = NRFX_ERROR_INVALID_PARAM ;
452
+ } else {
453
+ * ch = pin - 4 ;
454
+ }
455
+ } else if (cfg -> port_num == 2 ) {
456
+ * ch = pin & 0x7 ;
457
+ } else {
458
+ err = NRFX_ERROR_INVALID_PARAM ;
459
+ }
460
+
461
+ return err ;
462
+ }
463
+ #endif
464
+
465
+ return nrfx_gpiote_channel_alloc (& cfg -> gpiote , ch );
466
+ }
467
+
405
468
static int gpio_nrfx_pin_interrupt_configure (const struct device * port ,
406
469
gpio_pin_t pin ,
407
470
enum gpio_int_mode mode ,
@@ -437,14 +500,19 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
437
500
(nrf_gpio_pin_dir_get (abs_pin ) == NRF_GPIO_PIN_DIR_INPUT )) {
438
501
err = nrfx_gpiote_channel_get (& cfg -> gpiote , abs_pin , & ch );
439
502
if (err == NRFX_ERROR_INVALID_PARAM ) {
440
- err = nrfx_gpiote_channel_alloc ( & cfg -> gpiote , & ch );
503
+ err = chan_alloc ( cfg , pin , & ch );
441
504
if (err != NRFX_SUCCESS ) {
442
505
return - ENOMEM ;
443
506
}
444
507
}
445
508
446
509
trigger_config .p_in_channel = & ch ;
447
510
} else {
511
+ #ifdef GPIOTE_FEATURE_FLAG
512
+ if (cfg -> flags & GPIOTE_FLAG_NO_PORT_EVT ) {
513
+ return - ENOTSUP ;
514
+ }
515
+ #endif
448
516
/* If edge mode with channel was previously used and we are changing to sense or
449
517
* level triggered, we must free the channel.
450
518
*/
@@ -650,7 +718,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
650
718
#endif
651
719
};
652
720
653
- #define GPIOTE_PHANDLE (id ) DT_INST_PHANDLE(id, gpiote_instance)
654
721
#define GPIOTE_INST (id ) DT_PROP(GPIOTE_PHANDLE(id), instance)
655
722
656
723
#define GPIOTE_INSTANCE (id ) \
@@ -677,30 +744,37 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
677
744
#define PAD_PD (inst )
678
745
#endif
679
746
680
- #define GPIO_NRF_DEVICE (id ) \
681
- GPIOTE_CHECK(id); \
682
- static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
683
- .common = { \
684
- .port_pin_mask = \
685
- GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
686
- }, \
687
- .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
688
- .port_num = DT_INST_PROP(id, port), \
689
- .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
690
- .gpiote = GPIOTE_INSTANCE(id), \
691
- PAD_PD(id) \
692
- }; \
693
- \
694
- static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
695
- \
696
- PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
697
- \
698
- DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
699
- PM_DEVICE_DT_INST_GET(id), \
700
- &gpio_nrfx_p##id##_data, \
701
- &gpio_nrfx_p##id##_cfg, \
702
- PRE_KERNEL_1, \
703
- CONFIG_GPIO_INIT_PRIORITY, \
747
+ #define GPIO_NRF_DEVICE (id ) \
748
+ GPIOTE_CHECK(id); \
749
+ static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
750
+ .common = { \
751
+ .port_pin_mask = \
752
+ GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
753
+ }, \
754
+ .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
755
+ .port_num = DT_INST_PROP(id, port), \
756
+ .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
757
+ .gpiote = GPIOTE_INSTANCE(id), \
758
+ IF_ENABLED(GPIOTE_FEATURE_FLAG, \
759
+ (.flags = \
760
+ (DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \
761
+ GPIOTE_FLAG_NO_PORT_EVT : 0) | \
762
+ (DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ? \
763
+ GPIOTE_FLAG_FIXED_CHAN : 0),) \
764
+ ) \
765
+ PAD_PD(id) \
766
+ }; \
767
+ \
768
+ static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
769
+ \
770
+ PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
771
+ \
772
+ DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
773
+ PM_DEVICE_DT_INST_GET(id), \
774
+ &gpio_nrfx_p##id##_data, \
775
+ &gpio_nrfx_p##id##_cfg, \
776
+ PRE_KERNEL_1, \
777
+ CONFIG_GPIO_INIT_PRIORITY, \
704
778
&gpio_nrfx_drv_api_funcs);
705
779
706
780
DT_INST_FOREACH_STATUS_OKAY (GPIO_NRF_DEVICE )
0 commit comments