Skip to content

Commit c3b6d7d

Browse files
tests: drivers: clock_management: add test for clock_management on/off
Add testcase to verify support for clock_management on/off into the API testsuite. Signed-off-by: Daniel DeGrasse <[email protected]>
1 parent 6c2e9c6 commit c3b6d7d

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

tests/drivers/clock_management/clock_management_api/boards/native_sim.overlay

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,22 @@
5454
clock-ranking = <3>;
5555
};
5656

57+
test_emul_onoff_source: test-emul-onoff-source {
58+
compatible = "fixed-clock";
59+
clock-frequency = <50000000>;
60+
#clock-cells = <0>;
61+
62+
test_emul_onoff_gate: test-emul-onoff-gate {
63+
compatible = "vnd,emul-clock-gateable";
64+
#clock-cells = <0>;
65+
66+
emul_dev3_out: emul-dev3-out {
67+
compatible = "clock-output";
68+
#clock-cells = <0>;
69+
};
70+
};
71+
};
72+
5773
emul_mux1: emul-mux1 {
5874
compatible = "vnd,emul-clock-mux";
5975
inputs = <&emul_div1 &emul_div2>;
@@ -191,5 +207,21 @@
191207
clock-state-names = "default", "invalid", "shared",
192208
"locking";
193209
};
210+
211+
emul_dev3: emul-dev3 {
212+
compatible = "vnd,emul-clock-consumer";
213+
clock-outputs = <&emul_dev3_out>;
214+
clock-output-names = "default";
215+
/* Below properties aren't used on this node */
216+
default-freq = <0>;
217+
shared-freq = <0>;
218+
locking-freq = <0>;
219+
freq-constraints-0 = <0>;
220+
req-freq-0 = <0>;
221+
freq-constraints-1 = <0>;
222+
req-freq-1 = <0>;
223+
freq-constraints-2 = <0>;
224+
req-freq-2 = <0>;
225+
};
194226
};
195227
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2025, Tenstorrent AI ULC
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
description: |
6+
Binding for emulated clock gate node. This clock node simply can be turned on
7+
and off, and is used within the API test to verify the framework functions
8+
correctly.
9+
10+
compatible: "vnd,emul-clock-gateable"
11+
12+
include: [clock-node.yaml]
13+
14+
properties:
15+
"#clock-cells":
16+
const: 0

tests/drivers/clock_management/clock_management_api/src/test_clock_management_api.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static clock_management_state_t dev2_shared =
3636
static clock_management_state_t dev2_locking =
3737
CLOCK_MANAGEMENT_DT_GET_STATE(DT_NODELABEL(emul_dev2), default, locking);
3838

39+
3940
/* Define a second output using the same clock as emul_dev1 */
4041
CLOCK_MANAGEMENT_DEFINE_OUTPUT(DT_PHANDLE_BY_IDX(DT_NODELABEL(emul_dev1), clock_outputs,
4142
DT_CLOCK_OUTPUT_NAME_IDX(DT_NODELABEL(emul_dev1), default)),
@@ -293,6 +294,75 @@ ZTEST(clock_management_api, test_ranked)
293294
zassert_true(ret > 0, "Consumer 2 could not remove clock restrictions");
294295
}
295296

297+
#if DT_HAS_COMPAT_STATUS_OKAY(vnd_emul_clock_gateable)
298+
/* Only run this test if the gateable clock is present- this is all emulated,
299+
* so it likely only needs to run on native_sim
300+
*/
301+
302+
CLOCK_MANAGEMENT_DT_DEFINE_OUTPUT_BY_NAME(DT_NODELABEL(emul_dev3), default);
303+
304+
static const struct clock_output *dev3_out =
305+
CLOCK_MANAGEMENT_DT_GET_OUTPUT_BY_NAME(DT_NODELABEL(emul_dev3), default);
306+
307+
/*
308+
* Define a basic driver here for the gateable clock
309+
*/
310+
311+
#define DT_DRV_COMPAT vnd_emul_clock_gateable
312+
313+
static bool clock_is_gated;
314+
315+
struct gateable_clock_data {
316+
STANDARD_CLK_SUBSYS_DATA_DEFINE
317+
};
318+
319+
static clock_freq_t gateable_clock_recalc_rate(const struct clk *clk_hw, clock_freq_t parent_rate)
320+
{
321+
return clock_is_gated ? parent_rate : 0;
322+
}
323+
324+
static int gateable_clock_onoff(const struct clk *clk_hw, bool on)
325+
{
326+
clock_is_gated = !on;
327+
return 0;
328+
}
329+
330+
const struct clock_management_standard_api gateable_clock_api = {
331+
.recalc_rate = gateable_clock_recalc_rate,
332+
.shared.on_off = gateable_clock_onoff,
333+
};
334+
335+
#define GATEABLE_CLOCK_DEFINE(inst) \
336+
static struct gateable_clock_data gate_clk_##inst = { \
337+
STANDARD_CLK_SUBSYS_DATA_INIT(CLOCK_DT_GET(DT_INST_PARENT(inst))) \
338+
}; \
339+
CLOCK_DT_INST_DEFINE(inst, \
340+
&gate_clk_##inst, \
341+
&gateable_clock_api);
342+
343+
DT_INST_FOREACH_STATUS_OKAY(GATEABLE_CLOCK_DEFINE)
344+
345+
ZTEST(clock_management_api, test_onoff)
346+
{
347+
/* First disable all unused clocks. We should see the gateable one switch off. */
348+
clock_management_disable_unused();
349+
zassert_true(clock_is_gated, "Emulated clock is unused but did not gate");
350+
/* Now enable the clock for dev3 */
351+
clock_management_on(dev3_out);
352+
zassert_false(clock_is_gated, "Emulated clock is in use but gated");
353+
/* Make sure the clock doesn't turn off now, it is in use */
354+
clock_management_disable_unused();
355+
zassert_false(clock_is_gated, "Emulated clock is in use but gated during disabled_unused");
356+
/* Raise reference count to clock */
357+
clock_management_on(dev3_out);
358+
/* Lower reference count */
359+
clock_management_off(dev3_out);
360+
zassert_false(clock_is_gated, "Emulated clock should not gate, one reference still exists");
361+
/* Turn off the clock */
362+
clock_management_off(dev3_out);
363+
zassert_true(clock_is_gated, "Emulated clock is off but did not gate");
364+
}
296365

366+
#endif /* DT_HAS_COMPAT_STATUS_OKAY(vnd_emul_clock_gateable) */
297367

298368
ZTEST_SUITE(clock_management_api, NULL, NULL, reset_clock_states, NULL, NULL);

0 commit comments

Comments
 (0)