Skip to content

Commit c4d475c

Browse files
bjarki-andreasenkartben
authored andcommitted
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 <bjarki.andreasen@nordicsemi.no>
1 parent d411288 commit c4d475c

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
@@ -331,15 +319,16 @@ static int gpio_nrfx_port_set_masked_raw(const struct device *port,
331319
const uint32_t set_mask = value & mask;
332320
const uint32_t clear_mask = (~set_mask) & mask;
333321

334-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
322+
ret = pm_device_runtime_get(port);
335323
if (ret < 0) {
336324
return ret;
337325
}
338326

327+
gpio_nrfx_gpd_retain_clear(port, mask);
339328
nrf_gpio_port_out_set(reg, set_mask);
340329
nrf_gpio_port_out_clear(reg, clear_mask);
341-
342-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
330+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
331+
return pm_device_runtime_put(port);
343332
}
344333

345334
static int gpio_nrfx_port_set_bits_raw(const struct device *port,
@@ -348,14 +337,15 @@ static int gpio_nrfx_port_set_bits_raw(const struct device *port,
348337
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
349338
int ret;
350339

351-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
340+
ret = pm_device_runtime_get(port);
352341
if (ret < 0) {
353342
return ret;
354343
}
355344

345+
gpio_nrfx_gpd_retain_clear(port, mask);
356346
nrf_gpio_port_out_set(reg, mask);
357-
358-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
347+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
348+
return pm_device_runtime_put(port);
359349
}
360350

361351
static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
@@ -364,14 +354,15 @@ static int gpio_nrfx_port_clear_bits_raw(const struct device *port,
364354
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
365355
int ret;
366356

367-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
357+
ret = pm_device_runtime_get(port);
368358
if (ret < 0) {
369359
return ret;
370360
}
371361

362+
gpio_nrfx_gpd_retain_clear(port, mask);
372363
nrf_gpio_port_out_clear(reg, mask);
373-
374-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
364+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
365+
return pm_device_runtime_put(port);
375366
}
376367

377368
static int gpio_nrfx_port_toggle_bits(const struct device *port,
@@ -383,15 +374,16 @@ static int gpio_nrfx_port_toggle_bits(const struct device *port,
383374
const uint32_t clear_mask = (~value) & mask;
384375
int ret;
385376

386-
ret = gpio_nrfx_gpd_retain_clear(port, mask);
377+
ret = pm_device_runtime_get(port);
387378
if (ret < 0) {
388379
return ret;
389380
}
390381

382+
gpio_nrfx_gpd_retain_clear(port, mask);
391383
nrf_gpio_port_out_set(reg, set_mask);
392384
nrf_gpio_port_out_clear(reg, clear_mask);
393-
394-
return gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
385+
gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT);
386+
return pm_device_runtime_put(port);
395387
}
396388

397389
#ifdef CONFIG_GPIO_NRFX_INTERRUPT
@@ -550,17 +542,68 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin,
550542
IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_isr, \
551543
NRFX_CONCAT(nrfx_gpiote_, DT_PROP(node_id, instance), _irq_handler), 0);
552544

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

558601
if (!has_gpiote(cfg)) {
559-
return 0;
602+
goto pm_init;
560603
}
561604

562605
if (nrfx_gpiote_init_check(&cfg->gpiote)) {
563-
return 0;
606+
goto pm_init;
564607
}
565608

566609
err = nrfx_gpiote_init(&cfg->gpiote, 0 /*not used*/);
@@ -573,7 +616,8 @@ static int gpio_nrfx_init(const struct device *port)
573616
DT_FOREACH_STATUS_OKAY(nordic_nrf_gpiote, GPIOTE_IRQ_HANDLER_CONNECT);
574617
#endif /* CONFIG_GPIO_NRFX_INTERRUPT */
575618

576-
return 0;
619+
pm_init:
620+
return pm_device_driver_init(port, gpio_nrfx_pm_hook);
577621
}
578622

579623
static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
@@ -638,8 +682,10 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
638682
\
639683
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
640684
\
685+
PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
686+
\
641687
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
642-
NULL, \
688+
PM_DEVICE_DT_INST_GET(id), \
643689
&gpio_nrfx_p##id##_data, \
644690
&gpio_nrfx_p##id##_cfg, \
645691
PRE_KERNEL_1, \

0 commit comments

Comments
 (0)