466 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Kunit tests for clk gate4 */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("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 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(ret);44 clk_hw_unregister_fixed_rate(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(ret);64 clk_hw_unregister_fixed_rate(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(ret);84 clk_hw_unregister_fixed_rate(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(ret);102 clk_hw_unregister_fixed_rate(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, 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(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(ctx->hw);229 clk_hw_unregister_fixed_rate(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_suite463);464MODULE_DESCRIPTION("Kunit tests for clk gate");465MODULE_LICENSE("GPL v2");466