Skip to content

Commit 941da29

Browse files
drivers: power_domain: add nrfs_swext driver
Add power domain driver for nordic nrfs swext power domain. Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
1 parent 774f9a8 commit 941da29

File tree

4 files changed

+201
-0
lines changed

4 files changed

+201
-0
lines changed

drivers/power_domain/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ 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_SWEXT power_domain_nrfs_swext.c)
1011
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_SOC_PM_STATE power_domain_soc_state_change.c)

drivers/power_domain/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,6 @@ config POWER_DOMAIN_SOC_PM_STATE
9999
Generic power domain control to turn on/off devices when the
100100
PM subsystem transitions in and out certain power states.
101101

102+
rsource "Kconfig.nrfs_swext"
103+
102104
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: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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_suspend(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_resume(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_pm_action(const struct device *dev,
115+
enum pm_device_action action)
116+
{
117+
int ret;
118+
119+
switch (action) {
120+
case PM_DEVICE_ACTION_SUSPEND:
121+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_OFF);
122+
ret = nrfs_swext_driver_suspend(dev);
123+
if (ret) {
124+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON);
125+
break;
126+
}
127+
128+
break;
129+
130+
case PM_DEVICE_ACTION_RESUME:
131+
ret = nrfs_swext_driver_resume(dev);
132+
if (ret) {
133+
break;
134+
}
135+
136+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON);
137+
break;
138+
139+
default:
140+
ret = -ENOTSUP;
141+
break;
142+
};
143+
144+
return ret;
145+
}
146+
147+
static int nrfs_swext_driver_init(const struct device *dev)
148+
{
149+
struct nrfs_swext_data *dev_data = dev->data;
150+
nrfs_err_t err;
151+
152+
LOG_DBG("waiting for nrfs backend connected");
153+
err = nrfs_backend_wait_for_connection(K_FOREVER);
154+
if (err != NRFS_SUCCESS) {
155+
LOG_ERR("nrfs backend not connected");
156+
return -ENODEV;
157+
}
158+
159+
err = nrfs_swext_init(nrfs_swext_driver_evt_handler);
160+
if (err != NRFS_SUCCESS) {
161+
LOG_ERR("failed to init swext service");
162+
return -ENODEV;
163+
}
164+
165+
k_sem_init(&dev_data->evt_sem, 0, 1);
166+
return pm_device_driver_init(dev, nrfs_swext_driver_pm_action);
167+
}
168+
169+
PM_DEVICE_DT_INST_DEFINE(0, nrfs_swext_driver_pm_action);
170+
171+
BUILD_ASSERT(DT_INST_PROP(0, max_current_ua) <= UINT16_MAX);
172+
BUILD_ASSERT(DT_INST_PROP(0, current_limit_ua) <= DT_INST_PROP(0, max_current_ua));
173+
174+
static struct nrfs_swext_data data0;
175+
static const struct nrfs_swext_config config0 = {
176+
.current_limit_ua = DT_INST_PROP(0, current_limit_ua),
177+
.enable_power_down_clamp = DT_INST_PROP(0, power_down_clamp),
178+
};
179+
180+
DEVICE_DT_INST_DEFINE(
181+
0,
182+
nrfs_swext_driver_init,
183+
PM_DEVICE_DT_INST_GET(0),
184+
&data0,
185+
&config0,
186+
POST_KERNEL,
187+
UTIL_INC(CONFIG_NRFS_BACKEND_IPC_SERVICE_INIT_PRIO),
188+
NULL
189+
);

0 commit comments

Comments
 (0)