Skip to content

Commit 8858afd

Browse files
tests: drivers: nrf_clock_control: Align tests for nRF9251
Align nrf_clock_control tests for nRF9251 targets. Signed-off-by: Adam Kondraciuk <adam.kondraciuk@nordicsemi.no>
1 parent 6e78b73 commit 8858afd

2 files changed

Lines changed: 351 additions & 1 deletion

File tree

tests/zephyr/drivers/clock_control/nrf_clock_control/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ cmake_minimum_required(VERSION 3.20.0)
99
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
1010
project(nrf_clock_control)
1111

12-
target_sources(app PRIVATE ${ZEPHYR_BASE}/tests/drivers/clock_control/nrf_clock_control/src/main.c)
12+
target_sources(app PRIVATE src/main.c)
Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
/*
2+
* Copyright (c) 2026 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <zephyr/devicetree.h>
8+
#include <zephyr/devicetree/clocks.h>
9+
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/ztest.h>
12+
#include <zephyr/dt-bindings/clock/nrf-auxpll.h>
13+
14+
struct test_clk_context {
15+
const struct device *clk_dev;
16+
const struct nrf_clock_spec *clk_specs;
17+
size_t clk_specs_size;
18+
};
19+
20+
#if defined(CONFIG_CLOCK_CONTROL_NRF92_HSFLL_LOCAL)
21+
const struct nrf_clock_spec test_clk_specs_hsfll[] = {
22+
{
23+
.frequency = MHZ(128),
24+
.accuracy = 0,
25+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
26+
},
27+
{
28+
.frequency = MHZ(256),
29+
.accuracy = 0,
30+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
31+
},
32+
{
33+
.frequency = MHZ(64),
34+
.accuracy = 0,
35+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
36+
},
37+
};
38+
#endif
39+
40+
#if CONFIG_BOARD_NRF9251DK_NRF9251_CPUAPP
41+
const struct nrf_clock_spec test_clk_specs_fll16m[] = {
42+
{
43+
.frequency = MHZ(16),
44+
.accuracy = 20000,
45+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
46+
},
47+
{
48+
.frequency = MHZ(16),
49+
.accuracy = 30,
50+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
51+
},
52+
};
53+
54+
static const struct test_clk_context fll16m_test_clk_contexts[] = {
55+
{
56+
.clk_dev = DEVICE_DT_GET(DT_NODELABEL(fll16m)),
57+
.clk_specs = test_clk_specs_fll16m,
58+
.clk_specs_size = ARRAY_SIZE(test_clk_specs_fll16m),
59+
},
60+
};
61+
62+
const struct nrf_clock_spec invalid_test_clk_specs_fll16m[] = {
63+
{
64+
.frequency = MHZ(16),
65+
.accuracy = 20,
66+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
67+
},
68+
{
69+
.frequency = MHZ(19),
70+
.accuracy = 0,
71+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
72+
},
73+
{
74+
.frequency = MHZ(16),
75+
.accuracy = 0,
76+
.precision = NRF_CLOCK_CONTROL_PRECISION_HIGH,
77+
},
78+
};
79+
80+
static const struct test_clk_context invalid_fll16m_test_clk_contexts[] = {
81+
{
82+
.clk_dev = DEVICE_DT_GET(DT_NODELABEL(fll16m)),
83+
.clk_specs = invalid_test_clk_specs_fll16m,
84+
.clk_specs_size = ARRAY_SIZE(invalid_test_clk_specs_fll16m),
85+
},
86+
};
87+
88+
static const struct test_clk_context cpuapp_hsfll_test_clk_contexts[] = {
89+
{
90+
.clk_dev = DEVICE_DT_GET(DT_NODELABEL(cpuapp_hsfll)),
91+
.clk_specs = test_clk_specs_hsfll,
92+
.clk_specs_size = ARRAY_SIZE(test_clk_specs_hsfll),
93+
},
94+
};
95+
#endif
96+
97+
#if defined(CONFIG_CLOCK_CONTROL_NRF_LFCLK)
98+
const struct nrf_clock_spec test_clk_specs_lfclk[] = {
99+
{
100+
.frequency = 32768,
101+
.accuracy = 0,
102+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
103+
},
104+
{
105+
.frequency = 32768,
106+
.accuracy = 20,
107+
.precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,
108+
},
109+
{
110+
.frequency = 32768,
111+
.accuracy = 20,
112+
.precision = NRF_CLOCK_CONTROL_PRECISION_HIGH,
113+
},
114+
};
115+
116+
static const struct test_clk_context lfclk_test_clk_contexts[] = {
117+
{
118+
.clk_dev = DEVICE_DT_GET(DT_NODELABEL(lfclk)),
119+
.clk_specs = test_clk_specs_lfclk,
120+
.clk_specs_size = ARRAY_SIZE(test_clk_specs_lfclk),
121+
},
122+
};
123+
#endif
124+
125+
static void test_request_release_clock_spec(const struct device *clk_dev,
126+
const struct nrf_clock_spec *clk_spec)
127+
{
128+
int ret = 0;
129+
int res = 0;
130+
struct onoff_client cli;
131+
uint32_t rate;
132+
133+
TC_PRINT("Clock under test: %s\n", clk_dev->name);
134+
sys_notify_init_spinwait(&cli.notify);
135+
ret = nrf_clock_control_request(clk_dev, clk_spec, &cli);
136+
zassert_between_inclusive(ret, 0, 2);
137+
do {
138+
ret = sys_notify_fetch_result(&cli.notify, &res);
139+
k_yield();
140+
} while (ret == -EAGAIN);
141+
TC_PRINT("Clock control request return value: %d\n", ret);
142+
TC_PRINT("Clock control request response code: %d\n", res);
143+
zassert_ok(ret);
144+
zassert_ok(res);
145+
ret = clock_control_get_rate(clk_dev, NULL, &rate);
146+
if (ret != -ENOSYS) {
147+
zassert_ok(ret);
148+
zassert_equal(rate, clk_spec->frequency);
149+
}
150+
k_msleep(1000);
151+
ret = nrf_clock_control_release(clk_dev, clk_spec);
152+
zassert_equal(ret, ONOFF_STATE_ON);
153+
}
154+
155+
static void test_clock_control_request(const struct test_clk_context *clk_contexts,
156+
size_t contexts_size)
157+
{
158+
int ret;
159+
const struct test_clk_context *clk_context;
160+
size_t clk_specs_size;
161+
const struct device *clk_dev;
162+
const struct nrf_clock_spec *req_spec;
163+
struct nrf_clock_spec res_spec;
164+
uint32_t startup_time_us;
165+
166+
for (size_t i = 0; i < contexts_size; i++) {
167+
clk_context = &clk_contexts[i];
168+
clk_specs_size = clk_context->clk_specs_size;
169+
170+
for (size_t u = 0; u < clk_specs_size; u++) {
171+
clk_dev = clk_context->clk_dev;
172+
req_spec = &clk_context->clk_specs[u];
173+
174+
zassert_true(device_is_ready(clk_dev), "%s is not ready", clk_dev->name);
175+
176+
TC_PRINT("Requested clock (%s) spec: frequency %d, accuracy %d, precision "
177+
"%d\n",
178+
clk_dev->name, req_spec->frequency, req_spec->accuracy,
179+
req_spec->precision);
180+
181+
ret = nrf_clock_control_resolve(clk_dev, req_spec, &res_spec);
182+
zassert(ret == 0 || ret == -ENOSYS,
183+
"minimum clock specs could not be resolved");
184+
if (ret == 0) {
185+
TC_PRINT("Resolved spec: frequency %d, accuracy %d, precision "
186+
"%d\n",
187+
res_spec.frequency, res_spec.accuracy, res_spec.precision);
188+
} else if (ret == -ENOSYS) {
189+
TC_PRINT("resolve not supported\n");
190+
res_spec.frequency = req_spec->frequency;
191+
res_spec.accuracy = req_spec->accuracy;
192+
res_spec.precision = req_spec->precision;
193+
}
194+
195+
ret = nrf_clock_control_get_startup_time(clk_dev, &res_spec,
196+
&startup_time_us);
197+
zassert(ret == 0 || ret == -ENOSYS, "failed to get startup time");
198+
if (ret == 0) {
199+
TC_PRINT("startup time for resloved spec: %uus\n", startup_time_us);
200+
} else if (ret == -ENOSYS) {
201+
TC_PRINT("get startup time not supported\n");
202+
}
203+
204+
TC_PRINT("Applying spec: frequency %d, accuracy %d, precision "
205+
"%d\n",
206+
res_spec.frequency, res_spec.accuracy, res_spec.precision);
207+
test_request_release_clock_spec(clk_dev, &res_spec);
208+
}
209+
}
210+
}
211+
212+
#if CONFIG_BOARD_NRF9251DK_NRF9251_CPUAPP
213+
ZTEST(nrf2_clock_control, test_cpuapp_hsfll_control)
214+
{
215+
TC_PRINT("APPLICATION DOMAIN HSFLL test\n");
216+
test_clock_control_request(cpuapp_hsfll_test_clk_contexts,
217+
ARRAY_SIZE(cpuapp_hsfll_test_clk_contexts));
218+
}
219+
220+
ZTEST(nrf2_clock_control, test_fll16m_control)
221+
{
222+
TC_PRINT("FLL16M test\n");
223+
test_clock_control_request(fll16m_test_clk_contexts, ARRAY_SIZE(fll16m_test_clk_contexts));
224+
}
225+
226+
ZTEST(nrf2_clock_control, test_invalid_fll16m_clock_spec_response)
227+
{
228+
int ret = 0;
229+
int res = 0;
230+
struct onoff_client cli;
231+
const struct test_clk_context *clk_context;
232+
size_t clk_specs_size;
233+
const struct device *clk_dev;
234+
const struct nrf_clock_spec *clk_spec;
235+
236+
TC_PRINT("FLL16M invalid clock specification test\n");
237+
238+
for (size_t i = 0; i < ARRAY_SIZE(invalid_fll16m_test_clk_contexts); i++) {
239+
clk_context = &invalid_fll16m_test_clk_contexts[i];
240+
clk_specs_size = clk_context->clk_specs_size;
241+
242+
for (size_t u = 0; u < clk_specs_size; u++) {
243+
clk_dev = clk_context->clk_dev;
244+
clk_spec = &clk_context->clk_specs[u];
245+
246+
zassert_true(device_is_ready(clk_dev),
247+
"%s is not ready", clk_dev->name);
248+
249+
TC_PRINT("Applying clock (%s) spec: frequency %d, accuracy %d, precision "
250+
"%d\n",
251+
clk_dev->name, clk_spec->frequency, clk_spec->accuracy,
252+
clk_spec->precision);
253+
254+
sys_notify_init_spinwait(&cli.notify);
255+
ret = nrf_clock_control_request(clk_dev, clk_spec, &cli);
256+
TC_PRINT("Clock control request return value: %d\n", ret);
257+
TC_PRINT("Clock control request response code: %d\n", res);
258+
zassert_equal(ret, -EINVAL);
259+
zassert_ok(res);
260+
}
261+
}
262+
}
263+
#endif
264+
265+
#if defined(CONFIG_CLOCK_CONTROL_NRF_LFCLK)
266+
ZTEST(nrf2_clock_control, test_lfclk_control)
267+
{
268+
TC_PRINT("LFCLK test\n");
269+
test_clock_control_request(lfclk_test_clk_contexts, ARRAY_SIZE(lfclk_test_clk_contexts));
270+
}
271+
272+
ZTEST(nrf2_clock_control, test_safe_request_cancellation)
273+
{
274+
int ret = 0;
275+
int res = 0;
276+
struct onoff_client cli;
277+
const struct test_clk_context *clk_context = &lfclk_test_clk_contexts[0];
278+
const struct device *clk_dev = clk_context->clk_dev;
279+
const struct nrf_clock_spec *clk_spec = &test_clk_specs_lfclk[0];
280+
281+
zassert_true(device_is_ready(clk_dev),
282+
"%s is not ready", clk_dev->name);
283+
284+
TC_PRINT("Safe clock request cancellation\n");
285+
TC_PRINT("Clock under test: %s\n", clk_dev->name);
286+
sys_notify_init_spinwait(&cli.notify);
287+
ret = nrf_clock_control_request(clk_dev, clk_spec, &cli);
288+
zassert_between_inclusive(ret, 0, 2);
289+
TC_PRINT("Clock control request return value: %d\n", ret);
290+
TC_PRINT("Clock control request response code: %d\n", res);
291+
zassert_ok(res);
292+
ret = nrf_clock_control_cancel_or_release(clk_dev, clk_spec, &cli);
293+
TC_PRINT("Clock control safe cancellation return value: %d\n", ret);
294+
zassert_between_inclusive(ret, ONOFF_STATE_ON, ONOFF_STATE_TO_ON);
295+
}
296+
#endif
297+
298+
static void *setup(void)
299+
{
300+
#if defined(CONFIG_BOARD_NRF9251DK_NRF9251_CPUAPP)
301+
const struct device *clk_dev = DEVICE_DT_GET(DT_NODELABEL(cpuapp_hsfll));
302+
const struct nrf_clock_spec clk_spec = {
303+
.frequency = MHZ(64),
304+
};
305+
struct onoff_client cli;
306+
uint32_t start_uptime;
307+
const uint32_t timeout_ms = 3000;
308+
309+
zassert_true(device_is_ready(clk_dev),
310+
"%s is not ready", clk_dev->name);
311+
312+
/* Constantly make requests to DVFS until one is successful (what also
313+
* means that the service has finished its initialization). This loop
314+
* also verifies that the clock control driver is able to recover after
315+
* an unsuccesful attempt to start a clock (at least one initial request
316+
* is expected to fail here due to DFVS not being initialized yet).
317+
*/
318+
TC_PRINT("Polling DVFS until it is ready\n");
319+
start_uptime = k_uptime_get_32();
320+
while (1) {
321+
int status;
322+
int ret;
323+
324+
sys_notify_init_spinwait(&cli.notify);
325+
ret = nrf_clock_control_request(clk_dev, &clk_spec, &cli);
326+
/* The on-off manager for this clock controller is expected to
327+
* always be in the off state when a request is done (its error
328+
* state is expected to be cleared by the clock control driver).
329+
*/
330+
zassert_equal(ret, ONOFF_STATE_OFF, "request result: %d", ret);
331+
do {
332+
ret = sys_notify_fetch_result(&cli.notify, &status);
333+
k_yield();
334+
} while (ret == -EAGAIN);
335+
336+
if (status == 0) {
337+
TC_PRINT("DVFS is ready\n");
338+
break;
339+
} else if ((k_uptime_get_32() - start_uptime) >= timeout_ms) {
340+
TC_PRINT("DVFS is not ready after %u ms\n", timeout_ms);
341+
ztest_test_fail();
342+
break;
343+
}
344+
}
345+
#endif
346+
347+
return NULL;
348+
}
349+
350+
ZTEST_SUITE(nrf2_clock_control, NULL, setup, NULL, NULL, NULL);

0 commit comments

Comments
 (0)