Skip to content

Commit 350d66c

Browse files
drivers: power-domain: add nrfs-gdpwr driver and bindings
Add NRFS Global Domain Power Request device driver and hardware bindings. Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
1 parent 941da29 commit 350d66c

File tree

5 files changed

+308
-0
lines changed

5 files changed

+308
-0
lines changed

drivers/power_domain/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO power_domain_gpio.c)
77
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO_MONITOR power_domain_gpio_monitor.c)
88
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_INTEL_ADSP power_domain_intel_adsp.c)
99
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NXP_SCU power_domain_nxp_scu.c)
10+
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRFS_GDPWR power_domain_nrfs_gdpwr.c)
1011
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRFS_SWEXT power_domain_nrfs_swext.c)
1112
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_SOC_PM_STATE power_domain_soc_state_change.c)

drivers/power_domain/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,6 @@ config POWER_DOMAIN_SOC_PM_STATE
100100
PM subsystem transitions in and out certain power states.
101101

102102
rsource "Kconfig.nrfs_swext"
103+
rsource "Kconfig.nrfs_gdpwr"
103104

104105
endif
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config POWER_DOMAIN_NRFS_GDPWR
5+
bool "NRFS Global Domain Power Request driver"
6+
depends on DT_HAS_NORDIC_NRFS_GDPWR_ENABLED
7+
select NRFS
8+
select NRFS_GDPWR_SERVICE_ENABLED
9+
default y
10+
11+
if POWER_DOMAIN_NRFS_GDPWR
12+
13+
config POWER_DOMAIN_NRFS_GDPWR_TIMEOUT_MS
14+
int "GDPWR request timeout in milliseconds"
15+
default 500
16+
17+
endif # POWER_DOMAIN_NRFS_GDPWR
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT nordic_nrfs_gdpwr
8+
9+
#include <zephyr/kernel.h>
10+
#include <zephyr/device.h>
11+
#include <zephyr/pm/device.h>
12+
#include <zephyr/logging/log.h>
13+
14+
#include <nrfs_gdpwr.h>
15+
#include <nrfs_backend_ipc_service.h>
16+
17+
LOG_MODULE_REGISTER(nrfs_gdpwr, CONFIG_POWER_DOMAIN_LOG_LEVEL);
18+
19+
#define MANAGER_REQUEST_TIMEOUT K_MSEC(CONFIG_POWER_DOMAIN_NRFS_GDPWR_TIMEOUT_MS)
20+
21+
static K_SEM_DEFINE(lock_sem, 1, 1);
22+
static K_SEM_DEFINE(req_sem, 0, 1);
23+
static nrfs_gdpwr_evt_type_t req_resp;
24+
static const struct device *const domains[] = {
25+
DT_INST_FOREACH_CHILD_SEP(0, DEVICE_DT_GET, (,))
26+
};
27+
28+
struct domain_data {
29+
bool off;
30+
bool synced;
31+
};
32+
33+
struct domain_config {
34+
gdpwr_power_domain_t domain;
35+
};
36+
37+
static void manager_event_handler(nrfs_gdpwr_evt_t const *evt, void *context)
38+
{
39+
ARG_UNUSED(context);
40+
41+
req_resp = evt->type;
42+
k_sem_give(&req_sem);
43+
}
44+
45+
static void manager_lock(void)
46+
{
47+
if (k_is_pre_kernel()) {
48+
return;
49+
}
50+
51+
(void)k_sem_take(&lock_sem, K_FOREVER);
52+
}
53+
54+
static void manager_unlock(void)
55+
{
56+
if (k_is_pre_kernel()) {
57+
return;
58+
}
59+
60+
k_sem_give(&lock_sem);
61+
}
62+
63+
static int manager_set_domain_locked(gdpwr_power_domain_t domain, bool on)
64+
{
65+
nrfs_err_t err;
66+
gdpwr_request_type_t req = on ? GDPWR_POWER_REQUEST_SET : GDPWR_POWER_REQUEST_CLEAR;
67+
int ret;
68+
69+
err = nrfs_gdpwr_power_request(domain, req, NULL);
70+
if (err != NRFS_SUCCESS) {
71+
LOG_ERR("%s %s", "nrfs gdpwr request", "failed");
72+
return -EIO;
73+
}
74+
75+
ret = k_sem_take(&req_sem, MANAGER_REQUEST_TIMEOUT);
76+
if (ret < 0) {
77+
LOG_ERR("%s %s", "nrfs gdpwr request", "timed out");
78+
return -ETIMEDOUT;
79+
}
80+
81+
if (req_resp != NRFS_GDPWR_REQ_APPLIED) {
82+
LOG_ERR("%s %s", "nrfs gdpwr request", "rejected");
83+
return -EIO;
84+
}
85+
86+
return 0;
87+
}
88+
89+
static int manager_set_domain(const struct device *dev, bool on)
90+
{
91+
struct domain_data *dev_data = dev->data;
92+
const struct domain_config *dev_config = dev->config;
93+
int ret;
94+
95+
manager_lock();
96+
97+
if (dev_data->synced) {
98+
ret = manager_set_domain_locked(dev_config->domain, on);
99+
} else {
100+
ret = 0;
101+
dev_data->off = !on;
102+
}
103+
104+
manager_unlock();
105+
return ret;
106+
}
107+
108+
static int manager_sync_domain_locked(const struct device *dev)
109+
{
110+
struct domain_data *dev_data = dev->data;
111+
const struct domain_config *dev_config = dev->config;
112+
113+
dev_data->synced = true;
114+
115+
if (dev_data->off) {
116+
return manager_set_domain_locked(dev_config->domain, false);
117+
}
118+
119+
return 0;
120+
}
121+
122+
static int manager_sync_domains_locked(void)
123+
{
124+
int ret;
125+
126+
ARRAY_FOR_EACH(domains, i) {
127+
ret = manager_sync_domain_locked(domains[i]);
128+
if (ret) {
129+
break;
130+
}
131+
}
132+
133+
return ret;
134+
}
135+
136+
static int manager_init(void)
137+
{
138+
nrfs_err_t err;
139+
int ret;
140+
141+
err = nrfs_backend_wait_for_connection(K_FOREVER);
142+
if (err != NRFS_SUCCESS) {
143+
LOG_ERR("%s %s", "nrfs backend connection", "failed");
144+
return -EIO;
145+
}
146+
147+
err = nrfs_gdpwr_init(manager_event_handler);
148+
if (err != NRFS_SUCCESS) {
149+
LOG_ERR("%s %s", "nrfs gdpwr init", "failed");
150+
return -EIO;
151+
}
152+
153+
manager_lock();
154+
ret = manager_sync_domains_locked();
155+
manager_unlock();
156+
return ret;
157+
}
158+
159+
SYS_INIT(manager_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
160+
161+
static int domain_pm_suspend(const struct device *dev)
162+
{
163+
return manager_set_domain(dev, false);
164+
}
165+
166+
static int domain_pm_resume(const struct device *dev)
167+
{
168+
return manager_set_domain(dev, true);
169+
}
170+
171+
static int domain_pm_action(const struct device *dev, enum pm_device_action action)
172+
{
173+
int ret;
174+
175+
switch (action) {
176+
case PM_DEVICE_ACTION_SUSPEND:
177+
ret = domain_pm_suspend(dev);
178+
break;
179+
180+
case PM_DEVICE_ACTION_RESUME:
181+
ret = domain_pm_resume(dev);
182+
break;
183+
184+
case PM_DEVICE_ACTION_TURN_OFF:
185+
case PM_DEVICE_ACTION_TURN_ON:
186+
ret = -ENOTSUP;
187+
break;
188+
189+
default:
190+
ret = -EINVAL;
191+
break;
192+
}
193+
194+
return ret;
195+
}
196+
197+
static int domain_init(const struct device *dev)
198+
{
199+
return pm_device_driver_init(dev, domain_pm_action);
200+
}
201+
202+
#define DOMAIN_NODE_SYMNAME(node, sym) \
203+
_CONCAT_4(domain, _, sym, DT_NODE_CHILD_IDX(node))
204+
205+
#define DOMAIN_NODE_TO_GDPWR_ENUM(node) \
206+
_CONCAT(GDPWR_GD_, DT_NODE_FULL_NAME_UPPER_TOKEN(node))
207+
208+
#define DOMAIN_DEFINE(node) \
209+
static struct domain_config DOMAIN_NODE_SYMNAME(node, data); \
210+
static const struct domain_config DOMAIN_NODE_SYMNAME(node, config) = { \
211+
.domain = DOMAIN_NODE_TO_GDPWR_ENUM(node), \
212+
}; \
213+
\
214+
PM_DEVICE_DT_DEFINE(node, domain_pm_action); \
215+
\
216+
DEVICE_DT_DEFINE( \
217+
node, \
218+
domain_init, \
219+
PM_DEVICE_DT_GET(node), \
220+
&DOMAIN_NODE_SYMNAME(node, data), \
221+
&DOMAIN_NODE_SYMNAME(node, config), \
222+
PRE_KERNEL_1, \
223+
0, \
224+
NULL \
225+
);
226+
227+
DT_INST_FOREACH_CHILD(0, DOMAIN_DEFINE)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
Nordic NRFS Global Domain Power Request
6+
7+
The NRFS Global Domain Power Request service manages
8+
global power domains using NRFS.
9+
10+
Each child node represents a global power domain, mapped
11+
by name. The fast-active-0 child node is mapped to the
12+
FAST_ACTIVE_0 global power domain. The nodelabel of each
13+
child node is the node name prepended with "gdpwr",
14+
using underscores.
15+
16+
Example layout:
17+
18+
gdpwr {
19+
compatible = "nordic,nrfs-gdpwr";
20+
status = "disabled";
21+
22+
gdpwr_fast_active_0: fast-active-0 {
23+
#power-domain-cells = <0>;
24+
};
25+
26+
gdpwr_fast_active_1: fast-active-1 {
27+
#power-domain-cells = <0>;
28+
};
29+
30+
gdpwr_fast_main: fast-main {
31+
#power-domain-cells = <0>;
32+
};
33+
34+
gdpwr_slow_active: slow-active {
35+
#power-domain-cells = <0>;
36+
};
37+
38+
gdpwr_slow_main: slow-main {
39+
#power-domain-cells = <0>;
40+
};
41+
};
42+
43+
Example usage:
44+
45+
uart120: uart@8e6000 {
46+
compatible = "nordic,nrf-uarte";
47+
reg = <0x8e6000 0x1000>;
48+
status = "disabled";
49+
power-domains = <&gdpwr_fast_active_1>;
50+
};
51+
52+
compatible: "nordic,nrfs-gdpwr"
53+
54+
include: base.yaml
55+
56+
child-binding:
57+
description: Nordic NRFS Global Power Domain
58+
59+
properties:
60+
"#power-domain-cells":
61+
type: int
62+
const: 0

0 commit comments

Comments
 (0)