Skip to content

Commit 3addd28

Browse files
committed
[nrf fromlist] drivers: clock_control: Separated nrf hfclk192m shim from nrf clock shim.
Separated clock_control_nrf_hfclk192m shim from clock_control_nrf shim. Upstream PR #: 99290 Signed-off-by: Michal Frankiewicz <[email protected]>
1 parent 89a042a commit 3addd28

File tree

6 files changed

+351
-0
lines changed

6 files changed

+351
-0
lines changed

drivers/clock_control/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_AUXPLL clock_cont
6363
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HFCLK clock_control_nrf_hfclk.c)
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)
66+
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HFCLK192M clock_control_nrf_hfclk192m.c)
6667
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_COMMON clock_control_nrf_common.c)
6768
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL60X clock_control_bl60x.c)
6869
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
@@ -344,6 +344,12 @@ config CLOCK_CONTROL_NRF_LFCLK
344344
select CLOCK_CONTROL_NRF_COMMON
345345
default y
346346

347+
config CLOCK_CONTROL_NRF_HFCLK192M
348+
bool "NRF HFCLK192M driver support"
349+
depends on DT_HAS_NORDIC_NRF_CLOCK_HFCLK192M_ENABLED
350+
select CLOCK_CONTROL_NRF_COMMON
351+
default y
352+
347353
config CLOCK_CONTROL_NRF_AUXPLL
348354
bool "nRF Auxiliary PLL driver"
349355
default y
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
/*
2+
* Copyright (c) 2016-2020 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 "nrf_clock_calibration.h"
13+
#include "clock_control_nrf_common.h"
14+
#include <nrfx_clock_hfclk192m.h>
15+
#include <zephyr/logging/log.h>
16+
#include <zephyr/shell/shell.h>
17+
#include <zephyr/irq.h>
18+
19+
LOG_MODULE_REGISTER(clock_control_hfclk192m, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
20+
21+
#define DT_DRV_COMPAT nordic_nrf_clock_hfclk192m
22+
23+
#define CLOCK_DEVICE_HFCLK192M DEVICE_DT_GET(DT_NODELABEL(hfclk192m))
24+
25+
#define CTX_ONOFF BIT(6)
26+
#define CTX_API BIT(7)
27+
#define CTX_MASK (CTX_ONOFF | CTX_API)
28+
29+
#define STATUS_MASK 0x7
30+
#define GET_STATUS(flags) (flags & STATUS_MASK)
31+
#define GET_CTX(flags) (flags & CTX_MASK)
32+
33+
/* Helper logging macros. */
34+
#ifdef CONFIG_LOG
35+
#define CLOCK_LOG(lvl, dev, ...) \
36+
LOG_##lvl("%s: " GET_ARG_N(1, __VA_ARGS__), \
37+
"hfclk192m" 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+
} hfclk192m_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+
} hfclk192m_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 = ((hfclk192m_data_t *)dev->data)->cb;
109+
110+
((hfclk192m_data_t *)dev->data)->cb = NULL;
111+
set_on_state(&((hfclk192m_data_t *)dev->data)->flags);
112+
DBG(dev, "Clock started");
113+
114+
if (callback) {
115+
callback(dev, NULL, (hfclk192m_data_t *)dev->data)->user_data);
116+
}
117+
}
118+
119+
static void hfclk192m_start(void)
120+
{
121+
nrfx_clock_hfclk192m_start();
122+
}
123+
124+
static void hfclk192m_stop(void)
125+
{
126+
nrfx_clock_hfclk192m_stop();
127+
}
128+
129+
static int stop(const struct device *dev, uint32_t ctx)
130+
{
131+
int err;
132+
133+
err = set_off_state(&((hfclk192m_data_t *)dev->data)->flags, ctx);
134+
if (err < 0) {
135+
return err;
136+
}
137+
138+
((hfclk192m_config_t *)dev->config)->stop();
139+
140+
return 0;
141+
}
142+
143+
static int async_start(const struct device *dev, clock_control_cb_t cb, void *user_data,
144+
uint32_t ctx)
145+
{
146+
int err;
147+
148+
err = set_starting_state(&((hfclk192m_data_t *)dev->data)->flags, ctx);
149+
if (err < 0) {
150+
return err;
151+
}
152+
153+
((hfclk192m_data_t *)dev->data)->cb = cb;
154+
((hfclk192m_data_t *)dev->data)->user_data = user_data;
155+
156+
((hfclk192m_config_t *)dev->config)->start();
157+
158+
return 0;
159+
}
160+
161+
static void blocking_start_callback(const struct device *dev, clock_control_subsys_t subsys,
162+
void *user_data)
163+
{
164+
ARG_UNUSED(subsys);
165+
166+
struct k_sem *sem = user_data;
167+
168+
k_sem_give(sem);
169+
}
170+
171+
static void onoff_stop(struct onoff_manager *mgr, onoff_notify_fn notify)
172+
{
173+
int res;
174+
175+
res = stop(CLOCK_DEVICE_HFCLK192M, CTX_ONOFF);
176+
notify(mgr, res);
177+
}
178+
179+
static void onoff_started_callback(const struct device *dev, clock_control_subsys_t sys,
180+
void *user_data)
181+
{
182+
ARG_UNUSED(sys);
183+
184+
onoff_notify_fn notify = user_data;
185+
186+
notify(&((hfclk192m_data_t *)dev->data)->mgr, 0);
187+
}
188+
189+
static void onoff_start(struct onoff_manager *mgr, onoff_notify_fn notify)
190+
{
191+
int err;
192+
193+
err = async_start(CLOCK_DEVICE_HFCLK192M, onoff_started_callback, notify, CTX_ONOFF);
194+
if (err < 0) {
195+
notify(mgr, err);
196+
}
197+
}
198+
199+
static void clock_event_handler(void)
200+
{
201+
const struct device *dev = CLOCK_DEVICE_HFCLK192M;
202+
203+
clkstarted_handle(dev);
204+
}
205+
206+
static int api_start(const struct device *dev, clock_control_subsys_t subsys, clock_control_cb_t cb,
207+
void *user_data)
208+
{
209+
ARG_UNUSED(subsys);
210+
211+
return async_start(dev, cb, user_data, CTX_API);
212+
}
213+
214+
static int api_blocking_start(const struct device *dev, clock_control_subsys_t subsys)
215+
{
216+
struct k_sem sem = Z_SEM_INITIALIZER(sem, 0, 1);
217+
int err;
218+
219+
if (!IS_ENABLED(CONFIG_MULTITHREADING)) {
220+
return -ENOTSUP;
221+
}
222+
223+
err = api_start(dev, subsys, blocking_start_callback, &sem);
224+
if (err < 0) {
225+
return err;
226+
}
227+
228+
return k_sem_take(&sem, K_MSEC(500));
229+
}
230+
231+
static int api_stop(const struct device *dev, clock_control_subsys_t subsys)
232+
{
233+
ARG_UNUSED(subsys);
234+
235+
return stop(dev, CTX_API);
236+
}
237+
238+
static enum clock_control_status api_get_status(const struct device *dev,
239+
clock_control_subsys_t subsys)
240+
{
241+
ARG_UNUSED(subsys);
242+
243+
return GET_STATUS(((hfclk192m_data_t *)dev->data)->flags);
244+
}
245+
246+
static int api_request(const struct device *dev, const struct nrf_clock_spec *spec,
247+
struct onoff_client *cli)
248+
{
249+
hfclk192m_data_t *dev_data = dev->data;
250+
251+
ARG_UNUSED(spec);
252+
253+
return onoff_request(&dev_data->mgr, cli);
254+
}
255+
256+
static int api_release(const struct device *dev, const struct nrf_clock_spec *spec)
257+
{
258+
hfclk192m_data_t *dev_data = dev->data;
259+
260+
ARG_UNUSED(spec);
261+
262+
return onoff_release(&dev_data->mgr);
263+
}
264+
265+
static int api_cancel_or_release(const struct device *dev, const struct nrf_clock_spec *spec,
266+
struct onoff_client *cli)
267+
{
268+
hfclk192m_data_t *dev_data = dev->data;
269+
270+
ARG_UNUSED(spec);
271+
272+
return onoff_cancel_or_release(&dev_data->mgr, cli);
273+
}
274+
275+
static int clk_init(const struct device *dev)
276+
{
277+
int err;
278+
static const struct onoff_transitions transitions = {.start = onoff_start,
279+
.stop = onoff_stop};
280+
281+
clock_control_nrf_common_connect_irq();
282+
283+
if (nrfx_clock_hfclk192m_init(clock_event_handler) != 0) {
284+
return -EIO;
285+
}
286+
287+
err = onoff_manager_init(&((hfclk192m_data_t *)dev->data)->mgr, &transitions);
288+
if (err < 0) {
289+
return err;
290+
}
291+
292+
((hfclk192m_data_t *)dev->data)->flags = CLOCK_CONTROL_STATUS_OFF;
293+
294+
return 0;
295+
}
296+
297+
CLOCK_CONTROL_NRF_IRQ_HANDLERS_ITERABLE(clock_control_nrf_hfclk192m,
298+
&nrfx_clock_hfclk192m_irq_handler);
299+
300+
static DEVICE_API(nrf_clock_control, clock_control_api) = {
301+
.std_api =
302+
{
303+
.on = api_blocking_start,
304+
.off = api_stop,
305+
.async_on = api_start,
306+
.get_status = api_get_status,
307+
},
308+
.request = api_request,
309+
.release = api_release,
310+
.cancel_or_release = api_cancel_or_release,
311+
};
312+
313+
static hfclk192m_data_t data;
314+
315+
static const hfclk192m_config_t config = {
316+
.start = hfclk192m_start,
317+
.stop = hfclk192m_stop,
318+
};
319+
320+
DEVICE_DT_DEFINE(DT_NODELABEL(hfclk192m), clk_init, NULL, &data, &config, PRE_KERNEL_1,
321+
CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_control_api);

dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ lfclk: lfclk@5000 {
8282
status = "okay";
8383
};
8484

85+
hfclk192m: hfclk192m@5000 {
86+
compatible = "nordic,nrf-clock-hfclk192m";
87+
reg = <0x5000 0x1000>;
88+
interrupts = <5 NRF_DEFAULT_IRQ_PRIORITY>;
89+
status = "okay";
90+
};
91+
8592
power: power@5000 {
8693
compatible = "nordic,nrf-power";
8794
reg = <0x5000 0x1000>;
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 hfclk192m clock control node
5+
6+
compatible: "nordic,nrf-clock-hfclk192m"
7+
8+
include: base.yaml
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
interrupts:
15+
required: true

tests/drivers/clock_control/clock_control_api/testcase.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ tests:
2121
- nrf51dk/nrf51822
2222
- nrf52dk/nrf52832
2323
- nrf52840dk/nrf52840
24+
- nrf5340dk/nrf5340/cpuapp
2425
- nrf9160dk/nrf9160
2526
- nrf54l15dk/nrf54l15/cpuapp
2627
- nrf54l15dk/nrf54l15/cpuapp/ns

0 commit comments

Comments
 (0)