Skip to content

[nrf fromtree] drivers: gpio: nrfx: Add support for GPIOTE0 in nrf54h20 cpurad #3041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 101 additions & 27 deletions drivers/gpio/gpio_nrfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,26 @@
#include <nrf/gpd.h>
#endif

#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance)
#define GPIOTE_PROP(idx, prop) DT_PROP(GPIOTE(idx), prop)

#define IS_NO_PORT_INSTANCE(id) DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ||
#define IS_FIXED_CH_INSTANCE(id) DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ||

Check notice on line 27 in drivers/gpio/gpio_nrfx.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/gpio/gpio_nrfx.c:27 -#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance) -#define GPIOTE_PROP(idx, prop) DT_PROP(GPIOTE(idx), prop) - -#define IS_NO_PORT_INSTANCE(id) DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) || +#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance) +#define GPIOTE_PROP(idx, prop) DT_PROP(GPIOTE(idx), prop) + +#define IS_NO_PORT_INSTANCE(id) DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ||

#if DT_INST_FOREACH_STATUS_OKAY(IS_NO_PORT_INSTANCE) 0
#define GPIOTE_NO_PORT_EVT_SUPPORT 1
#endif

#if DT_INST_FOREACH_STATUS_OKAY(IS_FIXED_CH_INSTANCE) 0
#define GPIOTE_FIXED_CH_SUPPORT 1
#endif

#if defined(GPIOTE_NO_PORT_EVT_SUPPORT) || defined(GPIOTE_FIXED_CH_SUPPORT)
#define GPIOTE_FEATURE_FLAG 1
#define GPIOTE_FLAG_NO_PORT_EVT BIT(0)

Check notice on line 39 in drivers/gpio/gpio_nrfx.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/gpio/gpio_nrfx.c:39 -#define GPIOTE_FEATURE_FLAG 1 +#define GPIOTE_FEATURE_FLAG 1
#define GPIOTE_FLAG_FIXED_CHAN BIT(1)
#endif

struct gpio_nrfx_data {
/* gpio_driver_data needs to be first */
struct gpio_driver_data common;
Expand All @@ -33,6 +53,9 @@
uint32_t edge_sense;
uint8_t port_num;
nrfx_gpiote_t gpiote;
#if defined(GPIOTE_FEATURE_FLAG)
uint32_t flags;
#endif
#ifdef CONFIG_SOC_NRF54H20_GPD
uint8_t pad_pd;
#endif
Expand Down Expand Up @@ -180,6 +203,7 @@
abs_pin, &input_pin_config);
if (err != NRFX_SUCCESS) {
ret = -EINVAL;

goto end;
}
}
Expand Down Expand Up @@ -211,13 +235,21 @@
}

if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT) && free_ch) {
#ifdef GPIOTE_FEATURE_FLAG
/* Fixed channel was used, no need to free. */
if (cfg->flags & GPIOTE_FLAG_FIXED_CHAN) {
goto end;
}
#endif
err = nrfx_gpiote_channel_free(&cfg->gpiote, ch);
__ASSERT_NO_MSG(err == NRFX_SUCCESS);
}

end:
gpio_nrfx_gpd_retain_set(port, BIT(pin));
return pm_device_runtime_put(port);
int pm_ret = pm_device_runtime_put(port);

return (ret != 0) ? ret : pm_ret;
}

#ifdef CONFIG_GPIO_GET_CONFIG
Expand Down Expand Up @@ -393,6 +425,37 @@
NRFX_GPIOTE_TRIGGER_LOTOHI;
}

static nrfx_err_t chan_alloc(const struct gpio_nrfx_cfg *cfg, gpio_pin_t pin, uint8_t *ch)
{
#ifdef GPIOTE_FEATURE_FLAG
if (cfg->flags & GPIOTE_FLAG_FIXED_CHAN) {
/* Currently fixed channel relation is only present in one instance (GPIOTE0 on
* cpurad). The rules are following:
* - GPIOTE0 can only be used with P1 (pins 4-11) and P2 (pins (0-11))
* - P1: channel => pin - 4, e.g. P1.4 => channel 0, P1.5 => channel 1
* - P2: channel => pin % 8, e.g. P2.0 => channel 0, P2.8 => channel 0
*/
nrfx_err_t err = NRFX_SUCCESS;

if (cfg->port_num == 1) {
if (pin < 4) {
err = NRFX_ERROR_INVALID_PARAM;
} else {
*ch = pin - 4;
}
} else if (cfg->port_num == 2) {
*ch = pin & 0x7;
} else {
err = NRFX_ERROR_INVALID_PARAM;
}

return err;
}
#endif

return nrfx_gpiote_channel_alloc(&cfg->gpiote, ch);
}

