Skip to content

Commit e14f786

Browse files
drivers: gpio: nrfx: impl pm device runtime
Implement PM_DEVICE_RUNTIME for gpio_nrfx.c PM is required to request/release the GPD domain if such exists for a given GPIO instance. Without this, every single API call will result in a requesting the GPD domain, which makes it slow and unusable from ISRs, given GPD requires IPC. Now, user can simply get the GPIO before using it, and put it once done, calling the APIs from ISR while resumed. Signed-off-by: Bjarki Arge Andreasen <[email protected]>
1 parent 2742e46 commit e14f786

File tree

1 file changed

+91
-45
lines changed

1 file changed

+91
-45
lines changed

drivers/gpio/gpio_nrfx.c

Lines changed: 91 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <zephyr/drivers/gpio.h>
1212
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
1313
#include <zephyr/irq.h>
14+
#include <zephyr/pm/device.h>
15+
#include <zephyr/pm/device_runtime.h>
1416

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

@@ -62,53 +64,37 @@ static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags)
6264
return NRF_GPIO_PIN_NOPULL;
6365
}
6466

65-
static int gpio_nrfx_gpd_retain_set(const struct device *port, uint32_t mask, gpio_flags_t flags)
67+
static void gpio_nrfx_gpd_retain_set(const struct device *port, uint32_t mask, gpio_flags_t flags)
6668
{
6769
#ifdef CONFIG_SOC_NRF54H20_GPD
6870
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
6971

70-
if (cfg->pad_pd == NRF_GPD_FAST_ACTIVE1) {
71-
int ret;
72-
73-
if (flags & GPIO_OUTPUT) {
74-
nrf_gpio_port_retain_enable(cfg->port, mask);
75-
}
76-
77-
ret = nrf_gpd_release(NRF_GPD_FAST_ACTIVE1);
78-
if (ret < 0) {
79-
return ret;
80-
}
72+
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1 || !(flags & GPIO_OUTPUT)) {
73+
return;
8174
}
75+
76+
nrf_gpio_port_retain_enable(cfg->port, mask);
8277
#else
8378
ARG_UNUSED(port);
8479
ARG_UNUSED(mask);
8580
ARG_UNUSED(flags);
8681
#endif
87-
88-
return 0;
8982
}
9083

91-
static int gpio_nrfx_gpd_retain_clear(const struct device *port, uint32_t mask)
84+
static void gpio_nrfx_gpd_retain_clear(const struct device *port, uint32_t mask)
9285
{
9386
#ifdef CONFIG_SOC_NRF54H20_GPD
9487
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
9588

96-
if (cfg->pad_pd == NRF_GPD_FAST_ACTIVE1) {
97-
int ret;
98-
99-
ret = nrf_gpd_request(NRF_GPD_FAST_ACTIVE1);
100-
if (ret < 0) {
101-
return ret;
102-
}
103-
104-
nrf_gpio_port_retain_disable(cfg->port, mask);
89+
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
90+
return;
10591
}
92+
93+
nrf_gpio_port_retain_disable(cfg->port, mask);
10694
#else
10795
ARG_UNUSED(port);
10896
ARG_UNUSED(mask);
10997
#endif
110-
111-
return 0;
11298
}
11399

114100
static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
@@ -152,11 +138,13 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
152138
return -EINVAL;
153139
}
154140

155-
ret = gpio_nrfx_gpd_retain_clear(port, BIT(pin));
141+
ret = pm_device_runtime_get(port);
156142
if (ret < 0) {
157143
return ret;
158144
}
159145

146+
gpio_nrfx_gpd_retain_clear(port, BIT(pin));
147+
160148
if (flags & GPIO_OUTPUT_INIT_HIGH) {
161149
nrf_gpio_port_out_set(cfg->port, BIT(pin));
162150
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
@@ -237,8 +225,8 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin,
237225
}
238226

239227
end:
240-
(void)gpio_nrfx_gpd_retain_set(port, BIT(pin), flags);
241-
return ret;
228+
gpio_nrfx_gpd_retain_set(port, BIT(pin), flags);
229+
return pm_device_runtime_put(port);
242230
}
243231

