xref: /openbmc/linux/drivers/clk/clk-gate_test.c (revision 4b33b5ff)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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