Skip to content

Commit 6498408

Browse files
drivers: power_domain: introduce nrfs swext
Introduce NRFS SWEXT (Switch External) device driver and devicetree binding. Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
1 parent a6b0bad commit 6498408

File tree

5 files changed

+241
-0
lines changed

5 files changed

+241
-0
lines changed

drivers/power_domain/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO_MONITOR power_domain_gpio_
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)
1010
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRFS_GDPWR power_domain_nrfs_gdpwr.c)
11+
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)
1213
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_TISCI power_domain_tisci.c)

drivers/power_domain/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,6 @@ config SOC_POWER_DOMAIN_INIT
124124
endif #POWER_DOMAIN_TISCI
125125

126126
rsource "Kconfig.nrfs_gdpwr"
127+
rsource "Kconfig.nrfs_swext"
127128

128129
endif
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config POWER_DOMAIN_NRFS_SWEXT
5+
bool "NRFS SWEXT power domain driver"
6+
depends on DT_HAS_NORDIC_NRFS_SWEXT_ENABLED
7+
select NRFS
8+
select NRFS_SWEXT_SERVICE_ENABLED
9+
default y
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
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_swext
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_swext.h>
15+
#include <nrfs_backend_ipc_service.h>
16+
17+
LOG_MODULE_REGISTER(nrfs_swext, CONFIG_POWER_DOMAIN_LOG_LEVEL);
18+
19+
BUILD_ASSERT(
20+
DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
21+
"multiple instances not supported"
22+
);
23+
24+
struct nrfs_swext_data {
25+
struct k_sem evt_sem;
26+
nrfs_swext_evt_type_t evt;
27+
};
28+
29+
struct nrfs_swext_config {
30+
uint16_t current_limit_ua;
31+
bool enable_power_down_clamp;
32+
};
33+
34+
static void nrfs_swext_driver_evt_handler(nrfs_swext_evt_t const *p_evt, void *context)
35+
{
36+
struct nrfs_swext_data *dev_data = context;
37+
38+
LOG_DBG("evt %u", (uint32_t)p_evt->type);
39+
40+
if (p_evt->type == NRFS_SWEXT_EVT_OVERCURRENT) {
41+
/* Overcurrent is an unrecoverable condition which requires hardware fix */
42+
LOG_ERR("overcurrent");
43+
k_panic();
44+
};
45+
46+
dev_data->evt = p_evt->type;
47+
k_sem_give(&dev_data->evt_sem);
48+
}
49+
50+
static int nrfs_swext_driver_power_down(const struct device *dev)
51+
{
52+
struct nrfs_swext_data *dev_data = dev->data;
53+
const struct nrfs_swext_config *dev_config = dev->config;
54+
nrfs_err_t err;
55+
swext_pd_clamp_t pd_clamp = dev_config->enable_power_down_clamp
56+
? SWEXT_PD_CLAMP_ENABLED
57+
: SWEXT_PD_CLAMP_DISABLED;
58+
59+
err = nrfs_swext_power_down(pd_clamp, dev_data);
60+
if (err != NRFS_SUCCESS) {
61+
LOG_ERR("failed to request power down");
62+
return -ENODEV;
63+
}
64+
65+
(void)k_sem_take(&dev_data->evt_sem, K_FOREVER);
66+
67+
if (dev_data->evt == NRFS_SWEXT_EVT_ENABLED) {
68+
return 0;
69+
}
70+
71+
LOG_ERR("power down request rejected");
72+
return -EIO;
73+
}
74+
75+
static int nrfs_swext_driver_power_up(const struct device *dev)
76+
{
77+
struct nrfs_swext_data *dev_data = dev->data;
78+
const struct nrfs_swext_config *dev_config = dev->config;
79+
nrfs_err_t err;
80+
uint8_t load_current;
81+
82+
load_current = nrfs_swext_load_current_to_raw(dev_config->current_limit_ua);
83+
err = nrfs_swext_power_up(load_current, dev_data);
84+
if (err != NRFS_SUCCESS) {
85+
LOG_ERR("failed to request power up");
86+
return -ENODEV;
87+
}
88+
89+
(void)k_sem_take(&dev_data->evt_sem, K_FOREVER);
90+
91+
if (dev_data->evt == NRFS_SWEXT_EVT_ENABLED) {
92+
return 0;
93+
}
94+
95+
LOG_ERR("power up request rejected");
96+
return -EIO;
97+
}
98+
99+
#if IS_ENABLED(CONFIG_DEVICE_DEPS) && IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN)
100+
static void nrfs_swext_driver_notify_children(const struct device *dev,
101+
enum pm_device_action action)
102+
{
103+
pm_device_children_action_run(dev, action, NULL);
104+
}
105+
#else
106+
static void nrfs_swext_driver_notify_children(const struct device *dev,
107+
enum pm_device_action action)
108+
{
109+
ARG_UNUSED(dev);
110+
ARG_UNUSED(action);
111+
}
112+
#endif
113+
114+
static int nrfs_swext_driver_suspend(const struct device *dev)
115+
{
116+
int ret;
117+
118+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_OFF);
119+
120+
ret = nrfs_swext_driver_power_down(dev);
121+
if (ret) {
122+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON);
123+
}
124+
125+
return ret;
126+
}
127+
128+
static int nrfs_swext_driver_resume(const struct device *dev)
129+
{
130+
int ret;
131+
132+
ret = nrfs_swext_driver_power_up(dev);
133+
if (ret == 0) {
134+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON);
135+
}
136+
137+
return ret;
138+
}
139+
140+
static int nrfs_swext_driver_pm_action(const struct device *dev,
141+
enum pm_device_action action)
142+
{
143+
int ret;
144+
145+
switch (action) {
146+
case PM_DEVICE_ACTION_SUSPEND:
147+
ret = nrfs_swext_driver_suspend(dev);
148+
break;
149+
150+
case PM_DEVICE_ACTION_RESUME:
151+
ret = nrfs_swext_driver_resume(dev);
152+
break;
153+
154+
default:
155+
ret = -ENOTSUP;
156+
break;
157+
};
158+
159+
return ret;
160+
}
161+
162+
static int nrfs_swext_driver_init(const struct device *dev)
163+
{
164+
struct nrfs_swext_data *dev_data = dev->data;
165+
nrfs_err_t err;
166+
167+
LOG_DBG("waiting for nrfs backend connected");
168+
err = nrfs_backend_wait_for_connection(K_FOREVER);
169+
if (err != NRFS_SUCCESS) {
170+
LOG_ERR("nrfs backend not connected");
171+
return -ENODEV;
172+
}
173+
174+
err = nrfs_swext_init(nrfs_swext_driver_evt_handler);
175+
if (err != NRFS_SUCCESS) {
176+
LOG_ERR("failed to init swext service");
177+
return -ENODEV;
178+
}
179+
180+
k_sem_init(&dev_data->evt_sem, 0, 1);
181+
return pm_device_driver_init(dev, nrfs_swext_driver_pm_action);
182+
}
183+
184+
PM_DEVICE_DT_INST_DEFINE(0, nrfs_swext_driver_pm_action);
185+
186+
BUILD_ASSERT(DT_INST_PROP(0, max_current_ua) <= UINT16_MAX);
187+
BUILD_ASSERT(DT_INST_PROP(0, current_limit_ua) <= DT_INST_PROP(0, max_current_ua));
188+
189+
static struct nrfs_swext_data data0;
190+
static const struct nrfs_swext_config config0 = {
191+
.current_limit_ua = DT_INST_PROP(0, current_limit_ua),
192+
.enable_power_down_clamp = DT_INST_PROP(0, power_down_clamp),
193+
};
194+
195+
DEVICE_DT_INST_DEFINE(
196+
0,
197+
nrfs_swext_driver_init,
198+
PM_DEVICE_DT_INST_GET(0),
199+
&data0,
200+
&config0,
201+
POST_KERNEL,
202+
UTIL_INC(CONFIG_NRFS_BACKEND_IPC_SERVICE_INIT_PRIO),
203+
NULL
204+
);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright 2025 Nordic Semiconductor
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Nordic NRFS SWEXT power domain
5+
6+
compatible: "nordic,nrfs-swext"
7+
8+
include: power-domain.yaml
9+
10+
properties:
11+
"#power-domain-cells":
12+
const: 0
13+
14+
max-current-ua:
15+
type: int
16+
description: Maxmimum supported current in microamps.
17+
required: true
18+
19+
current-limit-ua:
20+
type: int
21+
description: Maxmimum allowed current in microamps.
22+
required: true
23+
24+
power-down-clamp:
25+
type: boolean
26+
description: Enable ground clamp on output when powered down.

0 commit comments

Comments
 (0)