Skip to content

Commit 484e54a

Browse files
committed
[nrf fromlist] drivers: clock_control: Separated nrf xo24m shim from nrf clock shim.
Separated clock_control_nrf_xo24m shim from clock_control_nrf shim. Upstream PR #: 98684 Signed-off-by: Michal Frankiewicz <[email protected]>
1 parent 18bd06f commit 484e54a

File tree

9 files changed

+392
-0
lines changed

9 files changed

+392
-0
lines changed

boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp.dts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,7 @@
150150
&lfclk {
151151
status = "okay";
152152
};
153+
154+
&xo24m {
155+
status = "okay";
156+
};

boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@
138138
status = "okay";
139139
};
140140

141+
&xo24m {
142+
status = "okay";
143+
};
144+
141145
&ieee802154 {
142146
status = "okay";
143147
};

drivers/clock_control/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HFCLK clock_cont
6464
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_XO clock_control_nrf_xo.c)
6565
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_LFCLK clock_control_nrf_lfclk.c)
6666
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HFCLK192M clock_control_nrf_hfclk192m.c)
67+
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_XO24M clock_control_nrf_xo24m.c)
6768
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_COMMON clock_control_nrf_common.c)
6869
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL60X clock_control_bl60x.c)
6970
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL61X clock_control_bl61x.c)

drivers/clock_control/Kconfig.nrf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,12 @@ config CLOCK_CONTROL_NRF_HFCLK192M
350350
select CLOCK_CONTROL_NRF_COMMON
351351
default y
352352