static int gpio_nrfx_pin_interrupt_configure(const struct device *port,
gpio_pin_t pin,
enum gpio_int_mode mode,
Expand Down Expand Up @@ -428,14 +491,19 @@
(nrf_gpio_pin_dir_get(abs_pin) == NRF_GPIO_PIN_DIR_INPUT)) {
err = nrfx_gpiote_channel_get(&cfg->gpiote, abs_pin, &ch);
if (err == NRFX_ERROR_INVALID_PARAM) {
err = nrfx_gpiote_channel_alloc(&cfg->gpiote, &ch);
err = chan_alloc(cfg, pin, &ch);
if (err != NRFX_SUCCESS) {
return -ENOMEM;
}
}

trigger_config.p_in_channel = &ch;
} else {
#ifdef GPIOTE_FEATURE_FLAG
if (cfg->flags & GPIOTE_FLAG_NO_PORT_EVT) {
return -ENOTSUP;
}
#endif
/* If edge mode with channel was previously used and we are changing to sense or
* level triggered, we must free the channel.
*/
Expand Down Expand Up @@ -641,7 +709,6 @@
#endif
};

#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance)
#define GPIOTE_INST(id) DT_PROP(GPIOTE_PHANDLE(id), instance)

#define GPIOTE_INSTANCE(id) \
Expand All @@ -668,30 +735,37 @@
#define PAD_PD(inst)
#endif

#define GPIO_NRF_DEVICE(id) \
GPIOTE_CHECK(id); \
static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
.common = { \
.port_pin_mask = \
GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
}, \
.port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
.port_num = DT_INST_PROP(id, port), \
.edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
.gpiote = GPIOTE_INSTANCE(id), \
PAD_PD(id) \
}; \
\
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
\
PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
\
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
PM_DEVICE_DT_INST_GET(id), \
&gpio_nrfx_p##id##_data, \
&gpio_nrfx_p##id##_cfg, \
PRE_KERNEL_1, \
CONFIG_GPIO_INIT_PRIORITY, \
#define GPIO_NRF_DEVICE(id) \
GPIOTE_CHECK(id); \
static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \
.common = { \
.port_pin_mask = \
GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \
}, \
.port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \
.port_num = DT_INST_PROP(id, port), \
.edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \
.gpiote = GPIOTE_INSTANCE(id), \
IF_ENABLED(GPIOTE_FEATURE_FLAG, \
(.flags = \
(DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \
GPIOTE_FLAG_NO_PORT_EVT : 0) | \
(DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ? \
GPIOTE_FLAG_FIXED_CHAN : 0),) \
) \
PAD_PD(id) \
}; \
\
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
\
PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
\
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
PM_DEVICE_DT_INST_GET(id), \
&gpio_nrfx_p##id##_data, \
&gpio_nrfx_p##id##_cfg, \
PRE_KERNEL_1, \
CONFIG_GPIO_INIT_PRIORITY, \
&gpio_nrfx_drv_api_funcs);

Check notice on line 770 in drivers/gpio/gpio_nrfx.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/gpio/gpio_nrfx.c:770 -#define GPIO_NRF_DEVICE(id) \ - GPIOTE_CHECK(id); \ - static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \ - .common = { \ - .port_pin_mask = \ - GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \ - }, \ - .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \ - .port_num = DT_INST_PROP(id, port), \ - .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \ - .gpiote = GPIOTE_INSTANCE(id), \ +#define GPIO_NRF_DEVICE(id) \ + GPIOTE_CHECK(id); \ + static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \ + }, \ + .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \ + .port_num = DT_INST_PROP(id, port), \ + .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \ + .gpiote = GPIOTE_INSTANCE(id), \ IF_ENABLED(GPIOTE_FEATURE_FLAG, \ (.flags = \ (DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \ GPIOTE_FLAG_NO_PORT_EVT : 0) | \ (DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ? \ GPIOTE_FLAG_FIXED_CHAN : 0),) \ - ) \ - PAD_PD(id) \ - }; \ - \ - static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \ - \ - PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \ - \ - DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \ - PM_DEVICE_DT_INST_GET(id), \ - &gpio_nrfx_p##id##_data, \ - &gpio_nrfx_p##id##_cfg, \ - PRE_KERNEL_1, \ - CONFIG_GPIO_INIT_PRIORITY, \ - &gpio_nrfx_drv_api_funcs); + ) PAD_PD(id)}; \ + \ + static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \ + \ + PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \ + \ + DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, PM_DEVICE_DT_INST_GET(id), \ + &gpio_nrfx_p##id##_data, &gpio_nrfx_p##id##_cfg, PRE_KERNEL_1, \ + CONFIG_GPIO_INIT_PRIORITY, &gpio_nrfx_drv_api_funcs);
DT_INST_FOREACH_STATUS_OKAY(GPIO_NRF_DEVICE)
12 changes: 12 additions & 0 deletions dts/bindings/gpio/nordic,nrf-gpiote.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ compatible: "nordic,nrf-gpiote"
include:
- base.yaml
- nordic,split-channels.yaml
- pinctrl-device.yaml

properties:
reg:
Expand All @@ -16,6 +17,17 @@ properties:
interrupts:
required: true

no-port-event:
type: boolean
description: |
Indicates that the GPIOTE instance does not support PORT event.

fixed-channels-supported:
type: boolean
description: |
Indicates that the GPIOTE instance has fixed connection between pins and TE channels.
It means that a specific TE channel must be used for a given pin.

