Skip to content

Commit b3a9a1c

Browse files
tests: drivers: clock_management: add clock_management_api test
Add clock_management_api test. This test is intended to verify features of the clock management API, including the following: - verify that clock notification callbacks work as expected when a clock root is reconfigured - verify that if a driver returns an error when configuring a clock, this will be propagated to the user. - verify that consumer constraints will be able to block other consumers from reconfiguring clocks - verify that consumers can remove constraints on their clocks The test is supported on the `native_sim` target using emulated clock drivers for testing purposes in CI, and on the `lpcxpresso55s69/lpc55s69/cpu0` target to verify the clock management API on real hardware. Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
1 parent 2f12fa2 commit b3a9a1c

File tree

14 files changed

+1212
-0
lines changed

14 files changed

+1212
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
# Add "common" directory to get DTS bindings for emulated clock drivers
6+
list(APPEND DTS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../common)
7+
8+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
9+
project(clock_management_api)
10+
11+
FILE(GLOB app_sources src/*.c)
12+
FILE(GLOB clock_sources ../common/emul_clock_drivers/*.c)
13+
target_sources(app PRIVATE ${app_sources} ${clock_sources})
14+
15+
# Add custom clock drivers to clock management header list
16+
add_clock_management_header("../common/emul_clock_drivers/emul_clock_drivers.h")
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
Clock Management API Test
2+
#########################
3+
4+
This test is designed to verify the functionality of the clock management API.
5+
It defines two dummy devices, which will both be clock consumers. In addition,
6+
it defines several dummy clock nodes to verify API functionality. Boards
7+
should configure these dummy devices with clock states as described within
8+
the tests below.
9+
10+
Boards may also use the dummy clock nodes as needed if they do not have a
11+
hardware clock output they can safely reconfigure as part of this testcase.
12+
13+
The following tests will run, using the output clock with name "default":
14+
15+
* Verify that each consumer can apply the clock state named "default",
16+
and that the queried rates match the property "default-freq" for each
17+
device.
18+
19+
* Verify that applying the state named "invalid" propagates an
20+
error to the user. Board devicetree overlays should configure the
21+
invalid clock state property such that it will apply invalid clock settings.
22+
23+
* Apply the state named "shared" for the first consumer. The shared clock state
24+
property for this consumer should be set such that the first consumer
25+
will be notified about a clock rate change, but the second consumer will
26+
not be. Verify this is the case.
27+
28+
* Apply the state named "shared" for the second consumer. The shared clock state
29+
property for this consumer should be set such that both consumers will
30+
be notified about a clock rate change. Verify this is the case. Additionally,
31+
check that the consumers are now running at the frequency given by
32+
the "shared_freq" property.
33+
34+
* Apply the state named "locking" for the first consumer. The locking clock
35+
state property should be set with the "locking-state" property, so that
36+
the consumer will now reject changes to its clock. Additionally, check
37+
that the first consumer is now running at the rate given by "locking-freq"
38+
property.
39+
40+
* Apply the state named "locking" for the second consumer. The locking clock
41+
state property should be set such that it would modify the clock rate of
42+
the first consumer if applied. Verify that the state fails to apply.
43+
44+
* Set clock constraints for the first consumer based on the "freq-constraints-0"
45+
property present on that node. Verify that the resulting frequency is
46+
"req-freq-0". Boards should define these constraints such that none of
47+
the statically defined clock states match this request.
48+
49+
* Set clock constraints for the software consumer that are known to be
50+
incompatible with those set for the first consumer. Verify these constraints
51+
are rejected
52+
53+
* Set clock constraints for the second consumer based on the
54+
"freq-constraints-0" property present on that node. Verify that the resulting
55+
frequency is "req-freq-0", and that the first consumer was notified of the
56+
frequency change.
57+
58+
* Set clock constraints for the first consumer based on the "freq-constraints-1"
59+
property present on that node. Verify that the constraints are rejected.
60+
Boards should define these constraints such that they are incompatible with
61+
the constraints set by "freq-constraints-0" for the second consumer.
62+
63+
* Set clock constraints for the second consumer based on the
64+
"freq-constraints-1" property present on that node. Verify that the resulting
65+
frequency is "req-freq-1". Boards should define these constraints such that
66+
one of the statically defined constraints could satisfy this request, and such
67+
that the framework will now select the static state. No check is made if the
68+
first consumer is notified of this change.
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* Copyright 2024 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/* Clock CPU from FROHF, since we will use the PLLs within our testcases */
8+
&system_clock {
9+
sys_clk_96mhz: sys-clk-96mhz {
10+
compatible = "clock-state";
11+
clocks = <&ahbclkdiv 1 &fro_hf 1 &mainclksela 3 &mainclkselb 0>;
12+
clock-frequency = <DT_FREQ_M(96)>;
13+
locking-state;
14+
};
15+
};
16+
17+
&cpu0 {
18+
clock-state-0 = <&sys_clk_96mhz>;
19+
};
20+
21+
/* Disable the SD controller- we are using its clock for this test */
22+
&sdif {
23+
status = "disabled";
24+
};
25+
26+
/* Define clock states for clockout clock */
27+
&clkout_clock {
28+
clkout_500mhz: clkout-500mhz {
29+
compatible = "clock-state";
30+
/* Expect a clock frequency of 500 KHz */
31+
clocks = <&xtal32m 1 &clk_in_en 1 &pll0clksel 1
32+
&pll0_pdec 4 &pll0_directo 0
33+
&pll0 512000000 8 256 0 31 31 0 0 0
34+
&pll1_bypass 0 &clkoutsel 1
35+
&clkoutdiv 256>;
36+
clock-frequency = <DT_FREQ_K(500)>;
37+
};
38+
39+
clkout_invalid: clkout-invalid {
40+
compatible = "clock-state";
41+
/* Expect error when applying this invalid state */
42+
clocks = <&clkoutsel 10>;
43+
clock-frequency = <0>;
44+
};
45+
46+
clkout_shared: clkout-shared {
47+
compatible = "clock-state";
48+
/* Expect notification on first device only,
49+
* as sdioclksel is not selecting pll0 as an input.
50+
* After reconfiguring PLL0 from emul_dev2, output
51+
* frequency will be 25.5 MHz
52+
*/
53+
clocks = <&pll0_pdec 8 &pll0 401000000 4 0
54+
0 4 3 1 3363831808 0 &clkoutdiv 2>;
55+
clock-frequency = <DT_FREQ_K(25500)>;
56+
};
57+
58+
59+
clkout_locking: clkout-locking {
60+
compatible ="clock-state";
61+
/* Use PLL0 at 25.5 MHz, but make this a locking state.
62+
* this way, the SDIO locking state will fail to apply,
63+
* as it reconfigures PLL0
64+
*/
65+
clocks = <&pll0_pdec 8 &pll0 401000000 4 0
66+
0 4 3 1 3363831808 0 &clkoutdiv 2>;
67+
clock-frequency = <DT_FREQ_K(25500)>;
68+
locking-state;
69+
};
70+
};
71+
72+
/* Define clock states for SDIO clock */
73+
&sdio_clock {
74+
sdioclk_48mhz: sdioclk-48mhz {
75+
compatible = "clock-state";
76+
/* Expect a clock frequency of 48 MHz */
77+
clocks = <&fro_12m 1 &pll1clksel 0
78+
&pll1_pdec 4 &pll1_directo 0
79+
&pll1 384000000 4 128 0 62 31
80+
&pll1_bypass 0 &sdioclksel 5
81+
&sdioclkdiv 2>;
82+
clock-frequency = <DT_FREQ_M(48)>;
83+
};
84+
85+
sdioclk_invalid: sdioclk-invalid {
86+
compatible = "clock-state";
87+
/* Expect error when applying this invalid state */
88+
clocks = <&sdioclksel 8>;
89+
clock-frequency = <0>;
90+
};
91+
92+
sdioclk_shared: sdioclk-shared {
93+
compatible = "clock-state";
94+
/* Expect notification on both devices with this state.
95+
* frequency should be 25.5 MHz for each
96+
*/
97+
clocks = <&pll0_pdec 8 &pll0 408000000 4 0
98+
0 4 3 1 3422552064 0 &sdioclkdiv 2
99+
&sdioclksel 1>;
100+
clock-frequency = <DT_FREQ_K(25500)>;
101+
};
102+
103+
sdioclk_locking: sdioclk-locking {
104+
compatible = "clock-state";
105+
/* This state will fail to apply, as it reconfigures PLL0
106+
* and the first consumer currently has a locking frequency
107+
* constraint on the PLL0 frequency
108+
*/
109+
clocks = <&pll0_pdec 10 &pll0 408000000 4 0
110+
0 4 3 1 3422552064 0 &sdioclkdiv 2
111+
&sdioclksel 1>;
112+
clock-frequency = <DT_FREQ_K(20400)>;
113+
locking-state;
114+
};
115+
};
116+
117+
/ {
118+
/* Emulated device clock consumers */
119+
emul_devices {
120+
emul_dev1: emul-dev1 {
121+
compatible = "vnd,emul-clock-consumer";
122+
clock-outputs = <&clkout_clock>;
123+
clock-output-names = "default";
124+
clock-state-0 = <&clkout_500mhz &clkout_invalid>;
125+
default-freq = <500000>;
126+
clock-state-1 = <&clkout_invalid>;
127+
clock-state-2 = <&clkout_shared>;
128+
shared-freq = <25500000>;
129+
clock-state-3 = <&clkout_locking>;
130+
clock-state-names = "default", "invalid", "shared",
131+
"locking";
132+
locking-freq = <DT_FREQ_K(25500)>;
133+
/* Request 0-48MHz. We expect pll0 to be used to
134+
* produce this clock rate. We allow a frequency of
135+
* 0 to indicate the PLL can be gated if needed.
136+
*/
137+
freq-constraints-0 = <0 DT_FREQ_M(48)>;
138+
req-freq-0 = <DT_FREQ_M(48)>;
139+
/* Request narrow range that only PLL0 could produce.
140+
* Since emul_dev2 is using PLL0 as well and can't
141+
* accept this range, we expect this request to fail.
142+
*/
143+
freq-constraints-1 = <DT_FREQ_K(44100) DT_FREQ_K(44200)>;
144+
req-freq-1 = <0>;
145+
};
146+
147+
emul_dev2: emul-dev2 {
148+
compatible = "vnd,emul-clock-consumer";
149+
clock-outputs = <&sdio_clock>;
150+
clock-output-names = "default";
151+
clock-state-0 = <&sdioclk_48mhz>;
152+
default-freq = <48000000>;
153+
clock-state-1 = <&sdioclk_invalid>;
154+
clock-state-2 = <&sdioclk_shared>;
155+
shared-freq = <25500000>;
156+
clock-state-3 = <&sdioclk_locking>;
157+
clock-state-names = "default", "invalid", "shared",
158+
"locking";
159+
locking-freq = <0>;
160+
/* Request 40-43.5MHz. We expect pll0 to be used to
161+
* produce this clock rate, so emul_dev1 will be
162+
* notified.
163+
*/
164+
freq-constraints-0 = <DT_FREQ_M(40) DT_FREQ_K(43500)>;
165+
req-freq-0 = <DT_FREQ_K(43500)>;
166+
/* Request constraints that static state 0 can satisfy */
167+
freq-constraints-1 = <DT_FREQ_M(48) DT_FREQ_M(48)>;
168+
req-freq-1 = <DT_FREQ_M(48)>;
169+
};
170+
};
171+
};

0 commit comments

Comments
 (0)