Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
30c3b09
[nrf fromtree] drivers: gpio: nrf: use nrf_gpio_pin_retain_enable|dis…
gmarull Nov 21, 2024
21d0625
[nrf fromtree] drivers: gpio: nrf: add support for gpio_pin_get_config
gmarull Mar 14, 2025
43ba1df
[nrf fromtree] drivers: gpio: gpio_nrfx: store init output val for ge…
bjarki-andreasen May 7, 2025
385710a
[nrf fromtree] drivers: gpio: nrfx: impl pm device runtime
bjarki-andreasen May 6, 2025
a01556e
[nrf fromtree] drivers: spi_nrfx: Fix NRFX_ASSERT crash when sck pin …
anthony289478 Dec 18, 2024
0620111
[nrf fromtree] drivers: spi: nrfx_spim: Detect wrong configuration
nordic-krch Apr 9, 2025
c1f99c8
[nrf fromtree] drivers: spi: nrfx_spim: Remove explicit references to…
nordic-krch Apr 9, 2025
9ad85cd
[nrf fromtree] drivers: spi: nrfx_spim: use clock phandle for HSFLL n…
masz-nordic May 6, 2025
350d53d
[nrf fromtree] drivers: spi: nrfx_spim: impl spi_context_cs_get_all/p…
bjarki-andreasen May 6, 2025
827873a
[nrf fromtree] drivers: spi: nrfx_spim: self resume until spi_release()
bjarki-andreasen May 16, 2025
14f177b
[nrf fromtree] include: spi: Clarify data frame units and meaning
decsny Sep 20, 2024
b19912b
[nrf fromtree] spi: spi_context: extract lock condition
JordanYates Dec 9, 2024
8b19f13
[nrf fromtree] spi: context: update state when already locked
JordanYates Dec 9, 2024
e319b08
[nrf fromtree] drivers: spi_context: Functions for remaining len
decsny Jan 17, 2025
17a4d70
[nrf fromtree] drivers: spi_context: Add comments for context
decsny Feb 20, 2025
0909d76
[nrf fromtree] drivers: spi: context: Add helper for CS GPIO PM
bjarki-andreasen May 6, 2025
776d97e
[nrf noup] tests: drivers: spi: loopback: extend with cs gpio
bjarki-andreasen Jun 11, 2025
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
209 changes: 164 additions & 45 deletions drivers/gpio/gpio_nrfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <zephyr/drivers/gpio.h>
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
#include <zephyr/irq.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>

#include <zephyr/drivers/gpio/gpio_utils.h>

Expand Down Expand Up @@ -62,53 +64,37 @@
return NRF_GPIO_PIN_NOPULL;
}

static int gpio_nrfx_gpd_retain_set(const struct device *port, uint32_t mask, gpio_flags_t flags)
static void gpio_nrfx_gpd_retain_set(const struct device *port, uint32_t mask, gpio_flags_t flags)
{
#ifdef CONFIG_SOC_NRF54H20_GPD
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);

if (cfg->pad_pd == NRF_GPD_FAST_ACTIVE1) {
int ret;

if (flags & GPIO_OUTPUT) {
cfg->port->RETAINSET = mask;
}

ret = nrf_gpd_release(NRF_GPD_FAST_ACTIVE1);
if (ret < 0) {
return ret;
}
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1 || !(flags & GPIO_OUTPUT)) {
return;
}

nrf_gpio_port_retain_enable(cfg->port, mask);
#else
ARG_UNUSED(port);
ARG_UNUSED(mask);
ARG_UNUSED(flags);
#endif

return 0;
}

static int gpio_nrfx_gpd_retain_clear(const struct device *port, uint32_t mask)
static void gpio_nrfx_gpd_retain_clear(const struct device *port, uint32_t mask)
{
#ifdef CONFIG_SOC_NRF54H20_GPD
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);

if (cfg->pad_pd == NRF_GPD_FAST_ACTIVE1) {
int ret;

ret = nrf_gpd_request(NRF_GPD_FAST_ACTIVE1);
if (ret < 0) {
return ret;
}

cfg->port->RETAINCLR = mask;
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
return;
}

nrf_gpio_port_retain_disable(cfg->port, mask);
#else
ARG_UNUSED(port);
ARG_UNUSED(mask);
#endif

return 0;
}

static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
Expand Down Expand Up @@ -152,11 +138,13 @@
return -EINVAL;
}