353+
config CLOCK_CONTROL_NRF_XO24M
354+
bool "NRF XO242M driver support"
355+
depends on DT_HAS_NORDIC_NRF_CLOCK_XO24M_ENABLED
356+
select CLOCK_CONTROL_NRF_COMMON
357+
default y
358+
353359
config CLOCK_CONTROL_NRF_AUXPLL
354360
bool "nRF Auxiliary PLL driver"
355361
default y
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
/*
2+
* Copyright (c) 2016-2025 Nordic Semiconductor ASA
3+
* Copyright (c) 2016 Vinayak Kariappa Chettimada
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#include <soc.h>
9+
#include <zephyr/sys/onoff.h>
10+
#include <zephyr/drivers/clock_control.h>
11+
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
12+
#include "clock_control_nrf_common.h"
13+
#include <nrfx_clock_xo24m.h>
14+
#include <zephyr/logging/log.h>
15+
#include <zephyr/shell/shell.h>
16+
#include <zephyr/irq.h>
17+
18+
LOG_MODULE_REGISTER(clock_control_xo24m, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
19+
20+
#define DT_DRV_COMPAT nordic_nrf_clock_xo24m
21+
22+
#define CLOCK_DEVICE_XO24M DEVICE_DT_GET(DT_NODELABEL(xo24m))
23+
24+
#define CTX_ONOFF BIT(6)
25+
#define CTX_API BIT(7)
26+
#define CTX_MASK (CTX_ONOFF | CTX_API)
27+
28+
#define STATUS_MASK 0x7
29+
#define GET_STATUS(flags) (flags & STATUS_MASK)
30+
#define GET_CTX(flags) (flags & CTX_MASK)
31+
32+
/* Helper logging macros which prepends subsys name to the log. */
33+
#ifdef CONFIG_LOG
34+
#define CLOCK_LOG(lvl, dev, ...) \
35+
LOG_##lvl("%s: " GET_ARG_N(1, __VA_ARGS__), \
36+
"xo24m" \
37+
COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__),\
38+
(), (, GET_ARGS_LESS_N(1, __VA_ARGS__))))
39+
#else
40+
#define CLOCK_LOG(...)
41+
#endif
42+
43+
#define ERR(dev, ...) CLOCK_LOG(ERR, dev, __VA_ARGS__)
44+
#define WRN(dev, ...) CLOCK_LOG(WRN, dev, __VA_ARGS__)
45+
#define INF(dev, ...) CLOCK_LOG(INF, dev, __VA_ARGS__)
46+
#define DBG(dev, ...) CLOCK_LOG(DBG, dev, __VA_ARGS__)
47+
48+
typedef void (*clk_ctrl_func_t)(void);
49+
50+
typedef struct {
51+
struct onoff_manager mgr;
52+
clock_control_cb_t cb;
53+
void *user_data;
54+
uint32_t flags;
55+
} xo24m_data_t;
56+
57+
typedef struct {
58+
clk_ctrl_func_t start; /* Clock start function */
59+
clk_ctrl_func_t stop; /* Clock stop function */
60+
} xo24m_config_t;
61+
62+
static int set_off_state(uint32_t *flags, uint32_t ctx)
63+
{
64+
int err = 0;
65+
unsigned int key = irq_lock();
66+
uint32_t current_ctx = GET_CTX(*flags);
67+
68+
if ((current_ctx != 0) && (current_ctx != ctx)) {
69+
err = -EPERM;
70+
} else {
71+
*flags = CLOCK_CONTROL_STATUS_OFF;
72+
}
73+
74+
irq_unlock(key);
75+
76+
return err;
77+
}
78+
79+
static int set_starting_state(uint32_t *flags, uint32_t ctx)
80+
{
81+
int err = 0;
82+
unsigned int key = irq_lock();
83+
uint32_t current_ctx = GET_CTX(*flags);
84+
85+
if ((*flags & (STATUS_MASK)) == CLOCK_CONTROL_STATUS_OFF) {
86+
*flags = CLOCK_CONTROL_STATUS_STARTING | ctx;
87+
} else if (current_ctx != ctx) {
88+
err = -EPERM;
89+
} else {
90+
err = -EALREADY;
91+
}
92+
93+
irq_unlock(key);
94+
95+
return err;
96+
}
97+
98+
static void set_on_state(uint32_t *flags)
99+
{
100+
unsigned int key = irq_lock();
101+
102+
*flags = CLOCK_CONTROL_STATUS_ON | GET_CTX(*flags);
103+
irq_unlock(key);
104+
}
105+
106+
static void clkstarted_handle(const struct device *dev)
107+
{
108+
clock_control_cb_t callback = ((xo24m_data_t *)dev->data)->cb;
109+
void *user_data = ((xo24m_data_t *)dev->data)->user_data;
110+
111+
((xo24m_data_t *)dev->data)->cb = NULL;
112+
set_on_state(&((xo24m_data_t *)dev->data)->flags);
113+
DBG(dev, "Clock started");
114+
115+
if (callback) {
116+
callback(dev, NULL, user_data);
117+
}
118+
}
119+
120+
static void xo24m_start(void)
121+
{
122+
nrfx_clock_xo24m_start();
123+
}
124+
125+
static void xo24m_stop(void)
126+
{
127+
nrfx_clock_xo24m_stop();
128+
}
129+
130+
static int stop(const struct device *dev, uint32_t ctx)
131+
{
132+
int err;
133+
134+
err = set_off_state(&((xo24m_data_t *)dev->data)->flags, ctx);
135+
if (err < 0) {
136+
return err;
137+
}
138+
139+
((xo24m_config_t *)dev->config)->stop();
140+
141+
return 0;
142+
}
143+
144+
static int async_start(const struct device *dev, clock_control_cb_t cb, void *user_data,
145+
uint32_t ctx)
146+
{
147+
int err;
148+
149+
err = set_starting_state(&((xo24m_data_t *)dev->data)->flags, ctx);
150+
if (err < 0) {
151+
return err;
152+
}
153+
154+
((xo24m_data_t *)dev->data)->cb = cb;
155+
((xo24m_data_t *)dev->data)->user_data = user_data;
156+
157+
((xo24m_config_t *)dev->config)->start();
158+
159+
return 0;
160+
}
161+
162+
static void blocking_start_callback(const struct device *dev,
163+
clock_control_subsys_t subsys,
164+
void *user_data)
165+
{
166+
struct k_sem *sem = user_data;
167+
168+
k_sem_give(sem);
169+
}
170+
171+
static clock_control_subsys_t get_subsys(struct onoff_manager *mgr) //TODO remove
172+
{
173+
xo24m_data_t *data = CLOCK_DEVICE_XO24M->data;
174+
size_t offset = (size_t)(mgr - data->mgr);
175+
176+
return (clock_control_subsys_t)offset;
177+
}
178+
179+
static void onoff_stop(struct onoff_manager *mgr,
180+
onoff_notify_fn notify)
181+
{
182+
int res;
183+
184+
res = stop(CLOCK_DEVICE_XO24M, CTX_ONOFF);
185+
notify(mgr, res);
186+
}
187+
188+
static void onoff_started_callback(const struct device *dev,
189+
clock_control_subsys_t sys,
190+
void *user_data)
191+
{
192+
ARG_UNUSED(sys);
193+
194+
onoff_notify_fn notify = user_data;
195+
196+
notify(&((xo24m_data_t *)dev->data)->mgr, 0);
197+
}
198+
199+
static void onoff_start(struct onoff_manager *mgr,
200+
onoff_notify_fn notify)
201+
{
202+
int err;
203+
204+
err = async_start(CLOCK_DEVICE_XO24M, onoff_started_callback, notify, CTX_ONOFF);
205+
if (err < 0) {
206+
notify(mgr, err);
207+
}
208+
}
209+
210+
static void clock_event_handler(void)
211+
{
212+
const struct device *dev = CLOCK_DEVICE_XO24M;
213+
214+
clkstarted_handle(dev);
215+
}
216+
217+
static int api_start(const struct device *dev, clock_control_subsys_t subsys,
218+
clock_control_cb_t cb, void *user_data)
219+
{
220+
ARG_UNUSED(subsys);
221+
222+
return async_start(dev, cb, user_data, CTX_API);
223+
}
224+
225+
static int api_blocking_start(const struct device *dev,
226+
clock_control_subsys_t subsys)
227+
{
228+
struct k_sem sem = Z_SEM_INITIALIZER(sem, 0, 1);
229+
int err;
230+
231+
if (!IS_ENABLED(CONFIG_MULTITHREADING)) {
232+
return -ENOTSUP;
233+
}
234+
235+
err = api_start(dev, subsys, blocking_start_callback, &sem);
236+
if (err < 0) {
237+
return err;
238+
}
239+
240+
return k_sem_take(&sem, K_MSEC(500));
241+
}
242+
243+
static int api_stop(const struct device *dev, clock_control_subsys_t subsys)
244+
{
245+
ARG_UNUSED(subsys);
246+
247+
return stop(dev, CTX_API);
248+
}
249+
250+
static enum clock_control_status api_get_status(const struct device *dev,
251+
clock_control_subsys_t subsys)
252+
{
253+
ARG_UNUSED(subsys);
254+
255+
return GET_STATUS(((xo24m_data_t *)dev->data)->flags);
256+
}
257+
258+
static int api_request(const struct device *dev,
259+
const struct nrf_clock_spec *spec,
260+
struct onoff_client *cli)
261+
{
262+
xo24m_data_t *dev_data = dev->data;
263+
264+
ARG_UNUSED(spec);
265+
266+
return onoff_request(&dev_data->mgr, cli);
267+
}
268+
269+
static int api_release(const struct device *dev,
270+
const struct nrf_clock_spec *spec)
271+
{
272+
xo24m_data_t *dev_data = dev->data;
273+
274+
ARG_UNUSED(spec);
275+
276+
return onoff_release(&dev_data->mgr);
277+
}
278+
279+
static int api_cancel_or_release(const struct device *dev,
280+
const struct nrf_clock_spec *spec,
281+
struct onoff_client *cli)
282+
{
283+
xo24m_data_t *dev_data = dev->data;
284+
285+
ARG_UNUSED(spec);
286+
287+
return onoff_cancel_or_release(&dev_data->mgr, cli);
288+
}
289+
290+
static int clk_init(const struct device *dev)
291+
{
292+
nrfx_err_t nrfx_err;
293+
int err;
294+
static const struct onoff_transitions transitions = {
295+
.start = onoff_start,
296+
.stop = onoff_stop
297+
};
298+
299+
clock_control_nrf_common_connect_irq();
300+
301+
nrfx_err = nrfx_clock_xo24m_init(clock_event_handler);
302+
if (nrfx_err != NRFX_SUCCESS) {
303+
return -EIO;
304+
}
305+
306+
err = onoff_manager_init(&((xo24m_data_t *)dev->data)->mgr,
307+
&transitions);
308+
if (err < 0) {
309+
return err;
310+
}
311+
312+
((xo24m_data_t *)dev->data)->flags = CLOCK_CONTROL_STATUS_OFF;
313+
314+
return 0;
315+
}
316+
317+
static DEVICE_API(nrf_clock_control, clock_control_api) = {
318+
.std_api = {
319+
.on = api_blocking_start,
320+
.off = api_stop,
321+
.async_on = api_start,
322+
.get_status = api_get_status,
323+
},
324+
.request = api_request,
325+
.release = api_release,
326+
.cancel_or_release = api_cancel_or_release,
327+
};
328+
329+
static xo24m_data_t data;
330+
331+
static const xo24m_config_t config = {
332+
.start = xo24m_start,
333+
.stop = xo24m_stop,
334+
};
335+
336+
DEVICE_DT_DEFINE(DT_NODELABEL(xo24m), clk_init, NULL,
337+
&data, &config,
338+
PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
339+
&clock_control_api);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Nordic nRF xo24m clock control node
5+
6+
compatible: "nordic,nrf-clock-xo24m"
7+
8+
include: base.yaml
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
interrupts:
15+
required: true

0 commit comments

Comments
 (0)