1 From b50545c05484be6c9326377e03c69d165d3552f6 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Sat, 2 Apr 2022 17:27:40 +0200
4 Subject: [PATCH] clk: tests: Add some tests for orphan with multiple
7 Let's leverage the dummy mux with multiple parents we have to create a
8 mux whose default parent will never be registered, and thus will always
11 We can then create some tests to make sure that the clock API behaves
12 properly in such a case, and that the transition to a non-orphan clock
13 when we change the parent is done properly.
15 Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> # imx8mp
16 Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> # exynos4210, meson g12b
17 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
19 drivers/clk/clk_test.c | 173 +++++++++++++++++++++++++++++++++++++++++
20 1 file changed, 173 insertions(+)
22 --- a/drivers/clk/clk_test.c
23 +++ b/drivers/clk/clk_test.c
24 @@ -465,6 +465,178 @@ clk_multiple_parents_mux_test_suite = {
25 .test_cases = clk_multiple_parents_mux_test_cases,
29 +clk_orphan_transparent_multiple_parent_mux_test_init(struct kunit *test)
31 + struct clk_multiple_parent_ctx *ctx;
32 + const char *parents[2] = { "missing-parent", "proper-parent"};
35 + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
40 + ctx->parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("proper-parent",
41 + &clk_dummy_rate_ops,
43 + ctx->parents_ctx[1].rate = DUMMY_CLOCK_INIT_RATE;
44 + ret = clk_hw_register(NULL, &ctx->parents_ctx[1].hw);
48 + ctx->hw.init = CLK_HW_INIT_PARENTS("test-orphan-mux", parents,
49 + &clk_multiple_parents_mux_ops,
50 + CLK_SET_RATE_PARENT);
51 + ret = clk_hw_register(NULL, &ctx->hw);
59 +clk_orphan_transparent_multiple_parent_mux_test_exit(struct kunit *test)
61 + struct clk_multiple_parent_ctx *ctx = test->priv;
63 + clk_hw_unregister(&ctx->hw);
64 + clk_hw_unregister(&ctx->parents_ctx[1].hw);
68 + * Test that, for a mux whose current parent hasn't been registered yet,
69 + * calling clk_set_parent() to a valid parent will properly update the
70 + * mux parent and its orphan status.
73 +clk_test_orphan_transparent_multiple_parent_mux_set_parent(struct kunit *test)
75 + struct clk_multiple_parent_ctx *ctx = test->priv;
76 + struct clk_hw *hw = &ctx->hw;
77 + struct clk *clk = hw->clk;
78 + struct clk *parent, *new_parent;
81 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
82 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
84 + ret = clk_set_parent(clk, parent);
85 + KUNIT_ASSERT_EQ(test, ret, 0);
87 + new_parent = clk_get_parent(clk);
88 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
89 + KUNIT_EXPECT_TRUE(test, clk_is_match(parent, new_parent));
95 + * Test that, for a mux that started orphan but got switched to a valid
96 + * parent, the rate of the mux and its new parent are consistent.
99 +clk_test_orphan_transparent_multiple_parent_mux_set_parent_get_rate(struct kunit *test)
101 + struct clk_multiple_parent_ctx *ctx = test->priv;
102 + struct clk_hw *hw = &ctx->hw;
103 + struct clk *clk = hw->clk;
104 + struct clk *parent;
105 + unsigned long parent_rate, rate;
108 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
109 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
111 + parent_rate = clk_get_rate(parent);
112 + KUNIT_ASSERT_GT(test, parent_rate, 0);
114 + ret = clk_set_parent(clk, parent);
115 + KUNIT_ASSERT_EQ(test, ret, 0);
117 + rate = clk_get_rate(clk);
118 + KUNIT_ASSERT_GT(test, rate, 0);
119 + KUNIT_EXPECT_EQ(test, parent_rate, rate);
123 + * Test that, for a mux that started orphan but got switched to a valid
124 + * parent, calling clk_set_rate_range() will affect the parent state if
125 + * its rate is out of range.
128 +clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified(struct kunit *test)
130 + struct clk_multiple_parent_ctx *ctx = test->priv;
131 + struct clk_hw *hw = &ctx->hw;
132 + struct clk *clk = hw->clk, *parent;
133 + unsigned long rate;
136 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
137 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
139 + ret = clk_set_parent(clk, parent);
140 + KUNIT_ASSERT_EQ(test, ret, 0);
142 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
143 + KUNIT_ASSERT_EQ(test, ret, 0);
145 + rate = clk_get_rate(clk);
146 + KUNIT_ASSERT_GT(test, rate, 0);
147 + KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1);
148 + KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
154 + * Test that, for a mux whose current parent hasn't been registered yet,
155 + * calling clk_set_rate_range() will succeed, and will be taken into
156 + * account when rounding a rate.
159 +clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate(struct kunit *test)
161 + struct clk_multiple_parent_ctx *ctx = test->priv;
162 + struct clk_hw *hw = &ctx->hw;
163 + struct clk *clk = hw->clk;
164 + unsigned long rate;
167 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
168 + KUNIT_ASSERT_EQ(test, ret, 0);
170 + rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000);
171 + KUNIT_ASSERT_GT(test, rate, 0);
172 + KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1);
173 + KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
176 +static struct kunit_case clk_orphan_transparent_multiple_parent_mux_test_cases[] = {
177 + KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent),
178 + KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_get_rate),
179 + KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified),
180 + KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate),
185 + * Test suite for a basic mux clock with two parents. The default parent
186 + * isn't registered, only the second parent is. By default, the clock
187 + * will thus be orphan.
189 + * These tests are supposed to exercise the behaviour of the consumer
190 + * API when dealing with an orphan clock, and how we deal with the
191 + * transition to a valid parent.
193 +static struct kunit_suite clk_orphan_transparent_multiple_parent_mux_test_suite = {
194 + .name = "clk-orphan-transparent-multiple-parent-mux-test",
195 + .init = clk_orphan_transparent_multiple_parent_mux_test_init,
196 + .exit = clk_orphan_transparent_multiple_parent_mux_test_exit,
197 + .test_cases = clk_orphan_transparent_multiple_parent_mux_test_cases,
200 struct clk_single_parent_ctx {
201 struct clk_dummy_context parent_ctx;
203 @@ -1410,6 +1582,7 @@ static struct kunit_suite clk_range_mini
206 &clk_multiple_parents_mux_test_suite,
207 + &clk_orphan_transparent_multiple_parent_mux_test_suite,
208 &clk_orphan_transparent_single_parent_test_suite,
209 &clk_range_test_suite,
210 &clk_range_maximize_test_suite,