Skip to content

Commit 1927c18

Browse files
[nrf fromtree] drivers: power_domain: introduce nrfs_swext device driver
Introduce nrfx_swext device driver for NRFS SWEXT power domain device. Signed-off-by: Bjarki Arge Andreasen <[email protected]> (cherry picked from commit 5db84c7)
1 parent cb567a1 commit 1927c18

File tree

4 files changed

+211
-0
lines changed

4 files changed

+211
-0
lines changed

drivers/power_domain/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ 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_NRF_GPIO_PAD_GROUP power_domain_nrf_gpio_pad_group.c)
1213
zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_SOC_PM_STATE power_domain_soc_state_change.c)
1314
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,6 +124,7 @@ config SOC_POWER_DOMAIN_INIT
124124
endif #POWER_DOMAIN_TISCI
125125

126126
rsource "Kconfig.nrfs_gdpwr"
127+
rsource "Kconfig.nrfs_swext"
127128
rsource "Kconfig.nrf_gpio_pad_group"
128129
rsource "Kconfig.silabs_siwx91x"
129130

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: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
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+
const struct nrfs_swext_config *dev_config = dev->config;
53+
nrfs_err_t err;
54+
swext_pd_clamp_t pd_clamp = dev_config->enable_power_down_clamp
55+
? SWEXT_PD_CLAMP_ENABLED
56+
: SWEXT_PD_CLAMP_DISABLED;
57+
58+
/*
59+
* Power down request does not respond with an event.
60+
* Set context to NULL, fire and forget.
61+
*/
62+
err = nrfs_swext_power_down(pd_clamp, NULL);
63+
if (err != NRFS_SUCCESS) {
64+
LOG_ERR("failed to request power down");
65+
return -ENODEV;
66+
}
67+
68+
return 0;
69+
}
70+
71+
static int nrfs_swext_driver_power_up(const struct device *dev)
72+
{
73+
struct nrfs_swext_data *dev_data = dev->data;
74+
const struct nrfs_swext_config *dev_config = dev->config;
75+
nrfs_err_t err;
76+
uint8_t load_current;
77+
78+
load_current = nrfs_swext_load_current_to_raw(dev_config->current_limit_ua);
79+
err = nrfs_swext_power_up(load_current, dev_data);
80+
if (err != NRFS_SUCCESS) {
81+
LOG_ERR("failed to request power up");
82+
return -ENODEV;
83+
}
84+
85+
(void)k_sem_take(&dev_data->evt_sem, K_FOREVER);
86+
87+
if (dev_data->evt == NRFS_SWEXT_EVT_ENABLED) {
88+
return 0;
89+
}
90+
91+
LOG_ERR("power up request rejected");
92+
return -EIO;
93+
}
94+
95+
#if IS_ENABLED(CONFIG_DEVICE_DEPS) && IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN)
96+
static void nrfs_swext_driver_notify_children(const struct device *dev,
97+
enum pm_device_action action)
98+
{
99+
pm_device_children_action_run(dev, action, NULL);
100+
}
101+
#else
102+
static void nrfs_swext_driver_notify_children(const struct device *dev,
103+
enum pm_device_action action)
104+
{
105+
ARG_UNUSED(dev);
106+
ARG_UNUSED(action);
107+
}
108+
#endif
109+
110+
static int nrfs_swext_driver_suspend(const struct device *dev)
111+
{
112+
int ret;
113+
114+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_OFF);
115+
116+
ret = nrfs_swext_driver_power_down(dev);
117+
if (ret) {
118+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON);
119+
}
120+
121+
return ret;
122+
}
123+
124+
static int nrfs_swext_driver_resume(const struct device *dev)
125+
{
126+
int ret;
127+
128+
ret = nrfs_swext_driver_power_up(dev);
129+
if (ret == 0) {
130+
nrfs_swext_driver_notify_children(dev, PM_DEVICE_ACTION_TURN_ON);
131+
}
132+
133+
return ret;
134+
}
135+
136+
static int nrfs_swext_driver_pm_action(const struct device *dev,
137+
enum pm_device_action action)
138+
{
139+
int ret;
140+
141+
switch (action) {
142+
case PM_DEVICE_ACTION_SUSPEND:
143+
ret = nrfs_swext_driver_suspend(dev);
144+
break;
145+
146+
case PM_DEVICE_ACTION_RESUME:
147+
ret = nrfs_swext_driver_resume(dev);
148+
break;
149+
150+
default:
151+
ret = -ENOTSUP;
152+
break;
153+
};
154+
155+
return ret;
156+
}
157+
158+
static int nrfs_swext_driver_init(const struct device *dev)
159+
{
160+
struct nrfs_swext_data *dev_data = dev->data;
161+
nrfs_err_t err;
162+
163+
LOG_DBG("waiting for nrfs backend connected");
164+
err = nrfs_backend_wait_for_connection(K_FOREVER);
165+
if (err != NRFS_SUCCESS) {
166+
LOG_ERR("nrfs backend not connected");
167+
return -ENODEV;
168+
}
169+
170+
err = nrfs_swext_init(nrfs_swext_driver_evt_handler);
171+
if (err != NRFS_SUCCESS) {
172+
LOG_ERR("failed to init swext service");
173+
return -ENODEV;
174+
}
175+
176+
k_sem_init(&dev_data->evt_sem, 0, 1);
177+
return pm_device_driver_init(dev, nrfs_swext_driver_pm_action);
178+
}
179+
180+
PM_DEVICE_DT_INST_DEFINE(0, nrfs_swext_driver_pm_action);
181+
182+
BUILD_ASSERT(DT_INST_PROP(0, max_current_ua) <= UINT16_MAX);
183+
BUILD_ASSERT(DT_INST_PROP(0, current_limit_ua) <= DT_INST_PROP(0, max_current_ua));
184+
185+
static struct nrfs_swext_data data0;
186+
static const struct nrfs_swext_config config0 = {
187+
.current_limit_ua = DT_INST_PROP(0, current_limit_ua),
188+
.enable_power_down_clamp = DT_INST_PROP(0, power_down_clamp),
189+
};
190+
191+
DEVICE_DT_INST_DEFINE(
192+
0,
193+
nrfs_swext_driver_init,
194+
PM_DEVICE_DT_INST_GET(0),
195+
&data0,
196+
&config0,
197+
POST_KERNEL,
198+
UTIL_INC(CONFIG_NRFS_BACKEND_IPC_SERVICE_INIT_PRIO),
199+
NULL
200+
);

0 commit comments

Comments
 (0)