Skip to content

Commit 40be693

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 e96bf44 commit 40be693

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
#ifdef CONFIG_GPIO_GET_CONFIG
@@ -328,15 +316,16 @@ static int gpio_nrfx_port_set_masked_raw(const struct device *port,
328316
const uint32_t set_mask = value & mask;
329317
const uint32_t clear_mask = (~set_mask) & mask;
330318

331-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
319+
ret = pm_device_runtime_get(port);
332320
if (ret < 0) {
333321
return ret;
334322
}
335323

324+
gpio_nrfx_gpd_retain_clear(port, mask);
336325
nrf_gpio_port_out_set(reg, set_mask);
337326
nrf_gpio_port_out_clear(reg, clear_mask);
338-
339-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
327+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
328+
return pm_device_runtime_put(port);
340329
}
341330

342331
static int gpio_nrfx_port_set_bits_raw(const struct device *port,
@@ -345,14 +334,15 @@ static int gpio_nrfx_port_set_bits_raw(const struct device *port,
345334
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
346335
int ret;
347336

348-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
337+
ret = pm_device_runtime_get(port);
349338
if (ret < 0) {
350339
return ret;
351340
}
352341

342+
gpio_nrfx_gpd_retain_clear(port, mask);
353343
nrf_gpio_port_out_set(reg, mask);
354-
355-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
344+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
345+
return pm_device_runtime_put(port);
356346
}
357347

358348
static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
@@ -361,14 +351,15 @@ static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
361351
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
362352
int ret;
363353

364-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
354+
ret = pm_device_runtime_get(port);
365355
if (ret < 0) {
366356
return ret;
367357
}
368358

359+
gpio_nrfx_gpd_retain_clear(port, mask);
369360
nrf_gpio_port_out_clear(reg, mask);
370-
371-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
361+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
362+
return pm_device_runtime_put(port);
372363
}
373364

374365
static int gpio_nrfx_port_toggle_bits(const struct device *port,
@@ -380,15 +371,16 @@ static int gpio_nrfx_port_toggle_bits(const struct device *port,
380371
const uint32_t clear_mask = (~value) & mask;
381372
int ret;
382373

383-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
374+
ret = pm_device_runtime_get(port);
384375
if (ret < 0) {
385376
return ret;
386377
}
387378

379+
gpio_nrfx_gpd_retain_clear(port, mask);
388380
nrf_gpio_port_out_set(reg, set_mask);
389381
nrf_gpio_port_out_clear(reg, clear_mask);
390-
391-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
382+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
383+
return pm_device_runtime_put(port);
392384
}
393385

394386
#ifdef CONFIG_GPIO_NRFX_INTERRUPT
@@ -547,17 +539,68 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin,
547539
IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_isr, \
548540
NRFX_CONCAT(nrfx_gpiote_, DT_PROP(node_id, instance), _irq_handler), 0);
549541

542+
static int gpio_nrfx_pm_suspend(const struct device *port)
543+
{
544+
#ifdef CONFIG_SOC_NRF54H20_GPD
545+
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
546+
547+
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
548+
return 0;
549+
}
550+
551+
return nrf_gpd_release(NRF_GPD_FAST_ACTIVE1);
552+
#else
553+
ARG_UNUSED(port);
554+
return 0;
555+
#endif
556+
}
557+
558+
static int gpio_nrfx_pm_resume(const struct device *port)
559+
{
560+
#ifdef CONFIG_SOC_NRF54H20_GPD
561+
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
562+
563+
if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) {
564+
return 0;
565+
}
566+
567+
return nrf_gpd_request(NRF_GPD_FAST_ACTIVE1);
568+
#else
569+
ARG_UNUSED(port);
570+
return 0;
571+
#endif
572+
}
573+
574+
static int gpio_nrfx_pm_hook(const struct device *port, enum pm_device_action action)
575+
{
576+
int ret;
577+
578+
switch (action) {
579+
case PM_DEVICE_ACTION_SUSPEND:
580+
ret = gpio_nrfx_pm_suspend(port);
581+
break;
582+
case PM_DEVICE_ACTION_RESUME:
583+
ret = gpio_nrfx_pm_resume(port);
584+
break;
585+
default:
586+
ret = -ENOTSUP;
587+
break;
588+
}
589+
590+
return ret;
591+
}
592+
550593
static int gpio_nrfx_init(const struct device *port)
551594
{
552595
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
553596
nrfx_err_t err;
554597

555598
if (!has_gpiote(cfg)) {
556-
return 0;
599+
goto pm_init;
557600
}
558601

559602
if (nrfx_gpiote_init_check(&cfg->gpiote)) {
560-
return 0;
603+
goto pm_init;
561604
}
562605

563606
err = nrfx_gpiote_init(&cfg->gpiote, 0 /*not used*/);
@@ -570,7 +613,8 @@ static int gpio_nrfx_init(const struct device *port)
570613
DT_FOREACH_STATUS_OKAY(nordic_nrf_gpiote, GPIOTE_IRQ_HANDLER_CONNECT);
571614
#endif /* CONFIG_GPIO_NRFX_INTERRUPT */
572615

573-
return 0;
616+
pm_init:
617+
return pm_device_driver_init(port, gpio_nrfx_pm_hook);
574618
}
575619

576620
static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
@@ -635,8 +679,10 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
635679
\
636680
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
637681
\
682+
PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
683+
\
638684
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
639-
NULL, \
685+
PM_DEVICE_DT_INST_GET(id), \
640686
&gpio_nrfx_p##id##_data, \
641687
&gpio_nrfx_p##id##_cfg, \
642688
PRE_KERNEL_1, \

0 commit comments

Comments
 (0)