4f24f99cd4780d8ae28df9438944cdbba572a709
[openwrt/staging/linusw.git] /
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
5 parents
6
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
9 be orphan by default.
10
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.
14
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>
18 ---
19 drivers/clk/clk_test.c | 173 +++++++++++++++++++++++++++++++++++++++++
20 1 file changed, 173 insertions(+)
21
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,
26 };
27
28 +static int
29 +clk_orphan_transparent_multiple_parent_mux_test_init(struct kunit *test)
30 +{
31 + struct clk_multiple_parent_ctx *ctx;
32 + const char *parents[2] = { "missing-parent", "proper-parent"};
33 + int ret;
34 +
35 + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
36 + if (!ctx)
37 + return -ENOMEM;
38 + test->priv = ctx;
39 +
40 + ctx->parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("proper-parent",
41 + &clk_dummy_rate_ops,
42 + 0);
43 + ctx->parents_ctx[1].rate = DUMMY_CLOCK_INIT_RATE;
44 + ret = clk_hw_register(NULL, &ctx->parents_ctx[1].hw);
45 + if (ret)
46 + return ret;
47 +
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);
52 + if (ret)
53 + return ret;
54 +
55 + return 0;
56 +}
57 +
58 +static void
59 +clk_orphan_transparent_multiple_parent_mux_test_exit(struct kunit *test)
60 +{
61 + struct clk_multiple_parent_ctx *ctx = test->priv;
62 +
63 + clk_hw_unregister(&ctx->hw);
64 + clk_hw_unregister(&ctx->parents_ctx[1].hw);
65 +}
66 +
67 +/*
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.
71 + */
72 +static void
73 +clk_test_orphan_transparent_multiple_parent_mux_set_parent(struct kunit *test)
74 +{
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;
79 + int ret;
80 +
81 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
82 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
83 +
84 + ret = clk_set_parent(clk, parent);
85 + KUNIT_ASSERT_EQ(test, ret, 0);
86 +
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));
90 +
91 + clk_put(parent);
92 +}
93 +
94 +/*
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.
97 + */
98 +static void
99 +clk_test_orphan_transparent_multiple_parent_mux_set_parent_get_rate(struct kunit *test)
100 +{
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;
106 + int ret;
107 +
108 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
109 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
110 +
111 + parent_rate = clk_get_rate(parent);
112 + KUNIT_ASSERT_GT(test, parent_rate, 0);
113 +
114 + ret = clk_set_parent(clk, parent);
115 + KUNIT_ASSERT_EQ(test, ret, 0);
116 +
117 + rate = clk_get_rate(clk);
118 + KUNIT_ASSERT_GT(test, rate, 0);
119 + KUNIT_EXPECT_EQ(test, parent_rate, rate);
120 +}
121 +
122 +/*
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.
126 + */
127 +static void
128 +clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified(struct kunit *test)
129 +{
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;
134 + int ret;
135 +
136 + parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
137 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
138 +
139 + ret = clk_set_parent(clk, parent);
140 + KUNIT_ASSERT_EQ(test, ret, 0);
141 +
142 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
143 + KUNIT_ASSERT_EQ(test, ret, 0);
144 +
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);
149 +
150 + clk_put(parent);
151 +}
152 +
153 +/*
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.
157 + */
158 +static void
159 +clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate(struct kunit *test)
160 +{
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;
165 + int ret;
166 +
167 + ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2);
168 + KUNIT_ASSERT_EQ(test, ret, 0);
169 +
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);
174 +}
175 +
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),
181 + {}
182 +};
183 +
184 +/*
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.
188 + *
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.
192 + */
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,
198 +};
199 +
200 struct clk_single_parent_ctx {
201 struct clk_dummy_context parent_ctx;
202 struct clk_hw hw;
203 @@ -1410,6 +1582,7 @@ static struct kunit_suite clk_range_mini
204 kunit_test_suites(
205 &clk_test_suite,
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,