ret = gpio_nrfx_gpd_retain_clear(port, BIT(pin));
ret = pm_device_runtime_get(port);
if (ret < 0) {
return ret;
}

gpio_nrfx_gpd_retain_clear(port, BIT(pin));

if (flags & GPIO_OUTPUT_INIT_HIGH) {
nrf_gpio_port_out_set(cfg->port, BIT(pin));
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
Expand Down Expand Up @@ -237,9 +225,79 @@
}

end:
(void)gpio_nrfx_gpd_retain_set(port, BIT(pin), flags);
return ret;
gpio_nrfx_gpd_retain_set(port, BIT(pin), flags);
return pm_device_runtime_put(port);
}

#ifdef CONFIG_GPIO_GET_CONFIG
static int gpio_nrfx_pin_get_config(const struct device *port, gpio_pin_t pin,
gpio_flags_t *flags)
{

Check notice on line 235 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:235 -static int gpio_nrfx_pin_get_config(const struct device *port, gpio_pin_t pin, - gpio_flags_t *flags) +static int gpio_nrfx_pin_get_config(const struct device *port, gpio_pin_t pin, gpio_flags_t *flags)
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin);

*flags = 0U;

nrf_gpio_pin_dir_t dir = nrf_gpio_pin_dir_get(abs_pin);

if (dir == NRF_GPIO_PIN_DIR_OUTPUT) {
*flags |= GPIO_OUTPUT;
*flags |= nrf_gpio_pin_out_read(abs_pin)
? GPIO_OUTPUT_INIT_HIGH
: GPIO_OUTPUT_INIT_LOW;
}

Check notice on line 248 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:248 - *flags |= nrf_gpio_pin_out_read(abs_pin) - ? GPIO_OUTPUT_INIT_HIGH - : GPIO_OUTPUT_INIT_LOW; + *flags |= nrf_gpio_pin_out_read(abs_pin) ? GPIO_OUTPUT_INIT_HIGH + : GPIO_OUTPUT_INIT_LOW;

nrf_gpio_pin_input_t input = nrf_gpio_pin_input_get(abs_pin);

if (input == NRF_GPIO_PIN_INPUT_CONNECT) {
*flags |= GPIO_INPUT;
}

nrf_gpio_pin_pull_t pull = nrf_gpio_pin_pull_get(abs_pin);

switch (pull) {
case NRF_GPIO_PIN_PULLUP:
*flags |= GPIO_PULL_UP;
case NRF_GPIO_PIN_PULLDOWN:
*flags |= GPIO_PULL_DOWN;
default:
break;
}

nrf_gpio_pin_drive_t drive = nrf_gpio_pin_drive_get(abs_pin);

switch (drive) {
case NRF_GPIO_PIN_S0S1:
*flags |= NRF_GPIO_DRIVE_S0S1;
break;
case NRF_GPIO_PIN_S0H1:
*flags |= NRF_GPIO_DRIVE_S0H1;
break;
case NRF_GPIO_PIN_H0S1:
*flags |= NRF_GPIO_DRIVE_H0S1;
break;
case NRF_GPIO_PIN_H0H1:
*flags |= NRF_GPIO_DRIVE_H0H1;
break;
case NRF_GPIO_PIN_S0D1:
*flags |= NRF_GPIO_DRIVE_S0 | GPIO_OPEN_DRAIN;
break;
case NRF_GPIO_PIN_H0D1:
*flags |= NRF_GPIO_DRIVE_H0 | GPIO_OPEN_DRAIN;
break;
case NRF_GPIO_PIN_D0S1:
*flags |= NRF_GPIO_DRIVE_S1 | GPIO_OPEN_SOURCE;
break;
case NRF_GPIO_PIN_D0H1:
*flags |= NRF_GPIO_DRIVE_H1 | GPIO_OPEN_SOURCE;
break;
default:
break;
}

return 0;
}
#endif

static int gpio_nrfx_port_get_raw(const struct device *port,
gpio_port_value_t *value)
Expand All @@ -261,15 +319,16 @@
const uint32_t set_mask = value & mask;
const uint32_t clear_mask = (~set_mask) & mask;

ret = gpio_nrfx_gpd_retain_clear(port, mask);
ret = pm_device_runtime_get(port);
if (ret < 0) {
return ret;
}

