From 91a3f42070ad073346babac0aac51cbf13945ac1 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 10 Dec 2024 15:15:11 -0500 Subject: [PATCH] tests: drivers: clock_management: add clock_management_minimal test Add clock_management_minimal test. This test is intended to verify that clock management functions correctly when runtime notifications and rate setting are disabled. It also verifies that support for multiple clock outputs on a device works as expected. The test has the following phases: - apply default clock state for both clock outputs of the emulated consumer. Verify that the resulting clock frequencies match what is expected. - apply sleep clock state for both clock outputs of the emulated consumer. Verify that the resulting clock frequencies match what is expected. - Request a clock frequency from each clock output, which should match the frequency of one of the defined states exactly. Verify that the expected state is applied. 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 --- .../clock_management_minimal/CMakeLists.txt | 16 +++ .../clock_management_minimal/README.txt | 31 ++++ .../lpcxpresso55s69_lpc55s69_cpu0.overlay | 111 +++++++++++++++ .../boards/native_sim.overlay | 134 ++++++++++++++++++ .../dts/bindings/vnd,emul-clock-consumer.yaml | 56 ++++++++ .../clock_management_minimal/prj.conf | 4 + .../src/test_clock_management_minimal.c | 127 +++++++++++++++++ .../clock_management_minimal/testcase.yaml | 8 ++ 8 files changed, 487 insertions(+) create mode 100644 tests/drivers/clock_management/clock_management_minimal/CMakeLists.txt create mode 100644 tests/drivers/clock_management/clock_management_minimal/README.txt create mode 100644 tests/drivers/clock_management/clock_management_minimal/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay create mode 100644 tests/drivers/clock_management/clock_management_minimal/boards/native_sim.overlay create mode 100644 tests/drivers/clock_management/clock_management_minimal/dts/bindings/vnd,emul-clock-consumer.yaml create mode 100644 tests/drivers/clock_management/clock_management_minimal/prj.conf create mode 100644 tests/drivers/clock_management/clock_management_minimal/src/test_clock_management_minimal.c create mode 100644 tests/drivers/clock_management/clock_management_minimal/testcase.yaml diff --git a/tests/drivers/clock_management/clock_management_minimal/CMakeLists.txt b/tests/drivers/clock_management/clock_management_minimal/CMakeLists.txt new file mode 100644 index 000000000000000..b2ebe4b128bc84f --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/CMakeLists.txt @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +# Add "common" directory to get DTS bindings for emulated clock drivers +list(APPEND DTS_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../common) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(clock_management_minimal) + +FILE(GLOB app_sources src/*.c) +FILE(GLOB clock_sources ../common/emul_clock_drivers/*.c) +target_sources(app PRIVATE ${app_sources} ${clock_sources}) + +# Add custom clock drivers to clock management header list +add_clock_management_header("../common/emul_clock_drivers/emul_clock_drivers.h") diff --git a/tests/drivers/clock_management/clock_management_minimal/README.txt b/tests/drivers/clock_management/clock_management_minimal/README.txt new file mode 100644 index 000000000000000..7797f0158baf97c --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/README.txt @@ -0,0 +1,31 @@ +Clock Management Minimal Test +############################# + +This test is designed to verify that the clock management API can function +correctly without runtime callbacks or rate setting enabled. It defines one +dummy clock consumer. In addition, it defines several dummy clock nodes to +verify API functionality. Boards should configure these dummy devices with +clock states as described within the tests below. + +Boards may also use the dummy clock nodes as needed if they do not have a +hardware clock output they can safely reconfigure as part of this testcase. + +The following tests will run, using the output clock with name "default": + +* Verify that the consumer can apply the clock state named "default" for + both the "slow" and "fast" clock output, and that the queried rates of + the "slow" and "fast" clocks match the properties "slow-default-freq" + and "fast-default-freq", respectively. + +* Verify that the consumer can apply the clock state named "sleep" for + both the "slow" and "fast" clock output, and that the queried rates of + the "slow" and "fast" clocks match the properties "slow-sleep-freq" + and "fast-sleep-freq", respectively. + +* Verify that requesting the frequency given by "slow-request-freq" from + the "slow" clock output reconfigures that clock output to *exactly* the + frequency given by the "slow-request-freq" property. + +* Verify that requesting the frequency given by "fast-request-freq" from + the "fast" clock output reconfigures that clock output to *exactly* the + frequency given by the "fast-request-freq" property. diff --git a/tests/drivers/clock_management/clock_management_minimal/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay b/tests/drivers/clock_management/clock_management_minimal/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay new file mode 100644 index 000000000000000..d595b7237772c2e --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* Clock CPU from FROHF, since we will use the PLLs within our testcases */ +&system_clock { + sys_clk_96mhz: sys-clk-96mhz { + compatible = "clock-state"; + clocks = <&ahbclkdiv 1 &fro_hf 1 &mainclksela 3 &mainclkselb 0>; + clock-frequency = ; + locking-state; + }; +}; + +&cpu0 { + clock-state-0 = <&sys_clk_96mhz>; +}; + +/* Disable the SD controller- we are using its clock for this test */ +&sdif { + status = "disabled"; +}; + +/* Define clock states for clockout clock */ +&clkout_clock { + clkout_16mhz: clkout-16mhz { + compatible = "clock-state"; + /* Expect a clock frequency of 16 MHz */ + clocks = <&xtal32m 1 &clk_in_en 1 &pll0clksel 1 + &pll0_pdec 4 &pll0_directo 0 + &pll0 512000000 8 256 0 31 31 0 0 0 + &pll1_bypass 0 &clkoutsel 1 + &clkoutdiv 8>; + clock-frequency = ; + }; + + clkout_1mhz: clkout-1mhz { + compatible = "clock-state"; + /* Expect a clock frequency of 1MHz */ + clocks = <&fro_1m 1 &clkoutsel 4>; + clock-frequency = ; + }; + + clkout_500mhz: clkout-500mhz { + compatible = "clock-state"; + /* Expect a clock frequency of 500 KHz */ + clocks = <&xtal32m 1 &clk_in_en 1 &pll0clksel 1 + &pll0_pdec 4 &pll0_directo 0 + &pll0 512000000 8 256 0 31 31 0 0 0 + &pll1_bypass 0 &clkoutsel 1 + &clkoutdiv 256>; + clock-frequency = ; + }; +}; + +/* Define clock states for SDIO clock */ +&sdio_clock { + sdioclk_48mhz: sdioclk-48mhz { + compatible = "clock-state"; + /* Expect a clock frequency of 48 MHz */ + clocks = <&fro_12m 1 &pll1clksel 0 + &pll1_pdec 4 &pll1_directo 0 + &pll1 384000000 4 128 0 62 31 + &pll1_bypass 0 &sdioclksel 5 + &sdioclkdiv 2>; + clock-frequency = ; + }; + + sdioclk_24mhz: sdioclk-24mhz { + compatible = "clock-state"; + /* Expect a clock frequency of 24 MHz */ + clocks = <&fro_12m 1 &pll1clksel 0 + &pll1_pdec 4 &pll1_directo 0 + &pll1 384000000 4 128 0 62 31 + &pll1_bypass 0 &sdioclksel 5 + &sdioclkdiv 4>; + clock-frequency = ; + }; + + sdioclk_12mhz: sdioclk-12mhz { + compatible = "clock-state"; + /* Expect a clock frequency of 12 MHz */ + clocks = <&fro_hf 1 &sdioclksel 3 + &sdioclkdiv 8>; + clock-frequency = ; + }; +}; + +/ { + /* Emulated device clock consumer */ + emul_device { + emul_dev1: emul-dev1 { + compatible = "vnd,emul-clock-consumer"; + clock-outputs = <&clkout_clock &sdio_clock>; + clock-output-names = "slow", "fast"; + clock-state-0 = <&clkout_16mhz &sdioclk_48mhz>; + slow-default-freq = ; + fast-default-freq = ; + slow-sleep-freq = ; + fast-sleep-freq = ; + clock-state-1 = <&clkout_1mhz &sdioclk_12mhz>; + slow-request-freq = ; + fast-request-freq = ; + clock-state-names = "default", "sleep"; + }; + }; +}; diff --git a/tests/drivers/clock_management/clock_management_minimal/boards/native_sim.overlay b/tests/drivers/clock_management/clock_management_minimal/boards/native_sim.overlay new file mode 100644 index 000000000000000..3f1b75388096896 --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/boards/native_sim.overlay @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Define clock tree with emulated clock nodes. + * These node labels are chosen so that they won't conflict with SOC clock + * tree nodelabels. The clock driver implementations used by this tree are + * stored within the test itself + */ + +#include + +/ { + emul_clock_root { + emul_source1: emul-source1 { + compatible = "fixed-clock"; + clock-frequency = ; + #clock-cells = <0>; + + emul_div1: emul-div1 { + compatible = "vnd,emul-clock-div"; + max-div = <64>; + #clock-cells = <1>; + }; + }; + + emul_source2: emul-source2 { + compatible = "fixed-clock"; + clock-frequency = ; + #clock-cells = <0>; + + emul_div2: emul-div2 { + compatible = "vnd,emul-clock-div"; + max-div = <256>; + #clock-cells = <1>; + }; + }; + + emul_source3: emul-source3 { + compatible = "fixed-clock"; + clock-frequency = ; + #clock-cells = <0>; + }; + + emul_mux1: emul-mux1 { + compatible = "vnd,emul-clock-mux"; + inputs = <&emul_div1 &emul_div2>; + #clock-cells = <1>; + + dev1_out_slow: dev1-out-slow { + compatible = "clock-output"; + #clock-cells = <0>; + + /* Expect a clock frequency of 10 MHz */ + dev1_10mhz: dev1-10mhz { + compatible = "clock-state"; + clocks = <&emul_div1 1 &emul_mux1 0>; + clock-frequency = ; + }; + + /* Expect a clock frequency of 5 MHz */ + dev1_5mhz: dev1-5mhz { + compatible = "clock-state"; + clocks = <&emul_div1 2 &emul_mux1 0>; + clock-frequency = ; + }; + + /* Expect a clock frequency of 3.333333 MHz */ + dev1_3mhz: dev1-3mhz { + compatible = "clock-state"; + clocks = <&emul_div1 3 &emul_mux1 0>; + clock-frequency = <3333333>; + }; + }; + }; + + emul_mux2: emul-mux2 { + compatible = "vnd,emul-clock-mux"; + inputs = <&emul_mux1 &emul_source3>; + #clock-cells = <1>; + + dev1_out_fast: dev1-out-fast { + compatible = "clock-output"; + #clock-cells = <0>; + + /* Expect a clock frequency of 100 MHz */ + dev1_100mhz: dev1-100mhz { + compatible = "clock-state"; + clocks = <&emul_mux2 1>; + clock-frequency = ; + }; + + /* Expect a clock frequency of 50 MHz */ + dev1_50mhz: dev1-50mhz { + compatible = "clock-state"; + clocks = <&emul_mux2 0 + &emul_mux1 1 + &emul_div2 1>; + clock-frequency = ; + }; + + /* Expect a clock frequency of 25 MHz */ + dev1_25mhz: dev1-25mhz { + compatible = "clock-state"; + clocks = <&emul_mux2 0 + &emul_mux1 1 + &emul_div2 2>; + clock-frequency = ; + }; + }; + }; + }; + + /* Emulated device clock consumer */ + emul_device { + emul_dev1: emul-dev1 { + compatible = "vnd,emul-clock-consumer"; + clock-outputs = <&dev1_out_slow &dev1_out_fast>; + clock-output-names = "slow", "fast"; + clock-state-0 = <&dev1_10mhz &dev1_100mhz>; + slow-default-freq = ; + fast-default-freq = ; + slow-sleep-freq = <3333333>; + fast-sleep-freq = ; + clock-state-1 = <&dev1_3mhz &dev1_25mhz>; + slow-request-freq = ; + fast-request-freq = ; + clock-state-names = "default", "sleep"; + }; + }; +}; diff --git a/tests/drivers/clock_management/clock_management_minimal/dts/bindings/vnd,emul-clock-consumer.yaml b/tests/drivers/clock_management/clock_management_minimal/dts/bindings/vnd,emul-clock-consumer.yaml new file mode 100644 index 000000000000000..a25181702184f7c --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/dts/bindings/vnd,emul-clock-consumer.yaml @@ -0,0 +1,56 @@ +# Copyright (c) 2024 Tenstorrent AI UL +# +# SPDX-License-Identifier: Apache-2.0 + +description: | + Binding for emulated clock consumer device. This device is used in testing + to verify that clock states are applied as expected. + +compatible: "vnd,emul-clock-consumer" + +include: [clock-device.yaml] + +properties: + fast-default-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying default + clock state for fast output + + fast-sleep-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying sleep + clock state for fast output + + fast-request-freq: + type: int + required: true + description: | + Frequency this consumer will request from the fast output. Consumer + expects the resulting frequency from this request to match the + requested frequency exactly. + + slow-default-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying default + clock state for slow output + + slow-sleep-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying sleep + clock state for slow output + + slow-request-freq: + type: int + required: true + description: | + Frequency this consumer will request from the slow output. Consumer + expects the resulting frequency from this request to match the + requested frequency exactly. diff --git a/tests/drivers/clock_management/clock_management_minimal/prj.conf b/tests/drivers/clock_management/clock_management_minimal/prj.conf new file mode 100644 index 000000000000000..c0d438fa2d687eb --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ZTEST=y +CONFIG_CLOCK_MANAGEMENT=y +CONFIG_CLOCK_MANAGEMENT_RUNTIME=n +CONFIG_CLOCK_MANAGEMENT_SET_RATE=n diff --git a/tests/drivers/clock_management/clock_management_minimal/src/test_clock_management_minimal.c b/tests/drivers/clock_management/clock_management_minimal/src/test_clock_management_minimal.c new file mode 100644 index 000000000000000..5156042dfe26cc1 --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/src/test_clock_management_minimal.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +LOG_MODULE_REGISTER(test); + +/* Define clock management outputs for both states */ +CLOCK_MANAGEMENT_DT_DEFINE_OUTPUT_BY_NAME(DT_NODELABEL(emul_dev1), slow); +CLOCK_MANAGEMENT_DT_DEFINE_OUTPUT_BY_NAME(DT_NODELABEL(emul_dev1), fast); + +/* Get references to each clock management output and state */ +static const struct clock_output *dev1_slow = + CLOCK_MANAGEMENT_DT_GET_OUTPUT_BY_NAME(DT_NODELABEL(emul_dev1), slow); +static const struct clock_output *dev1_fast = + CLOCK_MANAGEMENT_DT_GET_OUTPUT_BY_NAME(DT_NODELABEL(emul_dev1), fast); +static clock_management_state_t dev1_slow_default = + CLOCK_MANAGEMENT_DT_GET_STATE(DT_NODELABEL(emul_dev1), slow, default); +static clock_management_state_t dev1_fast_default = + CLOCK_MANAGEMENT_DT_GET_STATE(DT_NODELABEL(emul_dev1), fast, default); +static clock_management_state_t dev1_slow_sleep = + CLOCK_MANAGEMENT_DT_GET_STATE(DT_NODELABEL(emul_dev1), slow, sleep); +static clock_management_state_t dev1_fast_sleep = + CLOCK_MANAGEMENT_DT_GET_STATE(DT_NODELABEL(emul_dev1), fast, sleep); + +/* Runs before every test, resets clocks to default state */ +void reset_clock_states(void *unused) +{ + ARG_UNUSED(unused); + int ret; + + /* Reset clock tree to default state */ + ret = clock_management_apply_state(dev1_slow, dev1_slow_default); + zassert_equal(ret, DT_PROP(DT_NODELABEL(emul_dev1), slow_default_freq), + "Failed to apply default clock management state for slow clock"); + ret = clock_management_apply_state(dev1_fast, dev1_fast_default); + zassert_equal(ret, DT_PROP(DT_NODELABEL(emul_dev1), fast_default_freq), + "Failed to apply default clock management state for fast clock"); +} + +ZTEST(clock_management_minimal, test_default_states) +{ + int ret; + int slow_default = DT_PROP(DT_NODELABEL(emul_dev1), slow_default_freq); + int fast_default = DT_PROP(DT_NODELABEL(emul_dev1), fast_default_freq); + + /* Apply default clock states for both clock outputs, make sure + * that rates match what is expected + */ + TC_PRINT("Applying default clock states\n"); + + ret = clock_management_apply_state(dev1_slow, dev1_slow_default); + zassert_equal(ret, slow_default, + "Failed to apply default clock management state for slow clock"); + ret = clock_management_get_rate(dev1_slow); + TC_PRINT("Slow clock default clock rate: %d\n", ret); + zassert_equal(ret, slow_default, + "Slow clock has invalid clock default clock rate"); + + ret = clock_management_apply_state(dev1_fast, dev1_fast_default); + zassert_equal(ret, fast_default, + "Failed to apply default clock management state for fast clock"); + ret = clock_management_get_rate(dev1_fast); + TC_PRINT("Fast clock default clock rate: %d\n", ret); + zassert_equal(ret, fast_default, + "Fast clock has invalid clock default clock rate"); +} + +ZTEST(clock_management_minimal, test_sleep_states) +{ + int ret; + int slow_sleep = DT_PROP(DT_NODELABEL(emul_dev1), slow_sleep_freq); + int fast_sleep = DT_PROP(DT_NODELABEL(emul_dev1), fast_sleep_freq); + + /* Apply sleep clock states for both clock outputs, make sure + * that rates match what is expected + */ + TC_PRINT("Applying sleep clock states\n"); + + ret = clock_management_apply_state(dev1_slow, dev1_slow_sleep); + zassert_equal(ret, slow_sleep, + "Failed to apply sleep clock management state for slow clock"); + ret = clock_management_get_rate(dev1_slow); + TC_PRINT("Slow clock sleep clock rate: %d\n", ret); + zassert_equal(ret, slow_sleep, + "Slow clock has invalid clock sleep clock rate"); + + ret = clock_management_apply_state(dev1_fast, dev1_fast_sleep); + zassert_equal(ret, fast_sleep, + "Failed to apply sleep clock management state for fast clock"); + ret = clock_management_get_rate(dev1_fast); + TC_PRINT("Fast clock sleep clock rate: %d\n", ret); + zassert_equal(ret, fast_sleep, + "Fast clock has invalid clock sleep clock rate"); +} + +ZTEST(clock_management_minimal, test_rate_req) +{ + const struct clock_management_rate_req dev1_slow_req = { + .min_freq = DT_PROP(DT_NODELABEL(emul_dev1), slow_request_freq), + .max_freq = DT_PROP(DT_NODELABEL(emul_dev1), slow_request_freq), + }; + const struct clock_management_rate_req dev1_fast_req = { + .min_freq = DT_PROP(DT_NODELABEL(emul_dev1), fast_request_freq), + .max_freq = DT_PROP(DT_NODELABEL(emul_dev1), fast_request_freq), + }; + + int dev1_slow_freq = DT_PROP(DT_NODELABEL(emul_dev1), slow_request_freq); + int dev1_fast_freq = DT_PROP(DT_NODELABEL(emul_dev1), fast_request_freq); + int ret; + + /* Apply constraints for slow clock */ + ret = clock_management_req_rate(dev1_slow, &dev1_slow_req); + zassert_equal(ret, dev1_slow_freq, + "Slow clock got incorrect frequency for request"); + TC_PRINT("Slow clock configured to rate %d\n", dev1_slow_freq); + ret = clock_management_req_rate(dev1_fast, &dev1_fast_req); + zassert_equal(ret, dev1_fast_freq, + "Fast clock got incorrect frequency for request"); + TC_PRINT("Fast clock configured to rate %d\n", dev1_fast_freq); +} + +ZTEST_SUITE(clock_management_minimal, NULL, NULL, reset_clock_states, NULL, NULL); diff --git a/tests/drivers/clock_management/clock_management_minimal/testcase.yaml b/tests/drivers/clock_management/clock_management_minimal/testcase.yaml new file mode 100644 index 000000000000000..0d43d87ed35bb36 --- /dev/null +++ b/tests/drivers/clock_management/clock_management_minimal/testcase.yaml @@ -0,0 +1,8 @@ +tests: + drivers.clock_management.api: + tags: + - drivers + - clock_management + integration_platforms: + - native_sim + filter: dt_compat_enabled("vnd,emul-clock-consumer")