11
11
#include <zephyr/drivers/gpio.h>
12
12
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
13
13
#include <zephyr/irq.h>
14
+ #include <zephyr/pm/device.h>
15
+ #include <zephyr/pm/device_runtime.h>
14
16
15
17
#include <zephyr/drivers/gpio/gpio_utils.h>
16
18
@@ -62,53 +64,37 @@ static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags)
62
64
return NRF_GPIO_PIN_NOPULL;
63
65
}
64
66
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)
66
68
{
67
69
#ifdef CONFIG_SOC_NRF54H20_GPD
68
70
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
69
71
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;
81
74
}
75
+
76
+ nrf_gpio_port_retain_enable(cfg->port, mask);
82
77
#else
83
78
ARG_UNUSED(port);
84
79
ARG_UNUSED(mask);
85
80
ARG_UNUSED(flags);
86
81
#endif
87
-
88
- return 0;
89
82
}
90
83
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)
92
85
{
93
86
#ifdef CONFIG_SOC_NRF54H20_GPD
94
87
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
95
88
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;
105
91
}
92
+
93
+ nrf_gpio_port_retain_disable(cfg->port, mask);
106
94
#else
107
95
ARG_UNUSED(port);
108
96
ARG_UNUSED(mask);
109
97
#endif
110
-
111
- return 0;
112
98
}
113
99
114
100
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,
152
138
return -EINVAL;
153
139
}
154
140
155
- ret = gpio_nrfx_gpd_retain_clear (port, BIT(pin) );
141
+ ret = pm_device_runtime_get (port);
156
142
if (ret < 0) {
157
143
return ret;
158
144
}
159
145
146
+ gpio_nrfx_gpd_retain_clear(port, BIT(pin));
147
+
160
148
if (flags & GPIO_OUTPUT_INIT_HIGH) {
161
149
nrf_gpio_port_out_set(cfg->port, BIT(pin));
162
150
} 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,
237
225
}
238
226
239
227
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) ;
242
230
}
243
231
244
232
#ifdef CONFIG_GPIO_GET_CONFIG
@@ -331,15 +319,16 @@ static int gpio_nrfx_port_set_masked_raw(const struct device *port,
331
319
const uint32_t set_mask = value & mask;
332
320
const uint32_t clear_mask = (~set_mask) & mask;
333
321
334
- ret = gpio_nrfx_gpd_retain_clear (port, mask );
322
+ ret = pm_device_runtime_get (port);
335
323
if (ret < 0) {
336
324
return ret;
337
325
}
338
326
327
+ gpio_nrfx_gpd_retain_clear(port, mask);
339
328
nrf_gpio_port_out_set(reg, set_mask);
340
329
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);
343
332
}
344
333
345
334
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,
348
337
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
349
338
int ret;
350
339
351
- ret = gpio_nrfx_gpd_retain_clear (port, mask );
340
+ ret = pm_device_runtime_get (port);
352
341
if (ret < 0) {
353
342
return ret;
354
343
}
355
344
345
+ gpio_nrfx_gpd_retain_clear(port, mask);
356
346
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);
359
349
}
360
350
361
351
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,
364
354
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
365
355
int ret;
366
356
367
- ret = gpio_nrfx_gpd_retain_clear (port, mask );
357
+ ret = pm_device_runtime_get (port);
368
358
if (ret < 0) {
369
359
return ret;
370
360
}
371
361
362
+ gpio_nrfx_gpd_retain_clear(port, mask);
372
363
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);
375
366
}
376
367
377
368
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,
383
374
const uint32_t clear_mask = (~value) & mask;
384
375
int ret;
385
376
386
- ret = gpio_nrfx_gpd_retain_clear (port, mask );
377
+ ret = pm_device_runtime_get (port);
387
378
if (ret < 0) {
388
379
return ret;
389
380
}
390
381
382
+ gpio_nrfx_gpd_retain_clear(port, mask);
391
383
nrf_gpio_port_out_set(reg, set_mask);
392
384
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);
395
387
}
396
388
397
389
#ifdef CONFIG_GPIO_NRFX_INTERRUPT
@@ -550,17 +542,68 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin,
550
542
IRQ_CONNECT(DT_IRQN(node_id), DT_IRQ(node_id, priority), nrfx_isr, \
551
543
NRFX_CONCAT(nrfx_gpiote_, DT_PROP(node_id, instance), _irq_handler), 0);
552
544
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
+
553
596
static int gpio_nrfx_init(const struct device *port)
554
597
{
555
598
const struct gpio_nrfx_cfg *cfg = get_port_cfg(port);
556
599
nrfx_err_t err;
557
600
558
601
if (!has_gpiote(cfg)) {
559
- return 0 ;
602
+ goto pm_init ;
560
603
}
561
604
562
605
if (nrfx_gpiote_init_check(&cfg->gpiote)) {
563
- return 0 ;
606
+ goto pm_init ;
564
607
}
565
608
566
609
err = nrfx_gpiote_init(&cfg->gpiote, 0 /*not used*/);
@@ -573,7 +616,8 @@ static int gpio_nrfx_init(const struct device *port)
573
616
DT_FOREACH_STATUS_OKAY(nordic_nrf_gpiote, GPIOTE_IRQ_HANDLER_CONNECT);
574
617
#endif /* CONFIG_GPIO_NRFX_INTERRUPT */
575
618
576
- return 0;
619
+ pm_init:
620
+ return pm_device_driver_init(port, gpio_nrfx_pm_hook);
577
621
}
578
622
579
623
static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
@@ -638,8 +682,10 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = {
638
682
\
639
683
static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \
640
684
\
685
+ PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \
686
+ \
641
687
DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \
642
- NULL, \
688
+ PM_DEVICE_DT_INST_GET(id), \
643
689
&gpio_nrfx_p##id##_data, \
644
690
&gpio_nrfx_p##id##_cfg, \
645
691
PRE_KERNEL_1, \
0 commit comments