244232
static int gpio_nrfx_port_get_raw(const struct device *port,
@@ -261,15 +249,16 @@ static int gpio_nrfx_port_set_masked_raw(const struct device *port,
261249
const uint32_t set_mask = value & mask;
262250
const uint32_t clear_mask = (~set_mask) & mask;
263251

264-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
252+
ret = pm_device_runtime_get(port);
265253
if (ret < 0) {
266254
return ret;
267255
}
268256

257+
gpio_nrfx_gpd_retain_clear(port, mask);
269258
nrf_gpio_port_out_set(reg, set_mask);
270259
nrf_gpio_port_out_clear(reg, clear_mask);
271-
272-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
260+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
261+
return pm_device_runtime_put(port);
273262
}
274263

275264
static int gpio_nrfx_port_set_bits_raw(const struct device *port,
@@ -278,14 +267,15 @@ static int gpio_nrfx_port_set_bits_raw(const struct device *port,
278267
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
279268
int ret;
280269

281-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
270+
ret = pm_device_runtime_get(port);
282271
if (ret < 0) {
283272
return ret;
284273
}
285274

275+
gpio_nrfx_gpd_retain_clear(port, mask);
286276
nrf_gpio_port_out_set(reg, mask);
287-
288-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
277+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
278+
return pm_device_runtime_put(port);
289279
}
290280

291281
static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
@@ -294,14 +284,15 @@ static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
294284
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
295285
int ret;
296286

297-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
287+
ret = pm_device_runtime_get(port);
298288
if (ret < 0) {
299289
return ret;
300290
}
301291

292+
gpio_nrfx_gpd_retain_clear(port, mask);
302293
nrf_gpio_port_out_clear(reg, mask);
303-
304-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
294+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
295+
return pm_device_runtime_put(port);
305296
}
306297

307298
static int gpio_nrfx_port_toggle_bits(const struct device *port,
@@ -313,15 +304,16 @@ static int gpio_nrfx_port_toggle_bits(const struct device *port,
313304
const uint32_t clear_mask = (~value) & mask;
314305
int ret;
315306

316-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
307+
ret = pm_device_runtime_get(port);
317308
if (ret < 0) {
318309
return ret;
319310
}
320311

312+
gpio_nrfx_gpd_retain_clear(port, mask);
321313
nrf_gpio_port_out_set(reg, set_mask);
322314
nrf_gpio_port_out_clear(reg, clear_mask);
323-
324-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
315+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
316+
return pm_device_runtime_put(port);
325317
}
326318

327319
#ifdef CONFIG_GPIO_NRFX_INTERRUPT
@@ -480,17 +472,68 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin,
480472
IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_isr, \
481473
NRFX_CONCAT(nrfx_gpiote_, DT_PROP(node_id, instance), _irq_handler), 0);
482474

475+
static int gpio_nrfx_pm_suspend(const struct device *port)
476+
{
477+
#ifdef CONFIG_SOC_NRF54H20_GPD
478+
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
479+
480+
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
481+
return 0;
482+
}
483+
484+
return nrf_gpd_release(NRF_GPD_FAST_ACTIVE1);
485+
#else
486+
ARG_UNUSED(port);
487+
return 0;
488+
#endif
489+
}
490+
491+
static int gpio_nrfx_pm_resume(const struct device *port)
492+
{
493+
#ifdef CONFIG_SOC_NRF54H20_GPD
494+
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
495+
496+
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
497+
return 0;
498+
}
499+
500+
return nrf_gpd_request(NRF_GPD_FAST_ACTIVE1);
501+
#else
502+
ARG_UNUSED(port);
503+
return 0;
504+
#endif
505+
}
506+
507+
static int gpio_nrfx_pm_hook(const struct device *port, enum pm_device_action action)
508+
{
509+
int ret;
510+
511+
switch (action) {
512+
case PM_DEVICE_ACTION_SUSPEND:
513+
ret = gpio_nrfx_pm_suspend(port);
514+
break;
515+
case PM_DEVICE_ACTION_RESUME:
516+
ret = gpio_nrfx_pm_resume(port);
517+
break;
518+
default:
519+
ret = -ENOTSUP;
520+
break;
521+
}
522+
523+
return ret;
524+
}
525+
483526
static int gpio_nrfx_init(const struct device *port)
484527
{
485528
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
486529
nrfx_err_t err;
487530

488531
if (!has_gpiote(cfg)) {
489-
return 0;
532+
goto pm_init;
490533
}
491534

492535
if (nrfx_gpiote_init_check(&cfg->gpiote)) {
493-
return 0;
536+
goto pm_init;
494537
}
495538

496539
err = nrfx_gpiote_init(&cfg->gpiote, 0 /*not used*/);
@@ -503,7 +546,8 @@ static int gpio_nrfx_init(const struct device *port)
503546
DT_FOREACH_STATUS_OKAY(nordic_nrf_gpiote, GPIOTE_IRQ_HANDLER_CONNECT);
504547
#endif /* CONFIG_GPIO_NRFX_INTERRUPT */
505548

506-
return 0;
549+
pm_init:
550+
return pm_device_driver_init(port, gpio_nrfx_pm_hook);
507551
}
508552

509553
static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
@@ -565,8 +609,10 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
565609
\
566610
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
567611
\
612+
PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
613+
\
568614
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
569-
NULL, \
615+
PM_DEVICE_DT_INST_GET(id), \
570616
&gpio_nrfx_p##id##_data, \
571617
&gpio_nrfx_p##id##_cfg, \
572618
PRE_KERNEL_1, \

0 commit comments

Comments
 (0)