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
clk_gate_register_test_dev(struct kunit * test)11 static 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("test_gate_device", -1, NULL, 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(ret);
26 platform_device_put(pdev);
27 }
28
clk_gate_register_test_parent_names(struct kunit * test)29 static 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(ret);
44 clk_hw_unregister_fixed_rate(parent);
45 }
46
clk_gate_register_test_parent_data(struct kunit * test)47 static 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(ret);
64 clk_hw_unregister_fixed_rate(parent);
65 }
66
clk_gate_register_test_parent_data_legacy(struct kunit * test)67 static 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(ret);
84 clk_hw_unregister_fixed_rate(parent);
85 }
86
clk_gate_register_test_parent_hw(struct kunit * test)87 static 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(ret);
102 clk_hw_unregister_fixed_rate(parent);
103 }
104
clk_gate_register_test_hiword_invalid(struct kunit * test)105 static 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
115 static 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
125 static struct kunit_suite clk_gate_register_test_suite = {
126 .name = "clk-gate-register-test",
127 .test_cases = clk_gate_register_test_cases,
128 };
129
130 struct clk_gate_test_context {
131 void __iomem *fake_mem;
132 struct clk_hw *hw;
133 struct clk_hw *parent;
134 u32 fake_reg; /* Keep at end, KASAN can detect out of bounds */
135 };
136
clk_gate_test_alloc_ctx(struct kunit * test)137 static 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, 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
clk_gate_test_parent_rate(struct kunit * test)148 static 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(parent);
154 unsigned long rate = clk_hw_get_rate(hw);
155
156 KUNIT_EXPECT_EQ(test, prate, rate);
157 }
158
clk_gate_test_enable(struct kunit * test)159 static 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, 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
clk_gate_test_disable(struct kunit * test)176 static 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, ctx->fake_reg);
187
188 clk_disable_unprepare(clk);
189 KUNIT_EXPECT_EQ(test, disable_val, 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
196 static 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
clk_gate_test_init(struct kunit * test)203 static 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
clk_gate_test_exit(struct kunit * test)224 static void clk_gate_test_exit(struct kunit *test)
225 {
226 struct clk_gate_test_context *ctx = test->priv;
227
228 clk_hw_unregister_gate(ctx->hw);
229 clk_hw_unregister_fixed_rate(ctx->parent);
230 }
231
232 static 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
clk_gate_test_invert_enable(struct kunit * test)239 static 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, 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
clk_gate_test_invert_disable(struct kunit * test)256 static 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, ctx->fake_reg);
267
268 clk_disable_unprepare(clk);
269 KUNIT_EXPECT_EQ(test, disable_val, 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
276 static 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
clk_gate_test_invert_init(struct kunit * test)282 static 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 = 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
305 static 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
clk_gate_test_hiword_enable(struct kunit * test)312 static 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, 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
clk_gate_test_hiword_disable(struct kunit * test)329 static 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, ctx->fake_reg);
340
341 clk_disable_unprepare(clk);
342 KUNIT_EXPECT_EQ(test, disable_val, 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
349 static 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
clk_gate_test_hiword_init(struct kunit * test)355 static 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
377 static 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
clk_gate_test_is_enabled(struct kunit * test)384 static 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 = 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
clk_gate_test_is_disabled(struct kunit * test)399 static 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 = 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
clk_gate_test_is_enabled_inverted(struct kunit * test)414 static 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 = 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
clk_gate_test_is_disabled_inverted(struct kunit * test)429 static 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 = 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
444 static 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
452 static 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
457 kunit_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 );
464 MODULE_LICENSE("GPL v2");
465