2222#define GPIO_HAS_PAD_GROUP 0
2323#endif
2424
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+
2545struct gpio_nrfx_data {
2646 /* gpio_driver_data needs to be first */
2747 struct gpio_driver_data common ;
@@ -38,6 +58,9 @@ struct gpio_nrfx_cfg {
3858#if GPIO_HAS_PAD_GROUP
3959 const struct device * pad_group ;
4060#endif
61+ #if defined(GPIOTE_FEATURE_FLAG )
62+ uint32_t flags ;
63+ #endif
4164};
4265
4366static 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,
77100 nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP (cfg -> port_num , pin );
78101 nrf_gpio_pin_pull_t pull = get_pull (flags );
79102 nrf_gpio_pin_drive_t drive ;
103+ int pm_ret ;
80104
81105 switch (flags & (NRF_GPIO_DRIVE_MSK | GPIO_OPEN_DRAIN )) {
82106 case NRF_GPIO_DRIVE_S0S1 :
@@ -156,6 +180,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
156180 abs_pin , & input_pin_config );
157181 if (err != NRFX_SUCCESS ) {
158182 ret = - EINVAL ;
183+
159184 goto end ;
160185 }
161186 }
@@ -187,12 +212,20 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
187212 }
188213
189214 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
190221 err = nrfx_gpiote_channel_free (& cfg -> gpiote , ch );
191222 __ASSERT_NO_MSG (err == NRFX_SUCCESS );
192223 }
193224
194225end :
195- return pm_device_runtime_put (port );
226+ pm_ret = pm_device_runtime_put (port );
227+
228+ return (ret != 0 ) ? ret : pm_ret ;
196229}
197230
198231#ifdef CONFIG_GPIO_GET_CONFIG
@@ -360,6 +393,37 @@ static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode,
360393 NRFX_GPIOTE_TRIGGER_LOTOHI ;
361394}
362395
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+
363427static int gpio_nrfx_pin_interrupt_configure (const struct device * port ,
364428 gpio_pin_t pin ,
365429 enum gpio_int_mode mode ,
@@ -395,14 +459,19 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
395459 (nrf_gpio_pin_dir_get (abs_pin ) == NRF_GPIO_PIN_DIR_INPUT )) {
396460 err = nrfx_gpiote_channel_get (& cfg -> gpiote , abs_pin , & ch );
397461 if (err == NRFX_ERROR_INVALID_PARAM ) {
398- err = nrfx_gpiote_channel_alloc ( & cfg -> gpiote , & ch );
462+ err = chan_alloc ( cfg , pin , & ch );
399463 if (err != NRFX_SUCCESS ) {
400464 return - ENOMEM ;
401465 }
402466 }
403467
404468 trigger_config .p_in_channel = & ch ;
405469 } else {
470+ #ifdef GPIOTE_FEATURE_FLAG
471+ if (cfg -> flags & GPIOTE_FLAG_NO_PORT_EVT ) {
472+ return - ENOTSUP ;
473+ }
474+ #endif
406475 /* If edge mode with channel was previously used and we are changing to sense or
407476 * level triggered, we must free the channel.
408477 */
@@ -600,7 +669,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
600669#endif
601670};
602671
603- #define GPIOTE_PHANDLE (id ) DT_INST_PHANDLE(id, gpiote_instance)
604672#define GPIOTE_INST (id ) DT_PROP(GPIOTE_PHANDLE(id), instance)
605673
606674#define GPIOTE_INSTANCE (id ) \
@@ -626,30 +694,37 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
626694#define GPIO_NRF_PAD_GROUP_INIT (id )
627695#endif
628696
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, \
653728 &gpio_nrfx_drv_api_funcs);
654729
655730DT_INST_FOREACH_STATUS_OKAY (GPIO_NRF_DEVICE )
0 commit comments