Skip to content

Commit 6b75855

Browse files
committed
drivers: gpio: nrfx: Add support for GPIOTE0 on cpurad
Add support for special GPIOTE0 instance on nrf54h20/cpurad. This instance requires special handling because: - there is no support for PORT event (level interrupts) - TE channels are fixed to the pin Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
1 parent a56871a commit 6b75855

File tree

1 file changed

+102
-27
lines changed

1 file changed

+102
-27
lines changed

drivers/gpio/gpio_nrfx.c

Lines changed: 102 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,26 @@
2020
#include <nrf/gpd.h>
2121
#endif
2222

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+
2343
struct gpio_nrfx_data {
2444
/* gpio_driver_data needs to be first */
2545
struct gpio_driver_data common;
@@ -33,6 +53,9 @@ struct gpio_nrfx_cfg {
3353
uint32_t edge_sense;
3454
uint8_t port_num;
3555
nrfx_gpiote_t gpiote;
56+
#if defined(GPIOTE_FEATURE_FLAG)
57+
uint32_t flags;
58+
#endif
3659
#ifdef CONFIG_SOC_NRF54H20_GPD
3760
uint8_t pad_pd;
3861
#endif
@@ -189,6 +212,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
189212
abs_pin, &input_pin_config);
190213
if (err != NRFX_SUCCESS) {
191214
ret = -EINVAL;
215+
192216
goto end;
193217
}
194218
}
@@ -220,13 +244,21 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
220244
}
221245

222246
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
223253
err = nrfx_gpiote_channel_free(&cfg->gpiote, ch);
224254
__ASSERT_NO_MSG(err == NRFX_SUCCESS);
225255
}
226256

227257
end:
228258
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;
230262
}
231263

232264
#ifdef CONFIG_GPIO_GET_CONFIG
@@ -402,6 +434,37 @@ static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode,
402434
NRFX_GPIOTE_TRIGGER_LOTOHI;
403435
}
404436

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+
405468
static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
406469
gpio_pin_t pin,
407470
enum gpio_int_mode mode,
@@ -437,13 +500,19 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
437500
(nrf_gpio_pin_dir_get(abs_pin) == NRF_GPIO_PIN_DIR_INPUT)) {
438501
err = nrfx_gpiote_channel_get(&cfg->gpiote, abs_pin, &ch);
439502
if (err == NRFX_ERROR_INVALID_PARAM) {
440-
err = nrfx_gpiote_channel_alloc(&cfg->gpiote, &ch);
503+
err = chan_alloc(cfg, pin, &ch);
441504
if (err != NRFX_SUCCESS) {
442505
return -ENOMEM;
443506
}
444507
}
445508

446509
trigger_config.p_in_channel = &ch;
510+
} else {
511+
#ifdef GPIOTE_FEATURE_FLAG
512+
if (cfg->flags & GPIOTE_FLAG_NO_PORT_EVT) {
513+
return -ENOTSUP;
514+
}
515+
#endif
447516
}
448517

449518
err = nrfx_gpiote_input_configure(&cfg->gpiote, abs_pin, &input_pin_config);
@@ -641,7 +710,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
641710
#endif
642711
};
643712

644-
#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance)
645713
#define GPIOTE_INST(id) DT_PROP(GPIOTE_PHANDLE(id), instance)
646714

647715
#define GPIOTE_INSTANCE(id) \
@@ -668,30 +736,37 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
668736
#define PAD_PD(inst)
669737
#endif
670738

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, \
739+
#define GPIO_NRF_DEVICE(id) \
740+
GPIOTE_CHECK(id); \
741+
static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
742+
.common = { \
743+
.port_pin_mask = \
744+
GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
745+
}, \
746+
.port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
747+
.port_num = DT_INST_PROP(id, port), \
748+
.edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
749+
.gpiote = GPIOTE_INSTANCE(id), \
750+
IF_ENABLED(GPIOTE_FEATURE_FLAG, \
751+
(.flags = \
752+
(DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \
753+
GPIOTE_FLAG_NO_PORT_EVT : 0) | \
754+
(DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ? \
755+
GPIOTE_FLAG_FIXED_CHAN : 0),) \
756+
) \
757+
PAD_PD(id) \
758+
}; \
759+
\
760+
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
761+
\
762+
PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
763+
\
764+
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
765+
PM_DEVICE_DT_INST_GET(id), \
766+
&gpio_nrfx_p##id##_data, \
767+
&gpio_nrfx_p##id##_cfg, \
768+
PRE_KERNEL_1, \
769+
CONFIG_GPIO_INIT_PRIORITY, \
695770
&gpio_nrfx_drv_api_funcs);
696771

697772
DT_INST_FOREACH_STATUS_OKAY(GPIO_NRF_DEVICE)

0 commit comments

Comments
 (0)