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