1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Kunit test for clk gate basic type
4 */
5#include <linux/clk.h>
6#include <linux/clk-provider.h>
7#include <linux/platform_device.h>
8
9#include <kunit/test.h>
10
11static void clk_gate_register_test_dev(struct kunit *test)
12{
13 struct clk_hw *ret;
14 struct platform_device *pdev;
15
16 pdev = platform_device_register_simple(name: "test_gate_device", id: -1, NULL, num: 0);
17 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
18
19 ret = clk_hw_register_gate(&pdev->dev, "test_gate", NULL, 0, NULL,
20 0, 0, NULL);
21 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
22 KUNIT_EXPECT_STREQ(test, "test_gate", clk_hw_get_name(ret));
23 KUNIT_EXPECT_EQ(test, 0UL, clk_hw_get_flags(ret));
24
25 clk_hw_unregister_gate(hw: ret);
26 platform_device_put(pdev);
27}
28
29static void clk_gate_register_test_parent_names(struct kunit *test)
30{
31 struct clk_hw *parent;
32 struct clk_hw *ret;
33
34 parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0,
35 1000000);
36 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
37
38 ret = clk_hw_register_gate(NULL, "test_gate", "test_parent", 0, NULL,
39 0, 0, NULL);
40 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
41 KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret));
42
43 clk_hw_unregister_gate(hw: ret);
44 clk_hw_unregister_fixed_rate(hw: parent);
45}
46
47static void clk_gate_register_test_parent_data(struct kunit *test)
48{
49 struct clk_hw *parent;
50 struct clk_hw *ret;
51 struct clk_parent_data pdata = { };
52
53 parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0,
54 1000000);
55 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
56 pdata.hw = parent;
57
58 ret = clk_hw_register_gate_parent_data(NULL, "test_gate", &pdata, 0,
59 NULL, 0, 0, NULL);
60 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
61 KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret));
62
63 clk_hw_unregister_gate(hw: ret);
64 clk_hw_unregister_fixed_rate(hw: parent);
65}
66
67static void clk_gate_register_test_parent_data_legacy(struct kunit *test)
68{
69 struct clk_hw *parent;
70 struct clk_hw *ret;
71 struct clk_parent_data pdata = { };
72
73 parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0,
74 1000000);
75 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
76 pdata.name = "test_parent";
77
78 ret = clk_hw_register_gate_parent_data(NULL, "test_gate", &pdata, 0,
79 NULL, 0, 0, NULL);
80 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
81 KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret));
82
83 clk_hw_unregister_gate(hw: ret);
84 clk_hw_unregister_fixed_rate(hw: parent);
85}
86
87static void clk_gate_register_test_parent_hw(struct kunit *test)
88{
89 struct clk_hw *parent;
90 struct clk_hw *ret;
91
92 parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0,
93 1000000);
94 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
95
96 ret = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0, NULL,
97 0, 0, NULL);
98 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
99 KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret));
100
101 clk_hw_unregister_gate(hw: ret);
102 clk_hw_unregister_fixed_rate(hw: parent);
103}
104
105static void clk_gate_register_test_hiword_invalid(struct kunit *test)
106{
107 struct clk_hw *ret;
108
109 ret = clk_hw_register_gate(NULL, "test_gate", NULL, 0, NULL,
110 20, CLK_GATE_HIWORD_MASK, NULL);
111
112 KUNIT_EXPECT_TRUE(test, IS_ERR(ret));
113}
114
115static struct kunit_case clk_gate_register_test_cases[] = {
116 KUNIT_CASE(clk_gate_register_test_dev),
117 KUNIT_CASE(clk_gate_register_test_parent_names),
118 KUNIT_CASE(clk_gate_register_test_parent_data),
119 KUNIT_CASE(clk_gate_register_test_parent_data_legacy),
120 KUNIT_CASE(clk_gate_register_test_parent_hw),
121 KUNIT_CASE(clk_gate_register_test_hiword_invalid),
122 {}
123};
124
125static struct kunit_suite clk_gate_register_test_suite = {
126 .name = "clk-gate-register-test",
127 .test_cases = clk_gate_register_test_cases,
128};
129
130struct clk_gate_test_context {
131 void __iomem *fake_mem;
132 struct clk_hw *hw;
133 struct clk_hw *parent;
134 __le32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
135};
136
137static struct clk_gate_test_context *clk_gate_test_alloc_ctx(struct kunit *test)
138{
139 struct clk_gate_test_context *ctx;
140
141 test->priv = ctx = kunit_kzalloc(test, size: sizeof(*ctx), GFP_KERNEL);
142 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
143 ctx->fake_mem = (void __force __iomem *)&ctx->fake_reg;
144
145 return ctx;
146}
147
148static void clk_gate_test_parent_rate(struct kunit *test)
149{
150 struct clk_gate_test_context *ctx = test->priv;
151 struct clk_hw *parent = ctx->parent;
152 struct clk_hw *hw = ctx->hw;
153 unsigned long prate = clk_hw_get_rate(hw: parent);
154 unsigned long rate = clk_hw_get_rate(hw);
155
156 KUNIT_EXPECT_EQ(test, prate, rate);
157}
158
159static void clk_gate_test_enable(struct kunit *test)
160{
161 struct clk_gate_test_context *ctx = test->priv;
162 struct clk_hw *parent = ctx->parent;
163 struct clk_hw *hw = ctx->hw;
164 struct clk *clk = hw->clk;
165 u32 enable_val = BIT(5);
166
167 KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
168
169 KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
170 KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
171 KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
172 KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
173 KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(parent));
174}
175
176static void clk_gate_test_disable(struct kunit *test)
177{
178 struct clk_gate_test_context *ctx = test->priv;
179 struct clk_hw *parent = ctx->parent;
180 struct clk_hw *hw = ctx->hw;
181 struct clk *clk = hw->clk;
182 u32 enable_val = BIT(5);
183 u32 disable_val = 0;
184
185 KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
186 KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
187
188 clk_disable_unprepare(clk);
189 KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
190 KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
191 KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
192 KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
193 KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(parent));
194}
195
196static struct kunit_case clk_gate_test_cases[] = {
197 KUNIT_CASE(clk_gate_test_parent_rate),
198 KUNIT_CASE(clk_gate_test_enable),
199 KUNIT_CASE(clk_gate_test_disable),
200 {}
201};
202
203static int clk_gate_test_init(struct kunit *test)
204{
205 struct clk_hw *parent;
206 struct clk_hw *hw;
207 struct clk_gate_test_context *ctx;
208
209 ctx = clk_gate_test_alloc_ctx(test);
210 parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0,
211 2000000);
212 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
213
214 hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0,
215 ctx->fake_mem, 5, 0, NULL);
216 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
217
218 ctx->hw = hw;
219 ctx->parent = parent;
220
221 return 0;
222}
223
224static void clk_gate_test_exit(struct kunit *test)
225{
226 struct clk_gate_test_context *ctx = test->priv;
227
228 clk_hw_unregister_gate(hw: ctx->hw);
229 clk_hw_unregister_fixed_rate(hw: ctx->parent);
230}
231
232static struct kunit_suite clk_gate_test_suite = {
233 .name = "clk-gate-test",
234 .init = clk_gate_test_init,
235 .exit = clk_gate_test_exit,
236 .test_cases = clk_gate_test_cases,
237};
238
239static void clk_gate_test_invert_enable(struct kunit *test)
240{
241 struct clk_gate_test_context *ctx = test->priv;
242 struct clk_hw *parent = ctx->parent;
243 struct clk_hw *hw = ctx->hw;
244 struct clk *clk = hw->clk;
245 u32 enable_val = 0;
246
247 KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
248
249 KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
250 KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
251 KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
252 KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
253 KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(parent));
254}
255
256static void clk_gate_test_invert_disable(struct kunit *test)
257{
258 struct clk_gate_test_context *ctx = test->priv;
259 struct clk_hw *parent = ctx->parent;
260 struct clk_hw *hw = ctx->hw;
261 struct clk *clk = hw->clk;
262 u32 enable_val = 0;
263 u32 disable_val = BIT(15);
264
265 KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
266 KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
267
268 clk_disable_unprepare(clk);
269 KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
270 KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
271 KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
272 KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
273 KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(parent));
274}
275
276static struct kunit_case clk_gate_test_invert_cases[] = {
277 KUNIT_CASE(clk_gate_test_invert_enable),
278 KUNIT_CASE(clk_gate_test_invert_disable),
279 {}
280};
281
282static int clk_gate_test_invert_init(struct kunit *test)
283{
284 struct clk_hw *parent;
285 struct clk_hw *hw;
286 struct clk_gate_test_context *ctx;
287
288 ctx = clk_gate_test_alloc_ctx(test);
289 parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0,
290 2000000);
291 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
292
293 ctx->fake_reg = cpu_to_le32(BIT(15)); /* Default to off */
294 hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0,
295 ctx->fake_mem, 15,
296 CLK_GATE_SET_TO_DISABLE, NULL);
297 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
298
299 ctx->hw = hw;
300 ctx->parent = parent;
301
302 return 0;
303}
304
305static struct kunit_suite clk_gate_test_invert_suite = {
306 .name = "clk-gate-invert-test",
307 .init = clk_gate_test_invert_init,
308 .exit = clk_gate_test_exit,
309 .test_cases = clk_gate_test_invert_cases,
310};
311
312static void clk_gate_test_hiword_enable(struct kunit *test)
313{
314 struct clk_gate_test_context *ctx = test->priv;
315 struct clk_hw *parent = ctx->parent;
316 struct clk_hw *hw = ctx->hw;
317 struct clk *clk = hw->clk;
318 u32 enable_val = BIT(9) | BIT(9 + 16);
319
320 KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
321
322 KUNIT_EXPECT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
323 KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw));
324 KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw));
325 KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent));
326 KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(parent));
327}
328
329static void clk_gate_test_hiword_disable(struct kunit *test)
330{
331 struct clk_gate_test_context *ctx = test->priv;
332 struct clk_hw *parent = ctx->parent;
333 struct clk_hw *hw = ctx->hw;
334 struct clk *clk = hw->clk;
335 u32 enable_val = BIT(9) | BIT(9 + 16);
336 u32 disable_val = BIT(9 + 16);
337
338 KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0);
339 KUNIT_ASSERT_EQ(test, enable_val, le32_to_cpu(ctx->fake_reg));
340
341 clk_disable_unprepare(clk);
342 KUNIT_EXPECT_EQ(test, disable_val, le32_to_cpu(ctx->fake_reg));
343 KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw));
344 KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw));
345 KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent));
346 KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(parent));
347}
348
349static struct kunit_case clk_gate_test_hiword_cases[] = {
350 KUNIT_CASE(clk_gate_test_hiword_enable),
351 KUNIT_CASE(clk_gate_test_hiword_disable),
352 {}
353};
354
355static int clk_gate_test_hiword_init(struct kunit *test)
356{
357 struct clk_hw *parent;
358 struct clk_hw *hw;
359 struct clk_gate_test_context *ctx;
360
361 ctx = clk_gate_test_alloc_ctx(test);
362 parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0,
363 2000000);
364 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent);
365
366 hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0,
367 ctx->fake_mem, 9,
368 CLK_GATE_HIWORD_MASK, NULL);
369 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
370
371 ctx->hw = hw;
372 ctx->parent = parent;
373
374 return 0;
375}
376
377static struct kunit_suite clk_gate_test_hiword_suite = {
378 .name = "clk-gate-hiword-test",
379 .init = clk_gate_test_hiword_init,
380 .exit = clk_gate_test_exit,
381 .test_cases = clk_gate_test_hiword_cases,
382};
383
384static void clk_gate_test_is_enabled(struct kunit *test)
385{
386 struct clk_hw *hw;
387 struct clk_gate_test_context *ctx;
388
389 ctx = clk_gate_test_alloc_ctx(test);
390 ctx->fake_reg = cpu_to_le32(BIT(7));
391 hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
392 0, NULL);
393 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
394 KUNIT_ASSERT_TRUE(test, clk_hw_is_enabled(hw));
395
396 clk_hw_unregister_gate(hw);
397}
398
399static void clk_gate_test_is_disabled(struct kunit *test)
400{
401 struct clk_hw *hw;
402 struct clk_gate_test_context *ctx;
403
404 ctx = clk_gate_test_alloc_ctx(test);
405 ctx->fake_reg = cpu_to_le32(BIT(4));
406 hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7,
407 0, NULL);
408 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
409 KUNIT_ASSERT_FALSE(test, clk_hw_is_enabled(hw));
410
411 clk_hw_unregister_gate(hw);
412}
413
414static void clk_gate_test_is_enabled_inverted(struct kunit *test)
415{
416 struct clk_hw *hw;
417 struct clk_gate_test_context *ctx;
418
419 ctx = clk_gate_test_alloc_ctx(test);
420 ctx->fake_reg = cpu_to_le32(BIT(31));
421 hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 2,
422 CLK_GATE_SET_TO_DISABLE, NULL);
423 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
424 KUNIT_ASSERT_TRUE(test, clk_hw_is_enabled(hw));
425
426 clk_hw_unregister_gate(hw);
427}
428
429static void clk_gate_test_is_disabled_inverted(struct kunit *test)
430{
431 struct clk_hw *hw;
432 struct clk_gate_test_context *ctx;
433
434 ctx = clk_gate_test_alloc_ctx(test);
435 ctx->fake_reg = cpu_to_le32(BIT(29));
436 hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 29,
437 CLK_GATE_SET_TO_DISABLE, NULL);
438 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw);
439 KUNIT_ASSERT_FALSE(test, clk_hw_is_enabled(hw));
440
441 clk_hw_unregister_gate(hw);
442}
443
444static struct kunit_case clk_gate_test_enabled_cases[] = {
445 KUNIT_CASE(clk_gate_test_is_enabled),
446 KUNIT_CASE(clk_gate_test_is_disabled),
447 KUNIT_CASE(clk_gate_test_is_enabled_inverted),
448 KUNIT_CASE(clk_gate_test_is_disabled_inverted),
449 {}
450};
451
452static struct kunit_suite clk_gate_test_enabled_suite = {
453 .name = "clk-gate-is_enabled-test",
454 .test_cases = clk_gate_test_enabled_cases,
455};
456
457kunit_test_suites(
458 &clk_gate_register_test_suite,
459 &clk_gate_test_suite,
460 &clk_gate_test_invert_suite,
461 &clk_gate_test_hiword_suite,
462 &clk_gate_test_enabled_suite
463);
464MODULE_LICENSE("GPL v2");
465

source code of linux/drivers/clk/clk-gate_test.c