instance:
type: int
required: true
Expand Down
10 changes: 10 additions & 0 deletions dts/vendor/nordic/nrf54h20.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,16 @@
interrupts = <37 NRF_DEFAULT_IRQ_PRIORITY>;
};

gpiote0: gpiote@27000 {
compatible = "nordic,nrf-gpiote";
reg = <0x27000 0x1000>;
status = "disabled";
interrupts = <39 NRF_DEFAULT_IRQ_PRIORITY>;
instance = <0>;
no-port-event;
fixed-channels-supported;
};

timer020: timer@28000 {
compatible = "nordic,nrf-timer";
reg = <0x28000 0x1000>;
Expand Down
2 changes: 1 addition & 1 deletion modules/hal_nordic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if(CONFIG_NRF_REGTOOL_GENERATE_UICR)
list(APPEND nrf_regtool_components GENERATE:UICR)
endif()
if(DEFINED nrf_regtool_components)
find_package(nrf-regtool 9.1.0
find_package(nrf-regtool 9.2.0
REQUIRED
COMPONENTS ${nrf_regtool_components}
PATHS ${CMAKE_CURRENT_LIST_DIR}/nrf-regtool
Expand Down
4 changes: 4 additions & 0 deletions modules/hal_nordic/nrfx/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ config NRFX_GPIOTE131
depends on $(dt_nodelabel_exists,gpiote131)
select NRFX_GPIOTE

config NRFX_GPIOTE_NONUNIFORM_INSTANCES
def_bool $(dt_nodelabel_enabled,gpiote0)
depends on $(dt_nodelabel_bool_prop,gpiote0,fixed-channels-supported)

config NRFX_GPIOTE_NUM_OF_EVT_HANDLERS
int "Number of event handlers"
depends on NRFX_GPIOTE
Expand Down
3 changes: 3 additions & 0 deletions modules/hal_nordic/nrfx/nrfx_kconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@
#ifdef CONFIG_NRFX_GPIOTE131
#define NRFX_GPIOTE131_ENABLED 1
#endif
#ifdef CONFIG_NRFX_GPIOTE_NONUNIFORM_INSTANCES
#define NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES 1
#endif

#ifdef CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS
#define NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: Apache-2.0 */

&pinctrl {
gpiote0_default_alt: gpiote0_default_alt {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 4)>;
};
};
};

/ {
resources {
compatible = "test-gpio-basic-api";
out-gpios = <&gpio1 5 0>;
in-gpios = <&gpio1 4 0>;
};
};

&gpio1 {
status = "okay";
gpiote-instance = <&gpiote0>;
};

&gpiote0 {
status = "okay";
pinctrl-0 = <&gpiote0_default_alt>;
pinctrl-names = "default";
};
7 changes: 5 additions & 2 deletions tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,19 @@ static int init_callback(const struct device *dev_in, const struct device *dev_o
static void trigger_callback(const struct device *dev_in, const struct device *dev_out,
int enable_cb)
{
int rc;

gpio_pin_set(dev_out, PIN_OUT, 0);
k_sleep(K_MSEC(100));

cb_cnt[0] = 0;
cb_cnt[1] = 0;
if (enable_cb == 1) {
gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_RISING);
rc = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_RISING);
} else {
gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE);
rc = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE);
}
zassert_equal(rc, 0);
k_sleep(K_MSEC(100));
gpio_pin_set(dev_out, PIN_OUT, 1);
k_sleep(K_MSEC(1000));
Expand Down
6 changes: 6 additions & 0 deletions tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ ZTEST(after_flash_gpio_config_trigger, test_gpio_config_twice_trigger)
k_sleep(K_MSEC(10));
zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt);

ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE);
zassert_ok(ret, "interrupt disabling failed");

gpio_remove_callback(dev_in, &drv_data->gpio_cb);
}

Expand Down Expand Up @@ -115,5 +118,8 @@ ZTEST(after_flash_gpio_config_trigger, test_gpio_config_trigger)
k_sleep(K_MSEC(10));
zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt);

ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE);
zassert_ok(ret, "interrupt disabling failed");

gpio_remove_callback(dev_in, &drv_data->gpio_cb);
}
7 changes: 7 additions & 0 deletions tests/drivers/gpio/gpio_basic_api/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,10 @@ tests:
platform_allow:
- siwx917_rb4338a
extra_args: "DTC_OVERLAY_FILE=boards/siwx917_rb4338a-uulp.overlay"
drivers.gpio.2pin.nrf54h20_cpurad_gpiote0:
harness_config:
fixture: i2s_loopback # Loopback includes the pin pair needed for that test
platform_allow:
- nrf54h20dk/nrf54h20/cpurad
extra_args:
- DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpurad_gpiote0.overlay"
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ manifest:
groups:
- hal
- name: hal_nordic
revision: 71308dc6d8c021887ce5d98a36cafe9517375a91
revision: pull/298/head
path: modules/hal/nordic
groups:
- hal
Expand Down
Loading