Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: gate: Add some kunit test suites

Test various parts of the clk gate implementation with the kunit testing
framework.

Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Acked-by: Daniel Latypov <dlatypov@google.com>
Cc: <kunit-dev@googlegroups.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Link: https://lore.kernel.org/r/20220120175902.2165958-1-sboyd@kernel.org

+476
+3
drivers/clk/.kunitconfig
··· 1 + CONFIG_KUNIT=y 2 + CONFIG_COMMON_CLK=y 3 + CONFIG_CLK_GATE_KUNIT_TEST=y
+8
drivers/clk/Kconfig
··· 428 428 source "drivers/clk/xilinx/Kconfig" 429 429 source "drivers/clk/zynqmp/Kconfig" 430 430 431 + # Kunit test cases 432 + config CLK_GATE_KUNIT_TEST 433 + tristate "Basic gate type Kunit test" if !KUNIT_ALL_TESTS 434 + depends on KUNIT 435 + default KUNIT_ALL_TESTS 436 + help 437 + Kunit test for the basic clk gate type. 438 + 431 439 endif
+1
drivers/clk/Makefile
··· 6 6 obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o 7 7 obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o 8 8 obj-$(CONFIG_COMMON_CLK) += clk-gate.o 9 + obj-$(CONFIG_CLK_GATE_KUNIT_TEST) += clk-gate_test.o 9 10 obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o 10 11 obj-$(CONFIG_COMMON_CLK) += clk-mux.o 11 12 obj-$(CONFIG_COMMON_CLK) += clk-composite.o
+464
drivers/clk/clk-gate_test.c
··· 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");