From 64fb7bb109577248de2abd468c796ba609a92838 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 1 Oct 2024 16:42:19 -0500 Subject: [PATCH] tests: drivers: clock_management: add clock management hardware test Add clock management hardware test. This test applies a series of clock states for a given consumer, and verifies that each state produces the expected rate. This test is intended to verify that each clock node driver within an SOC implementation works as expected. Boards should define their test overlays for this test to exercise as much of the clock tree as possible, and ensure some clock states do not define an explicit clocks property, to test their `clock_set_rate` and `clock_round_rate` implementations. Initial support is added for the `lpcxpresso55s69/lpc55s69/cpu0` target, as this is the only hardware supporting clock management. Signed-off-by: Daniel DeGrasse --- .../clock_management_hw/CMakeLists.txt | 9 +++ .../clock_management_hw/README.txt | 32 +++++++++ .../lpcxpresso55s69_lpc55s69_cpu0.overlay | 70 +++++++++++++++++++ .../dts/bindings/vnd,emul-clock-consumer.yaml | 47 +++++++++++++ .../clock_management_hw/prj.conf | 5 ++ .../src/test_clock_management_hw.c | 62 ++++++++++++++++ .../clock_management_hw/testcase.yaml | 8 +++ 7 files changed, 233 insertions(+) create mode 100644 tests/drivers/clock_management/clock_management_hw/CMakeLists.txt create mode 100644 tests/drivers/clock_management/clock_management_hw/README.txt create mode 100644 tests/drivers/clock_management/clock_management_hw/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay create mode 100644 tests/drivers/clock_management/clock_management_hw/dts/bindings/vnd,emul-clock-consumer.yaml create mode 100644 tests/drivers/clock_management/clock_management_hw/prj.conf create mode 100644 tests/drivers/clock_management/clock_management_hw/src/test_clock_management_hw.c create mode 100644 tests/drivers/clock_management/clock_management_hw/testcase.yaml diff --git a/tests/drivers/clock_management/clock_management_hw/CMakeLists.txt b/tests/drivers/clock_management/clock_management_hw/CMakeLists.txt new file mode 100644 index 00000000000000..a7c0fc7253e267 --- /dev/null +++ b/tests/drivers/clock_management/clock_management_hw/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(clock_management_hw) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/clock_management/clock_management_hw/README.txt b/tests/drivers/clock_management/clock_management_hw/README.txt new file mode 100644 index 00000000000000..8a07adca1df462 --- /dev/null +++ b/tests/drivers/clock_management/clock_management_hw/README.txt @@ -0,0 +1,32 @@ +Clock Management Hardware Test +############################## + +This test is designed to verify the functionality of hardware clock trees +implementing the clock management API. It defines one dummy devices, which +will be a clock consumer. + +The test will apply five clock states for the dummy device, and verify the +frequency matches an expected value for each state. The states are as +follows: + +* clock-state-0: CLOCK_MANAGEMENT_STATE_DEFAULT, frequency set by "default-freq" + property of consumer node + +* clock-state-1: CLOCK_MANAGEMENT_STATE_SLEEP, frequency set by "sleep-freq" + property of consumer node + +* clock-state-2: CLOCK_MANAGEMENT_STATE_TEST1, frequency set by "test1-freq" + property of consumer node + +* clock-state-3: CLOCK_MANAGEMENT_STATE_TEST2, frequency set by "test2-freq" + property of consumer node + +* clock-state-4: CLOCK_MANAGEMENT_STATE_TEST3, frequency set by "test3-freq" + property of consumer node + +Devices should define these states to exercise as many clock node drivers as +possible. One example might be clocking from a PLL in the default state, a +high speed internal oscillator in the sleep state, and a low speed external +oscillator in the test state. Some states should avoid defining explicit +configuration settings, to verify that runtime clock set_rate APIs work as +expected. diff --git a/tests/drivers/clock_management/clock_management_hw/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay b/tests/drivers/clock_management/clock_management_hw/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay new file mode 100644 index 00000000000000..fd0dc4680f643c --- /dev/null +++ b/tests/drivers/clock_management/clock_management_hw/boards/lpcxpresso55s69_lpc55s69_cpu0.overlay @@ -0,0 +1,70 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* 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>; +}; + +/* Define clock states for clockout clock */ +&clkout_clock { + clkout_default: clkout-default { + compatible = "clock-state"; + /* Enable PLL1 and switch clkout to use it */ + clocks = <&xtal32m 1 &clk_in_en 1 &pll1clksel 1 &pll1_pdec 2 + &pll1_directo 0 &pll1 300000000 4 75 0 39 19 + &pll1_bypass 0 &clkoutsel 5 &clkoutdiv 2>; + clock-frequency = <75000000>; + }; + clkout_sleep: clkout-sleep { + compatible = "clock-state"; + clocks = <&fro_hf 1 &clkoutsel 3 &clkoutdiv 1>; + clock-frequency = <96000000>; + }; + clkout_test1: clkout-test1 { + /* Should use runtime frequency requests */ + compatible = "clock-state"; + clock-frequency = <73000000>; + }; + clkout_test2: clkout-test2 { + /* Should use runtime frequency requests */ + compatible = "clock-state"; + clock-frequency = <147640000>; + }; + clkout_test3: clkout-test3 { + /* Should use runtime frequency requests */ + compatible = "clock-state"; + clock-frequency = <1000000>; + }; +}; + +/ { + emul_dev: emul-dev { + compatible = "vnd,emul-clock-consumer"; + clock-outputs = <&clkout_clock>; + clock-output-names = "default"; + clock-state-0 = <&clkout_default>; + default-freq = <75000000>; + clock-state-1 = <&clkout_sleep>; + sleep-freq = <96000000>; + clock-state-2 = <&clkout_test1>; + test1-freq = <73000000>; + clock-state-3 = <&clkout_test2>; + test2-freq = <147640000>; + clock-state-4 = <&clkout_test3>; + test3-freq = <1000000>; + clock-state-names= "default", "sleep", "test1", + "test2", "test3"; + }; +}; diff --git a/tests/drivers/clock_management/clock_management_hw/dts/bindings/vnd,emul-clock-consumer.yaml b/tests/drivers/clock_management/clock_management_hw/dts/bindings/vnd,emul-clock-consumer.yaml new file mode 100644 index 00000000000000..c34faa0784bb2a --- /dev/null +++ b/tests/drivers/clock_management/clock_management_hw/dts/bindings/vnd,emul-clock-consumer.yaml @@ -0,0 +1,47 @@ +# Copyright 2024 NXP +# +# 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: + default-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying default clock + management state + + sleep-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying sleep clock + management state + + test1-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying test1 clock + management state + + test2-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying test2 clock + management state + + test3-freq: + type: int + required: true + description: | + Frequency this consumer expects to read when applying test3 clock + management state diff --git a/tests/drivers/clock_management/clock_management_hw/prj.conf b/tests/drivers/clock_management/clock_management_hw/prj.conf new file mode 100644 index 00000000000000..d21f18a659ed36 --- /dev/null +++ b/tests/drivers/clock_management/clock_management_hw/prj.conf @@ -0,0 +1,5 @@ +CONFIG_ZTEST=y +CONFIG_CLOCK_MANAGEMENT=y +CONFIG_CLOCK_MANAGEMENT_RUNTIME=y +CONFIG_CLOCK_MANAGEMENT_SET_RATE=y +CONFIG_ZTEST_STACK_SIZE=2048 diff --git a/tests/drivers/clock_management/clock_management_hw/src/test_clock_management_hw.c b/tests/drivers/clock_management/clock_management_hw/src/test_clock_management_hw.c new file mode 100644 index 00000000000000..a310e18068539e --- /dev/null +++ b/tests/drivers/clock_management/clock_management_hw/src/test_clock_management_hw.c @@ -0,0 +1,62 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +LOG_MODULE_REGISTER(test); + +#define CONSUMER_NODE DT_NODELABEL(emul_dev) + +CLOCK_MANAGEMENT_DT_DEFINE_OUTPUT_BY_NAME(CONSUMER_NODE, default); + +/* Get references to each clock management state and output */ +static const struct clock_output *dev_out = + CLOCK_MANAGEMENT_DT_GET_OUTPUT_BY_NAME(CONSUMER_NODE, default); +static clock_management_state_t dev_default = + CLOCK_MANAGEMENT_DT_GET_STATE(CONSUMER_NODE, default, default); +static clock_management_state_t dev_sleep = + CLOCK_MANAGEMENT_DT_GET_STATE(CONSUMER_NODE, default, sleep); +static clock_management_state_t dev_test1 = + CLOCK_MANAGEMENT_DT_GET_STATE(CONSUMER_NODE, default, test1); +static clock_management_state_t dev_test2 = + CLOCK_MANAGEMENT_DT_GET_STATE(CONSUMER_NODE, default, test2); +static clock_management_state_t dev_test3 = + CLOCK_MANAGEMENT_DT_GET_STATE(CONSUMER_NODE, default, test3); + +void apply_clock_state(clock_management_state_t state, const char *state_name, + int expected_rate) +{ + int ret; + + /* Apply clock state, verify frequencies */ + TC_PRINT("Try to apply %s clock state\n", state_name); + + ret = clock_management_apply_state(dev_out, state); + zassert_equal(ret, expected_rate, + "Failed to apply %s clock management state", state_name); + + /* Check rate */ + ret = clock_management_get_rate(dev_out); + TC_PRINT("Consumer %s clock rate: %d\n", state_name, ret); + zassert_equal(ret, expected_rate, + "Consumer has invalid %s clock rate", state_name); +} + +ZTEST(clock_management_hw, test_apply_states) +{ + apply_clock_state(dev_default, "default", + DT_PROP(CONSUMER_NODE, default_freq)); + apply_clock_state(dev_sleep, "sleep", + DT_PROP(CONSUMER_NODE, sleep_freq)); + apply_clock_state(dev_test1, "test1", + DT_PROP(CONSUMER_NODE, test1_freq)); + apply_clock_state(dev_test2, "test2", + DT_PROP(CONSUMER_NODE, test2_freq)); + apply_clock_state(dev_test3, "test3", + DT_PROP(CONSUMER_NODE, test3_freq)); +} + +ZTEST_SUITE(clock_management_hw, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/clock_management/clock_management_hw/testcase.yaml b/tests/drivers/clock_management/clock_management_hw/testcase.yaml new file mode 100644 index 00000000000000..7a37d34e7c04fe --- /dev/null +++ b/tests/drivers/clock_management/clock_management_hw/testcase.yaml @@ -0,0 +1,8 @@ +tests: + drivers.clock_management.hw: + tags: + - drivers + - clock_management + integration_platforms: + - lpcxpresso55s69/lpc55s69/cpu0 + filter: dt_compat_enabled("vnd,emul-clock-consumer")