gpio_nrfx_gpd_retain_clear(port, mask);
nrf_gpio_port_out_set(reg, set_mask);
nrf_gpio_port_out_clear(reg, clear_mask);

return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
return pm_device_runtime_put(port);
}

static int gpio_nrfx_port_set_bits_raw(const struct device *port,
Expand All @@ -278,14 +337,15 @@
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
int ret;

ret = gpio_nrfx_gpd_retain_clear(port, mask);
ret = pm_device_runtime_get(port);
if (ret < 0) {
return ret;
}

gpio_nrfx_gpd_retain_clear(port, mask);
nrf_gpio_port_out_set(reg, mask);

return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
return pm_device_runtime_put(port);
}

static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
Expand All @@ -294,14 +354,15 @@
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
int ret;

ret = gpio_nrfx_gpd_retain_clear(port, mask);
ret = pm_device_runtime_get(port);
if (ret < 0) {
return ret;
}

gpio_nrfx_gpd_retain_clear(port, mask);
nrf_gpio_port_out_clear(reg, mask);

return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
return pm_device_runtime_put(port);
}

static int gpio_nrfx_port_toggle_bits(const struct device *port,
Expand All @@ -313,15 +374,16 @@
const uint32_t clear_mask = (~value) & mask;
int ret;

ret = gpio_nrfx_gpd_retain_clear(port, mask);
ret = pm_device_runtime_get(port);
if (ret < 0) {
return ret;
}

gpio_nrfx_gpd_retain_clear(port, mask);
nrf_gpio_port_out_set(reg, set_mask);
nrf_gpio_port_out_clear(reg, clear_mask);

return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
return pm_device_runtime_put(port);
}

#ifdef CONFIG_GPIO_NRFX_INTERRUPT
Expand Down Expand Up @@ -480,17 +542,68 @@
IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_isr, \
NRFX_CONCAT(nrfx_gpiote_, DT_PROP(node_id, instance), _irq_handler), 0);

static int gpio_nrfx_pm_suspend(const struct device *port)
{
#ifdef CONFIG_SOC_NRF54H20_GPD
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);

if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
return 0;
}

return nrf_gpd_release(NRF_GPD_FAST_ACTIVE1);
#else
ARG_UNUSED(port);
return 0;
#endif
}

static int gpio_nrfx_pm_resume(const struct device *port)
{
#ifdef CONFIG_SOC_NRF54H20_GPD
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);

if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
return 0;
}

return nrf_gpd_request(NRF_GPD_FAST_ACTIVE1);
#else
ARG_UNUSED(port);
return 0;
#endif
}

static int gpio_nrfx_pm_hook(const struct device *port, enum pm_device_action action)
{
int ret;

switch (action) {
case PM_DEVICE_ACTION_SUSPEND:
ret = gpio_nrfx_pm_suspend(port);
break;
case PM_DEVICE_ACTION_RESUME:
ret = gpio_nrfx_pm_resume(port);
break;
default:
ret = -ENOTSUP;
break;
}

return ret;
}

static int gpio_nrfx_init(const struct device *port)
{
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
nrfx_err_t err;

if (!has_gpiote(cfg)) {
return 0;
goto pm_init;
}

if (nrfx_gpiote_init_check(&cfg->gpiote)) {
return 0;
goto pm_init;
}

err = nrfx_gpiote_init(&cfg->gpiote, 0 /*not used*/);
Expand All @@ -503,7 +616,8 @@
DT_FOREACH_STATUS_OKAY(nordic_nrf_gpiote, GPIOTE_IRQ_HANDLER_CONNECT);
#endif /* CONFIG_GPIO_NRFX_INTERRUPT */

return 0;
pm_init:
return pm_device_driver_init(port, gpio_nrfx_pm_hook);
}

static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = {
Expand All @@ -520,6 +634,9 @@
#ifdef CONFIG_GPIO_GET_DIRECTION
.port_get_direction = gpio_nrfx_port_get_direction,
#endif
#ifdef CONFIG_GPIO_GET_CONFIG
.pin_get_config = gpio_nrfx_pin_get_config,
#endif
};

#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance)
Expand Down Expand Up @@ -565,12 +682,14 @@
\
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, \
NULL, \
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 694 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:694 -#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, \ - &gpio_nrfx_drv_api_funcs); +#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, &gpio_nrfx_drv_api_funcs);
DT_INST_FOREACH_STATUS_OKAY(GPIO_NRF_DEVICE)
Loading
Loading