162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Kunit test for clk rate management 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#include <linux/clk.h> 662306a36Sopenharmony_ci#include <linux/clk-provider.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* Needed for clk_hw_get_clk() */ 962306a36Sopenharmony_ci#include "clk.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <kunit/test.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define DUMMY_CLOCK_INIT_RATE (42 * 1000 * 1000) 1462306a36Sopenharmony_ci#define DUMMY_CLOCK_RATE_1 (142 * 1000 * 1000) 1562306a36Sopenharmony_ci#define DUMMY_CLOCK_RATE_2 (242 * 1000 * 1000) 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistruct clk_dummy_context { 1862306a36Sopenharmony_ci struct clk_hw hw; 1962306a36Sopenharmony_ci unsigned long rate; 2062306a36Sopenharmony_ci}; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic unsigned long clk_dummy_recalc_rate(struct clk_hw *hw, 2362306a36Sopenharmony_ci unsigned long parent_rate) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci struct clk_dummy_context *ctx = 2662306a36Sopenharmony_ci container_of(hw, struct clk_dummy_context, hw); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci return ctx->rate; 2962306a36Sopenharmony_ci} 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic int clk_dummy_determine_rate(struct clk_hw *hw, 3262306a36Sopenharmony_ci struct clk_rate_request *req) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci /* Just return the same rate without modifying it */ 3562306a36Sopenharmony_ci return 0; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic int clk_dummy_maximize_rate(struct clk_hw *hw, 3962306a36Sopenharmony_ci struct clk_rate_request *req) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci /* 4262306a36Sopenharmony_ci * If there's a maximum set, always run the clock at the maximum 4362306a36Sopenharmony_ci * allowed. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci if (req->max_rate < ULONG_MAX) 4662306a36Sopenharmony_ci req->rate = req->max_rate; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return 0; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int clk_dummy_minimize_rate(struct clk_hw *hw, 5262306a36Sopenharmony_ci struct clk_rate_request *req) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci /* 5562306a36Sopenharmony_ci * If there's a minimum set, always run the clock at the minimum 5662306a36Sopenharmony_ci * allowed. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci if (req->min_rate > 0) 5962306a36Sopenharmony_ci req->rate = req->min_rate; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int clk_dummy_set_rate(struct clk_hw *hw, 6562306a36Sopenharmony_ci unsigned long rate, 6662306a36Sopenharmony_ci unsigned long parent_rate) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci struct clk_dummy_context *ctx = 6962306a36Sopenharmony_ci container_of(hw, struct clk_dummy_context, hw); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci ctx->rate = rate; 7262306a36Sopenharmony_ci return 0; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic int clk_dummy_single_set_parent(struct clk_hw *hw, u8 index) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci if (index >= clk_hw_get_num_parents(hw)) 7862306a36Sopenharmony_ci return -EINVAL; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci return 0; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic u8 clk_dummy_single_get_parent(struct clk_hw *hw) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic const struct clk_ops clk_dummy_rate_ops = { 8962306a36Sopenharmony_ci .recalc_rate = clk_dummy_recalc_rate, 9062306a36Sopenharmony_ci .determine_rate = clk_dummy_determine_rate, 9162306a36Sopenharmony_ci .set_rate = clk_dummy_set_rate, 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic const struct clk_ops clk_dummy_maximize_rate_ops = { 9562306a36Sopenharmony_ci .recalc_rate = clk_dummy_recalc_rate, 9662306a36Sopenharmony_ci .determine_rate = clk_dummy_maximize_rate, 9762306a36Sopenharmony_ci .set_rate = clk_dummy_set_rate, 9862306a36Sopenharmony_ci}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic const struct clk_ops clk_dummy_minimize_rate_ops = { 10162306a36Sopenharmony_ci .recalc_rate = clk_dummy_recalc_rate, 10262306a36Sopenharmony_ci .determine_rate = clk_dummy_minimize_rate, 10362306a36Sopenharmony_ci .set_rate = clk_dummy_set_rate, 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic const struct clk_ops clk_dummy_single_parent_ops = { 10762306a36Sopenharmony_ci /* 10862306a36Sopenharmony_ci * FIXME: Even though we should probably be able to use 10962306a36Sopenharmony_ci * __clk_mux_determine_rate() here, if we use it and call 11062306a36Sopenharmony_ci * clk_round_rate() or clk_set_rate() with a rate lower than 11162306a36Sopenharmony_ci * what all the parents can provide, it will return -EINVAL. 11262306a36Sopenharmony_ci * 11362306a36Sopenharmony_ci * This is due to the fact that it has the undocumented 11462306a36Sopenharmony_ci * behaviour to always pick up the closest rate higher than the 11562306a36Sopenharmony_ci * requested rate. If we get something lower, it thus considers 11662306a36Sopenharmony_ci * that it's not acceptable and will return an error. 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * It's somewhat inconsistent and creates a weird threshold 11962306a36Sopenharmony_ci * between rates above the parent rate which would be rounded to 12062306a36Sopenharmony_ci * what the parent can provide, but rates below will simply 12162306a36Sopenharmony_ci * return an error. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci .determine_rate = __clk_mux_determine_rate_closest, 12462306a36Sopenharmony_ci .set_parent = clk_dummy_single_set_parent, 12562306a36Sopenharmony_ci .get_parent = clk_dummy_single_get_parent, 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistruct clk_multiple_parent_ctx { 12962306a36Sopenharmony_ci struct clk_dummy_context parents_ctx[2]; 13062306a36Sopenharmony_ci struct clk_hw hw; 13162306a36Sopenharmony_ci u8 current_parent; 13262306a36Sopenharmony_ci}; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic int clk_multiple_parents_mux_set_parent(struct clk_hw *hw, u8 index) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = 13762306a36Sopenharmony_ci container_of(hw, struct clk_multiple_parent_ctx, hw); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if (index >= clk_hw_get_num_parents(hw)) 14062306a36Sopenharmony_ci return -EINVAL; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci ctx->current_parent = index; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci return 0; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic u8 clk_multiple_parents_mux_get_parent(struct clk_hw *hw) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = 15062306a36Sopenharmony_ci container_of(hw, struct clk_multiple_parent_ctx, hw); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return ctx->current_parent; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic const struct clk_ops clk_multiple_parents_mux_ops = { 15662306a36Sopenharmony_ci .get_parent = clk_multiple_parents_mux_get_parent, 15762306a36Sopenharmony_ci .set_parent = clk_multiple_parents_mux_set_parent, 15862306a36Sopenharmony_ci .determine_rate = __clk_mux_determine_rate_closest, 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic const struct clk_ops clk_multiple_parents_no_reparent_mux_ops = { 16262306a36Sopenharmony_ci .determine_rate = clk_hw_determine_rate_no_reparent, 16362306a36Sopenharmony_ci .get_parent = clk_multiple_parents_mux_get_parent, 16462306a36Sopenharmony_ci .set_parent = clk_multiple_parents_mux_set_parent, 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic int clk_test_init_with_ops(struct kunit *test, const struct clk_ops *ops) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci struct clk_dummy_context *ctx; 17062306a36Sopenharmony_ci struct clk_init_data init = { }; 17162306a36Sopenharmony_ci int ret; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 17462306a36Sopenharmony_ci if (!ctx) 17562306a36Sopenharmony_ci return -ENOMEM; 17662306a36Sopenharmony_ci ctx->rate = DUMMY_CLOCK_INIT_RATE; 17762306a36Sopenharmony_ci test->priv = ctx; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci init.name = "test_dummy_rate"; 18062306a36Sopenharmony_ci init.ops = ops; 18162306a36Sopenharmony_ci ctx->hw.init = &init; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 18462306a36Sopenharmony_ci if (ret) 18562306a36Sopenharmony_ci return ret; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci return 0; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int clk_test_init(struct kunit *test) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci return clk_test_init_with_ops(test, &clk_dummy_rate_ops); 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic int clk_maximize_test_init(struct kunit *test) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci return clk_test_init_with_ops(test, &clk_dummy_maximize_rate_ops); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int clk_minimize_test_init(struct kunit *test) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci return clk_test_init_with_ops(test, &clk_dummy_minimize_rate_ops); 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic void clk_test_exit(struct kunit *test) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci clk_hw_unregister(&ctx->hw); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci/* 21362306a36Sopenharmony_ci * Test that the actual rate matches what is returned by clk_get_rate() 21462306a36Sopenharmony_ci */ 21562306a36Sopenharmony_cistatic void clk_test_get_rate(struct kunit *test) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 21862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 21962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 22062306a36Sopenharmony_ci unsigned long rate; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci rate = clk_get_rate(clk); 22362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 22462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, ctx->rate); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci clk_put(clk); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/* 23062306a36Sopenharmony_ci * Test that, after a call to clk_set_rate(), the rate returned by 23162306a36Sopenharmony_ci * clk_get_rate() matches. 23262306a36Sopenharmony_ci * 23362306a36Sopenharmony_ci * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't 23462306a36Sopenharmony_ci * modify the requested rate, which is our case in clk_dummy_rate_ops. 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_cistatic void clk_test_set_get_rate(struct kunit *test) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 23962306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 24062306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 24162306a36Sopenharmony_ci unsigned long rate; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 24462306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_1), 24562306a36Sopenharmony_ci 0); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci rate = clk_get_rate(clk); 24862306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 24962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci clk_put(clk); 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci/* 25562306a36Sopenharmony_ci * Test that, after several calls to clk_set_rate(), the rate returned 25662306a36Sopenharmony_ci * by clk_get_rate() matches the last one. 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't 25962306a36Sopenharmony_ci * modify the requested rate, which is our case in clk_dummy_rate_ops. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_cistatic void clk_test_set_set_get_rate(struct kunit *test) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 26462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 26562306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 26662306a36Sopenharmony_ci unsigned long rate; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 26962306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_1), 27062306a36Sopenharmony_ci 0); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 27362306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_2), 27462306a36Sopenharmony_ci 0); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci rate = clk_get_rate(clk); 27762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 27862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci clk_put(clk); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci/* 28462306a36Sopenharmony_ci * Test that clk_round_rate and clk_set_rate are consitent and will 28562306a36Sopenharmony_ci * return the same frequency. 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_cistatic void clk_test_round_set_get_rate(struct kunit *test) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 29062306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 29162306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 29262306a36Sopenharmony_ci unsigned long set_rate; 29362306a36Sopenharmony_ci long rounded_rate; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci rounded_rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1); 29662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rounded_rate, 0); 29762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rounded_rate, DUMMY_CLOCK_RATE_1); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 30062306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_1), 30162306a36Sopenharmony_ci 0); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci set_rate = clk_get_rate(clk); 30462306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, set_rate, 0); 30562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rounded_rate, set_rate); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci clk_put(clk); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic struct kunit_case clk_test_cases[] = { 31162306a36Sopenharmony_ci KUNIT_CASE(clk_test_get_rate), 31262306a36Sopenharmony_ci KUNIT_CASE(clk_test_set_get_rate), 31362306a36Sopenharmony_ci KUNIT_CASE(clk_test_set_set_get_rate), 31462306a36Sopenharmony_ci KUNIT_CASE(clk_test_round_set_get_rate), 31562306a36Sopenharmony_ci {} 31662306a36Sopenharmony_ci}; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/* 31962306a36Sopenharmony_ci * Test suite for a basic rate clock, without any parent. 32062306a36Sopenharmony_ci * 32162306a36Sopenharmony_ci * These tests exercise the rate API with simple scenarios 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_cistatic struct kunit_suite clk_test_suite = { 32462306a36Sopenharmony_ci .name = "clk-test", 32562306a36Sopenharmony_ci .init = clk_test_init, 32662306a36Sopenharmony_ci .exit = clk_test_exit, 32762306a36Sopenharmony_ci .test_cases = clk_test_cases, 32862306a36Sopenharmony_ci}; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic int clk_uncached_test_init(struct kunit *test) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci struct clk_dummy_context *ctx; 33362306a36Sopenharmony_ci int ret; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 33662306a36Sopenharmony_ci if (!ctx) 33762306a36Sopenharmony_ci return -ENOMEM; 33862306a36Sopenharmony_ci test->priv = ctx; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci ctx->rate = DUMMY_CLOCK_INIT_RATE; 34162306a36Sopenharmony_ci ctx->hw.init = CLK_HW_INIT_NO_PARENT("test-clk", 34262306a36Sopenharmony_ci &clk_dummy_rate_ops, 34362306a36Sopenharmony_ci CLK_GET_RATE_NOCACHE); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 34662306a36Sopenharmony_ci if (ret) 34762306a36Sopenharmony_ci return ret; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci return 0; 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci/* 35362306a36Sopenharmony_ci * Test that for an uncached clock, the clock framework doesn't cache 35462306a36Sopenharmony_ci * the rate and clk_get_rate() will return the underlying clock rate 35562306a36Sopenharmony_ci * even if it changed. 35662306a36Sopenharmony_ci */ 35762306a36Sopenharmony_cistatic void clk_test_uncached_get_rate(struct kunit *test) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 36062306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 36162306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 36262306a36Sopenharmony_ci unsigned long rate; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci rate = clk_get_rate(clk); 36562306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 36662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_INIT_RATE); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci /* We change the rate behind the clock framework's back */ 36962306a36Sopenharmony_ci ctx->rate = DUMMY_CLOCK_RATE_1; 37062306a36Sopenharmony_ci rate = clk_get_rate(clk); 37162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 37262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci clk_put(clk); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci/* 37862306a36Sopenharmony_ci * Test that for an uncached clock, clk_set_rate_range() will work 37962306a36Sopenharmony_ci * properly if the rate hasn't changed. 38062306a36Sopenharmony_ci */ 38162306a36Sopenharmony_cistatic void clk_test_uncached_set_range(struct kunit *test) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 38462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 38562306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 38662306a36Sopenharmony_ci unsigned long rate; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 38962306a36Sopenharmony_ci clk_set_rate_range(clk, 39062306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 39162306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 39262306a36Sopenharmony_ci 0); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci rate = clk_get_rate(clk); 39562306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 39662306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 39762306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci clk_put(clk); 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci/* 40362306a36Sopenharmony_ci * Test that for an uncached clock, clk_set_rate_range() will work 40462306a36Sopenharmony_ci * properly if the rate has changed in hardware. 40562306a36Sopenharmony_ci * 40662306a36Sopenharmony_ci * In this case, it means that if the rate wasn't initially in the range 40762306a36Sopenharmony_ci * we're trying to set, but got changed at some point into the range 40862306a36Sopenharmony_ci * without the kernel knowing about it, its rate shouldn't be affected. 40962306a36Sopenharmony_ci */ 41062306a36Sopenharmony_cistatic void clk_test_uncached_updated_rate_set_range(struct kunit *test) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 41362306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 41462306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 41562306a36Sopenharmony_ci unsigned long rate; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* We change the rate behind the clock framework's back */ 41862306a36Sopenharmony_ci ctx->rate = DUMMY_CLOCK_RATE_1 + 1000; 41962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 42062306a36Sopenharmony_ci clk_set_rate_range(clk, 42162306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 42262306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 42362306a36Sopenharmony_ci 0); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci rate = clk_get_rate(clk); 42662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 42762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1 + 1000); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci clk_put(clk); 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic struct kunit_case clk_uncached_test_cases[] = { 43362306a36Sopenharmony_ci KUNIT_CASE(clk_test_uncached_get_rate), 43462306a36Sopenharmony_ci KUNIT_CASE(clk_test_uncached_set_range), 43562306a36Sopenharmony_ci KUNIT_CASE(clk_test_uncached_updated_rate_set_range), 43662306a36Sopenharmony_ci {} 43762306a36Sopenharmony_ci}; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/* 44062306a36Sopenharmony_ci * Test suite for a basic, uncached, rate clock, without any parent. 44162306a36Sopenharmony_ci * 44262306a36Sopenharmony_ci * These tests exercise the rate API with simple scenarios 44362306a36Sopenharmony_ci */ 44462306a36Sopenharmony_cistatic struct kunit_suite clk_uncached_test_suite = { 44562306a36Sopenharmony_ci .name = "clk-uncached-test", 44662306a36Sopenharmony_ci .init = clk_uncached_test_init, 44762306a36Sopenharmony_ci .exit = clk_test_exit, 44862306a36Sopenharmony_ci .test_cases = clk_uncached_test_cases, 44962306a36Sopenharmony_ci}; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic int 45262306a36Sopenharmony_ciclk_multiple_parents_mux_test_init(struct kunit *test) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx; 45562306a36Sopenharmony_ci const char *parents[2] = { "parent-0", "parent-1"}; 45662306a36Sopenharmony_ci int ret; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 45962306a36Sopenharmony_ci if (!ctx) 46062306a36Sopenharmony_ci return -ENOMEM; 46162306a36Sopenharmony_ci test->priv = ctx; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci ctx->parents_ctx[0].hw.init = CLK_HW_INIT_NO_PARENT("parent-0", 46462306a36Sopenharmony_ci &clk_dummy_rate_ops, 46562306a36Sopenharmony_ci 0); 46662306a36Sopenharmony_ci ctx->parents_ctx[0].rate = DUMMY_CLOCK_RATE_1; 46762306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parents_ctx[0].hw); 46862306a36Sopenharmony_ci if (ret) 46962306a36Sopenharmony_ci return ret; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci ctx->parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("parent-1", 47262306a36Sopenharmony_ci &clk_dummy_rate_ops, 47362306a36Sopenharmony_ci 0); 47462306a36Sopenharmony_ci ctx->parents_ctx[1].rate = DUMMY_CLOCK_RATE_2; 47562306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parents_ctx[1].hw); 47662306a36Sopenharmony_ci if (ret) 47762306a36Sopenharmony_ci return ret; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci ctx->current_parent = 0; 48062306a36Sopenharmony_ci ctx->hw.init = CLK_HW_INIT_PARENTS("test-mux", parents, 48162306a36Sopenharmony_ci &clk_multiple_parents_mux_ops, 48262306a36Sopenharmony_ci CLK_SET_RATE_PARENT); 48362306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 48462306a36Sopenharmony_ci if (ret) 48562306a36Sopenharmony_ci return ret; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci return 0; 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic void 49162306a36Sopenharmony_ciclk_multiple_parents_mux_test_exit(struct kunit *test) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci clk_hw_unregister(&ctx->hw); 49662306a36Sopenharmony_ci clk_hw_unregister(&ctx->parents_ctx[0].hw); 49762306a36Sopenharmony_ci clk_hw_unregister(&ctx->parents_ctx[1].hw); 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci/* 50162306a36Sopenharmony_ci * Test that for a clock with multiple parents, clk_get_parent() 50262306a36Sopenharmony_ci * actually returns the current one. 50362306a36Sopenharmony_ci */ 50462306a36Sopenharmony_cistatic void 50562306a36Sopenharmony_ciclk_test_multiple_parents_mux_get_parent(struct kunit *test) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 50862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 50962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 51062306a36Sopenharmony_ci struct clk *parent = clk_hw_get_clk(&ctx->parents_ctx[0].hw, NULL); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, clk_is_match(clk_get_parent(clk), parent)); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci clk_put(parent); 51562306a36Sopenharmony_ci clk_put(clk); 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci/* 51962306a36Sopenharmony_ci * Test that for a clock with a multiple parents, clk_has_parent() 52062306a36Sopenharmony_ci * actually reports all of them as parents. 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_cistatic void 52362306a36Sopenharmony_ciclk_test_multiple_parents_mux_has_parent(struct kunit *test) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 52662306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 52762306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 52862306a36Sopenharmony_ci struct clk *parent; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[0].hw, NULL); 53162306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, parent)); 53262306a36Sopenharmony_ci clk_put(parent); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 53562306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, parent)); 53662306a36Sopenharmony_ci clk_put(parent); 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci clk_put(clk); 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci/* 54262306a36Sopenharmony_ci * Test that for a clock with a multiple parents, if we set a range on 54362306a36Sopenharmony_ci * that clock and the parent is changed, its rate after the reparenting 54462306a36Sopenharmony_ci * is still within the range we asked for. 54562306a36Sopenharmony_ci * 54662306a36Sopenharmony_ci * FIXME: clk_set_parent() only does the reparenting but doesn't 54762306a36Sopenharmony_ci * reevaluate whether the new clock rate is within its boundaries or 54862306a36Sopenharmony_ci * not. 54962306a36Sopenharmony_ci */ 55062306a36Sopenharmony_cistatic void 55162306a36Sopenharmony_ciclk_test_multiple_parents_mux_set_range_set_parent_get_rate(struct kunit *test) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 55462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 55562306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 55662306a36Sopenharmony_ci struct clk *parent1, *parent2; 55762306a36Sopenharmony_ci unsigned long rate; 55862306a36Sopenharmony_ci int ret; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci kunit_skip(test, "This needs to be fixed in the core."); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci parent1 = clk_hw_get_clk(&ctx->parents_ctx[0].hw, NULL); 56362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent1); 56462306a36Sopenharmony_ci KUNIT_ASSERT_TRUE(test, clk_is_match(clk_get_parent(clk), parent1)); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci parent2 = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 56762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent2); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci ret = clk_set_rate(parent1, DUMMY_CLOCK_RATE_1); 57062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci ret = clk_set_rate(parent2, DUMMY_CLOCK_RATE_2); 57362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci ret = clk_set_rate_range(clk, 57662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1 - 1000, 57762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1 + 1000); 57862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci ret = clk_set_parent(clk, parent2); 58162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci rate = clk_get_rate(clk); 58462306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 58562306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1 - 1000); 58662306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_1 + 1000); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci clk_put(parent2); 58962306a36Sopenharmony_ci clk_put(parent1); 59062306a36Sopenharmony_ci clk_put(clk); 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic struct kunit_case clk_multiple_parents_mux_test_cases[] = { 59462306a36Sopenharmony_ci KUNIT_CASE(clk_test_multiple_parents_mux_get_parent), 59562306a36Sopenharmony_ci KUNIT_CASE(clk_test_multiple_parents_mux_has_parent), 59662306a36Sopenharmony_ci KUNIT_CASE(clk_test_multiple_parents_mux_set_range_set_parent_get_rate), 59762306a36Sopenharmony_ci {} 59862306a36Sopenharmony_ci}; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci/* 60162306a36Sopenharmony_ci * Test suite for a basic mux clock with two parents, with 60262306a36Sopenharmony_ci * CLK_SET_RATE_PARENT on the child. 60362306a36Sopenharmony_ci * 60462306a36Sopenharmony_ci * These tests exercise the consumer API and check that the state of the 60562306a36Sopenharmony_ci * child and parents are sane and consistent. 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_cistatic struct kunit_suite 60862306a36Sopenharmony_ciclk_multiple_parents_mux_test_suite = { 60962306a36Sopenharmony_ci .name = "clk-multiple-parents-mux-test", 61062306a36Sopenharmony_ci .init = clk_multiple_parents_mux_test_init, 61162306a36Sopenharmony_ci .exit = clk_multiple_parents_mux_test_exit, 61262306a36Sopenharmony_ci .test_cases = clk_multiple_parents_mux_test_cases, 61362306a36Sopenharmony_ci}; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic int 61662306a36Sopenharmony_ciclk_orphan_transparent_multiple_parent_mux_test_init(struct kunit *test) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx; 61962306a36Sopenharmony_ci const char *parents[2] = { "missing-parent", "proper-parent"}; 62062306a36Sopenharmony_ci int ret; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 62362306a36Sopenharmony_ci if (!ctx) 62462306a36Sopenharmony_ci return -ENOMEM; 62562306a36Sopenharmony_ci test->priv = ctx; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci ctx->parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("proper-parent", 62862306a36Sopenharmony_ci &clk_dummy_rate_ops, 62962306a36Sopenharmony_ci 0); 63062306a36Sopenharmony_ci ctx->parents_ctx[1].rate = DUMMY_CLOCK_INIT_RATE; 63162306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parents_ctx[1].hw); 63262306a36Sopenharmony_ci if (ret) 63362306a36Sopenharmony_ci return ret; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci ctx->hw.init = CLK_HW_INIT_PARENTS("test-orphan-mux", parents, 63662306a36Sopenharmony_ci &clk_multiple_parents_mux_ops, 63762306a36Sopenharmony_ci CLK_SET_RATE_PARENT); 63862306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 63962306a36Sopenharmony_ci if (ret) 64062306a36Sopenharmony_ci return ret; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci return 0; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic void 64662306a36Sopenharmony_ciclk_orphan_transparent_multiple_parent_mux_test_exit(struct kunit *test) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci clk_hw_unregister(&ctx->hw); 65162306a36Sopenharmony_ci clk_hw_unregister(&ctx->parents_ctx[1].hw); 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci/* 65562306a36Sopenharmony_ci * Test that, for a mux whose current parent hasn't been registered yet and is 65662306a36Sopenharmony_ci * thus orphan, clk_get_parent() will return NULL. 65762306a36Sopenharmony_ci */ 65862306a36Sopenharmony_cistatic void 65962306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_get_parent(struct kunit *test) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 66262306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 66362306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, clk_get_parent(clk), NULL); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci clk_put(clk); 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci/* 67162306a36Sopenharmony_ci * Test that, for a mux whose current parent hasn't been registered yet, 67262306a36Sopenharmony_ci * calling clk_set_parent() to a valid parent will properly update the 67362306a36Sopenharmony_ci * mux parent and its orphan status. 67462306a36Sopenharmony_ci */ 67562306a36Sopenharmony_cistatic void 67662306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_parent(struct kunit *test) 67762306a36Sopenharmony_ci{ 67862306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 67962306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 68062306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 68162306a36Sopenharmony_ci struct clk *parent, *new_parent; 68262306a36Sopenharmony_ci int ret; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 68562306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci ret = clk_set_parent(clk, parent); 68862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci new_parent = clk_get_parent(clk); 69162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 69262306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, clk_is_match(parent, new_parent)); 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci clk_put(parent); 69562306a36Sopenharmony_ci clk_put(clk); 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci/* 69962306a36Sopenharmony_ci * Test that, for a mux that started orphan but got switched to a valid 70062306a36Sopenharmony_ci * parent, calling clk_drop_range() on the mux won't affect the parent 70162306a36Sopenharmony_ci * rate. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_cistatic void 70462306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_parent_drop_range(struct kunit *test) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 70762306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 70862306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 70962306a36Sopenharmony_ci struct clk *parent; 71062306a36Sopenharmony_ci unsigned long parent_rate, new_parent_rate; 71162306a36Sopenharmony_ci int ret; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 71462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci parent_rate = clk_get_rate(parent); 71762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, parent_rate, 0); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci ret = clk_set_parent(clk, parent); 72062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci ret = clk_drop_range(clk); 72362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci new_parent_rate = clk_get_rate(clk); 72662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, new_parent_rate, 0); 72762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, parent_rate, new_parent_rate); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci clk_put(parent); 73062306a36Sopenharmony_ci clk_put(clk); 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci/* 73462306a36Sopenharmony_ci * Test that, for a mux that started orphan but got switched to a valid 73562306a36Sopenharmony_ci * parent, the rate of the mux and its new parent are consistent. 73662306a36Sopenharmony_ci */ 73762306a36Sopenharmony_cistatic void 73862306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_parent_get_rate(struct kunit *test) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 74162306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 74262306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 74362306a36Sopenharmony_ci struct clk *parent; 74462306a36Sopenharmony_ci unsigned long parent_rate, rate; 74562306a36Sopenharmony_ci int ret; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 74862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci parent_rate = clk_get_rate(parent); 75162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, parent_rate, 0); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci ret = clk_set_parent(clk, parent); 75462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci rate = clk_get_rate(clk); 75762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 75862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, parent_rate, rate); 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci clk_put(parent); 76162306a36Sopenharmony_ci clk_put(clk); 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/* 76562306a36Sopenharmony_ci * Test that, for a mux that started orphan but got switched to a valid 76662306a36Sopenharmony_ci * parent, calling clk_put() on the mux won't affect the parent rate. 76762306a36Sopenharmony_ci */ 76862306a36Sopenharmony_cistatic void 76962306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_parent_put(struct kunit *test) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 77262306a36Sopenharmony_ci struct clk *clk, *parent; 77362306a36Sopenharmony_ci unsigned long parent_rate, new_parent_rate; 77462306a36Sopenharmony_ci int ret; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 77762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci clk = clk_hw_get_clk(&ctx->hw, NULL); 78062306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, clk); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci parent_rate = clk_get_rate(parent); 78362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, parent_rate, 0); 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci ret = clk_set_parent(clk, parent); 78662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci clk_put(clk); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci new_parent_rate = clk_get_rate(parent); 79162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, new_parent_rate, 0); 79262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, parent_rate, new_parent_rate); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci clk_put(parent); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci/* 79862306a36Sopenharmony_ci * Test that, for a mux that started orphan but got switched to a valid 79962306a36Sopenharmony_ci * parent, calling clk_set_rate_range() will affect the parent state if 80062306a36Sopenharmony_ci * its rate is out of range. 80162306a36Sopenharmony_ci */ 80262306a36Sopenharmony_cistatic void 80362306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified(struct kunit *test) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 80662306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 80762306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 80862306a36Sopenharmony_ci struct clk *parent; 80962306a36Sopenharmony_ci unsigned long rate; 81062306a36Sopenharmony_ci int ret; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 81362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci ret = clk_set_parent(clk, parent); 81662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2); 81962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci rate = clk_get_rate(clk); 82262306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 82362306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 82462306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci clk_put(parent); 82762306a36Sopenharmony_ci clk_put(clk); 82862306a36Sopenharmony_ci} 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci/* 83162306a36Sopenharmony_ci * Test that, for a mux that started orphan but got switched to a valid 83262306a36Sopenharmony_ci * parent, calling clk_set_rate_range() won't affect the parent state if 83362306a36Sopenharmony_ci * its rate is within range. 83462306a36Sopenharmony_ci */ 83562306a36Sopenharmony_cistatic void 83662306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_untouched(struct kunit *test) 83762306a36Sopenharmony_ci{ 83862306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 83962306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 84062306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 84162306a36Sopenharmony_ci struct clk *parent; 84262306a36Sopenharmony_ci unsigned long parent_rate, new_parent_rate; 84362306a36Sopenharmony_ci int ret; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 84662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci parent_rate = clk_get_rate(parent); 84962306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, parent_rate, 0); 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci ret = clk_set_parent(clk, parent); 85262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci ret = clk_set_rate_range(clk, 85562306a36Sopenharmony_ci DUMMY_CLOCK_INIT_RATE - 1000, 85662306a36Sopenharmony_ci DUMMY_CLOCK_INIT_RATE + 1000); 85762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci new_parent_rate = clk_get_rate(parent); 86062306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, new_parent_rate, 0); 86162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, parent_rate, new_parent_rate); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci clk_put(parent); 86462306a36Sopenharmony_ci clk_put(clk); 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci/* 86862306a36Sopenharmony_ci * Test that, for a mux whose current parent hasn't been registered yet, 86962306a36Sopenharmony_ci * calling clk_set_rate_range() will succeed, and will be taken into 87062306a36Sopenharmony_ci * account when rounding a rate. 87162306a36Sopenharmony_ci */ 87262306a36Sopenharmony_cistatic void 87362306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate(struct kunit *test) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 87662306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 87762306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 87862306a36Sopenharmony_ci long rate; 87962306a36Sopenharmony_ci int ret; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2); 88262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000); 88562306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 88662306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 88762306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci clk_put(clk); 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci/* 89362306a36Sopenharmony_ci * Test that, for a mux that started orphan, was assigned and rate and 89462306a36Sopenharmony_ci * then got switched to a valid parent, its rate is eventually within 89562306a36Sopenharmony_ci * range. 89662306a36Sopenharmony_ci * 89762306a36Sopenharmony_ci * FIXME: Even though we update the rate as part of clk_set_parent(), we 89862306a36Sopenharmony_ci * don't evaluate whether that new rate is within range and needs to be 89962306a36Sopenharmony_ci * adjusted. 90062306a36Sopenharmony_ci */ 90162306a36Sopenharmony_cistatic void 90262306a36Sopenharmony_ciclk_test_orphan_transparent_multiple_parent_mux_set_range_set_parent_get_rate(struct kunit *test) 90362306a36Sopenharmony_ci{ 90462306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 90562306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 90662306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 90762306a36Sopenharmony_ci struct clk *parent; 90862306a36Sopenharmony_ci unsigned long rate; 90962306a36Sopenharmony_ci int ret; 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci kunit_skip(test, "This needs to be fixed in the core."); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci clk_hw_set_rate_range(hw, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2); 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 91662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci ret = clk_set_parent(clk, parent); 91962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci rate = clk_get_rate(clk); 92262306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 92362306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 92462306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci clk_put(parent); 92762306a36Sopenharmony_ci clk_put(clk); 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_cistatic struct kunit_case clk_orphan_transparent_multiple_parent_mux_test_cases[] = { 93162306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_get_parent), 93262306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent), 93362306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_drop_range), 93462306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_get_rate), 93562306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_put), 93662306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_modified), 93762306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_parent_set_range_untouched), 93862306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_range_round_rate), 93962306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_multiple_parent_mux_set_range_set_parent_get_rate), 94062306a36Sopenharmony_ci {} 94162306a36Sopenharmony_ci}; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci/* 94462306a36Sopenharmony_ci * Test suite for a basic mux clock with two parents. The default parent 94562306a36Sopenharmony_ci * isn't registered, only the second parent is. By default, the clock 94662306a36Sopenharmony_ci * will thus be orphan. 94762306a36Sopenharmony_ci * 94862306a36Sopenharmony_ci * These tests exercise the behaviour of the consumer API when dealing 94962306a36Sopenharmony_ci * with an orphan clock, and how we deal with the transition to a valid 95062306a36Sopenharmony_ci * parent. 95162306a36Sopenharmony_ci */ 95262306a36Sopenharmony_cistatic struct kunit_suite clk_orphan_transparent_multiple_parent_mux_test_suite = { 95362306a36Sopenharmony_ci .name = "clk-orphan-transparent-multiple-parent-mux-test", 95462306a36Sopenharmony_ci .init = clk_orphan_transparent_multiple_parent_mux_test_init, 95562306a36Sopenharmony_ci .exit = clk_orphan_transparent_multiple_parent_mux_test_exit, 95662306a36Sopenharmony_ci .test_cases = clk_orphan_transparent_multiple_parent_mux_test_cases, 95762306a36Sopenharmony_ci}; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_cistruct clk_single_parent_ctx { 96062306a36Sopenharmony_ci struct clk_dummy_context parent_ctx; 96162306a36Sopenharmony_ci struct clk_hw hw; 96262306a36Sopenharmony_ci}; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_cistatic int clk_single_parent_mux_test_init(struct kunit *test) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx; 96762306a36Sopenharmony_ci int ret; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 97062306a36Sopenharmony_ci if (!ctx) 97162306a36Sopenharmony_ci return -ENOMEM; 97262306a36Sopenharmony_ci test->priv = ctx; 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci ctx->parent_ctx.rate = DUMMY_CLOCK_INIT_RATE; 97562306a36Sopenharmony_ci ctx->parent_ctx.hw.init = 97662306a36Sopenharmony_ci CLK_HW_INIT_NO_PARENT("parent-clk", 97762306a36Sopenharmony_ci &clk_dummy_rate_ops, 97862306a36Sopenharmony_ci 0); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parent_ctx.hw); 98162306a36Sopenharmony_ci if (ret) 98262306a36Sopenharmony_ci return ret; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci ctx->hw.init = CLK_HW_INIT("test-clk", "parent-clk", 98562306a36Sopenharmony_ci &clk_dummy_single_parent_ops, 98662306a36Sopenharmony_ci CLK_SET_RATE_PARENT); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 98962306a36Sopenharmony_ci if (ret) 99062306a36Sopenharmony_ci return ret; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci return 0; 99362306a36Sopenharmony_ci} 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_cistatic void 99662306a36Sopenharmony_ciclk_single_parent_mux_test_exit(struct kunit *test) 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci clk_hw_unregister(&ctx->hw); 100162306a36Sopenharmony_ci clk_hw_unregister(&ctx->parent_ctx.hw); 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci/* 100562306a36Sopenharmony_ci * Test that for a clock with a single parent, clk_get_parent() actually 100662306a36Sopenharmony_ci * returns the parent. 100762306a36Sopenharmony_ci */ 100862306a36Sopenharmony_cistatic void 100962306a36Sopenharmony_ciclk_test_single_parent_mux_get_parent(struct kunit *test) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 101262306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 101362306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 101462306a36Sopenharmony_ci struct clk *parent = clk_hw_get_clk(&ctx->parent_ctx.hw, NULL); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, clk_is_match(clk_get_parent(clk), parent)); 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci clk_put(parent); 101962306a36Sopenharmony_ci clk_put(clk); 102062306a36Sopenharmony_ci} 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci/* 102362306a36Sopenharmony_ci * Test that for a clock with a single parent, clk_has_parent() actually 102462306a36Sopenharmony_ci * reports it as a parent. 102562306a36Sopenharmony_ci */ 102662306a36Sopenharmony_cistatic void 102762306a36Sopenharmony_ciclk_test_single_parent_mux_has_parent(struct kunit *test) 102862306a36Sopenharmony_ci{ 102962306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 103062306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 103162306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 103262306a36Sopenharmony_ci struct clk *parent = clk_hw_get_clk(&ctx->parent_ctx.hw, NULL); 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, parent)); 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci clk_put(parent); 103762306a36Sopenharmony_ci clk_put(clk); 103862306a36Sopenharmony_ci} 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci/* 104162306a36Sopenharmony_ci * Test that for a clock that can't modify its rate and with a single 104262306a36Sopenharmony_ci * parent, if we set disjoints range on the parent and then the child, 104362306a36Sopenharmony_ci * the second will return an error. 104462306a36Sopenharmony_ci * 104562306a36Sopenharmony_ci * FIXME: clk_set_rate_range() only considers the current clock when 104662306a36Sopenharmony_ci * evaluating whether ranges are disjoints and not the upstream clocks 104762306a36Sopenharmony_ci * ranges. 104862306a36Sopenharmony_ci */ 104962306a36Sopenharmony_cistatic void 105062306a36Sopenharmony_ciclk_test_single_parent_mux_set_range_disjoint_child_last(struct kunit *test) 105162306a36Sopenharmony_ci{ 105262306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 105362306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 105462306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 105562306a36Sopenharmony_ci struct clk *parent; 105662306a36Sopenharmony_ci int ret; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci kunit_skip(test, "This needs to be fixed in the core."); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci parent = clk_get_parent(clk); 106162306a36Sopenharmony_ci KUNIT_ASSERT_PTR_NE(test, parent, NULL); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci ret = clk_set_rate_range(parent, 1000, 2000); 106462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci ret = clk_set_rate_range(clk, 3000, 4000); 106762306a36Sopenharmony_ci KUNIT_EXPECT_LT(test, ret, 0); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci clk_put(clk); 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci/* 107362306a36Sopenharmony_ci * Test that for a clock that can't modify its rate and with a single 107462306a36Sopenharmony_ci * parent, if we set disjoints range on the child and then the parent, 107562306a36Sopenharmony_ci * the second will return an error. 107662306a36Sopenharmony_ci * 107762306a36Sopenharmony_ci * FIXME: clk_set_rate_range() only considers the current clock when 107862306a36Sopenharmony_ci * evaluating whether ranges are disjoints and not the downstream clocks 107962306a36Sopenharmony_ci * ranges. 108062306a36Sopenharmony_ci */ 108162306a36Sopenharmony_cistatic void 108262306a36Sopenharmony_ciclk_test_single_parent_mux_set_range_disjoint_parent_last(struct kunit *test) 108362306a36Sopenharmony_ci{ 108462306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 108562306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 108662306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 108762306a36Sopenharmony_ci struct clk *parent; 108862306a36Sopenharmony_ci int ret; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci kunit_skip(test, "This needs to be fixed in the core."); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci parent = clk_get_parent(clk); 109362306a36Sopenharmony_ci KUNIT_ASSERT_PTR_NE(test, parent, NULL); 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci ret = clk_set_rate_range(clk, 1000, 2000); 109662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci ret = clk_set_rate_range(parent, 3000, 4000); 109962306a36Sopenharmony_ci KUNIT_EXPECT_LT(test, ret, 0); 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci clk_put(clk); 110262306a36Sopenharmony_ci} 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci/* 110562306a36Sopenharmony_ci * Test that for a clock that can't modify its rate and with a single 110662306a36Sopenharmony_ci * parent, if we set a range on the parent and then call 110762306a36Sopenharmony_ci * clk_round_rate(), the boundaries of the parent are taken into 110862306a36Sopenharmony_ci * account. 110962306a36Sopenharmony_ci */ 111062306a36Sopenharmony_cistatic void 111162306a36Sopenharmony_ciclk_test_single_parent_mux_set_range_round_rate_parent_only(struct kunit *test) 111262306a36Sopenharmony_ci{ 111362306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 111462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 111562306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 111662306a36Sopenharmony_ci struct clk *parent; 111762306a36Sopenharmony_ci long rate; 111862306a36Sopenharmony_ci int ret; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci parent = clk_get_parent(clk); 112162306a36Sopenharmony_ci KUNIT_ASSERT_PTR_NE(test, parent, NULL); 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci ret = clk_set_rate_range(parent, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2); 112462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000); 112762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 112862306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 112962306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci clk_put(clk); 113262306a36Sopenharmony_ci} 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci/* 113562306a36Sopenharmony_ci * Test that for a clock that can't modify its rate and with a single 113662306a36Sopenharmony_ci * parent, if we set a range on the parent and a more restrictive one on 113762306a36Sopenharmony_ci * the child, and then call clk_round_rate(), the boundaries of the 113862306a36Sopenharmony_ci * two clocks are taken into account. 113962306a36Sopenharmony_ci */ 114062306a36Sopenharmony_cistatic void 114162306a36Sopenharmony_ciclk_test_single_parent_mux_set_range_round_rate_child_smaller(struct kunit *test) 114262306a36Sopenharmony_ci{ 114362306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 114462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 114562306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 114662306a36Sopenharmony_ci struct clk *parent; 114762306a36Sopenharmony_ci long rate; 114862306a36Sopenharmony_ci int ret; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci parent = clk_get_parent(clk); 115162306a36Sopenharmony_ci KUNIT_ASSERT_PTR_NE(test, parent, NULL); 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci ret = clk_set_rate_range(parent, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2); 115462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1 + 1000, DUMMY_CLOCK_RATE_2 - 1000); 115762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000); 116062306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 116162306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1 + 1000); 116262306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2 - 1000); 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_2 + 1000); 116562306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 116662306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1 + 1000); 116762306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2 - 1000); 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci clk_put(clk); 117062306a36Sopenharmony_ci} 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci/* 117362306a36Sopenharmony_ci * Test that for a clock that can't modify its rate and with a single 117462306a36Sopenharmony_ci * parent, if we set a range on the child and a more restrictive one on 117562306a36Sopenharmony_ci * the parent, and then call clk_round_rate(), the boundaries of the 117662306a36Sopenharmony_ci * two clocks are taken into account. 117762306a36Sopenharmony_ci */ 117862306a36Sopenharmony_cistatic void 117962306a36Sopenharmony_ciclk_test_single_parent_mux_set_range_round_rate_parent_smaller(struct kunit *test) 118062306a36Sopenharmony_ci{ 118162306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 118262306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 118362306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 118462306a36Sopenharmony_ci struct clk *parent; 118562306a36Sopenharmony_ci long rate; 118662306a36Sopenharmony_ci int ret; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci parent = clk_get_parent(clk); 118962306a36Sopenharmony_ci KUNIT_ASSERT_PTR_NE(test, parent, NULL); 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci ret = clk_set_rate_range(parent, DUMMY_CLOCK_RATE_1 + 1000, DUMMY_CLOCK_RATE_2 - 1000); 119262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci ret = clk_set_rate_range(clk, DUMMY_CLOCK_RATE_1, DUMMY_CLOCK_RATE_2); 119562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000); 119862306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 119962306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1 + 1000); 120062306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2 - 1000); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_2 + 1000); 120362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 120462306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1 + 1000); 120562306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2 - 1000); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci clk_put(clk); 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_cistatic struct kunit_case clk_single_parent_mux_test_cases[] = { 121162306a36Sopenharmony_ci KUNIT_CASE(clk_test_single_parent_mux_get_parent), 121262306a36Sopenharmony_ci KUNIT_CASE(clk_test_single_parent_mux_has_parent), 121362306a36Sopenharmony_ci KUNIT_CASE(clk_test_single_parent_mux_set_range_disjoint_child_last), 121462306a36Sopenharmony_ci KUNIT_CASE(clk_test_single_parent_mux_set_range_disjoint_parent_last), 121562306a36Sopenharmony_ci KUNIT_CASE(clk_test_single_parent_mux_set_range_round_rate_child_smaller), 121662306a36Sopenharmony_ci KUNIT_CASE(clk_test_single_parent_mux_set_range_round_rate_parent_only), 121762306a36Sopenharmony_ci KUNIT_CASE(clk_test_single_parent_mux_set_range_round_rate_parent_smaller), 121862306a36Sopenharmony_ci {} 121962306a36Sopenharmony_ci}; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci/* 122262306a36Sopenharmony_ci * Test suite for a basic mux clock with one parent, with 122362306a36Sopenharmony_ci * CLK_SET_RATE_PARENT on the child. 122462306a36Sopenharmony_ci * 122562306a36Sopenharmony_ci * These tests exercise the consumer API and check that the state of the 122662306a36Sopenharmony_ci * child and parent are sane and consistent. 122762306a36Sopenharmony_ci */ 122862306a36Sopenharmony_cistatic struct kunit_suite 122962306a36Sopenharmony_ciclk_single_parent_mux_test_suite = { 123062306a36Sopenharmony_ci .name = "clk-single-parent-mux-test", 123162306a36Sopenharmony_ci .init = clk_single_parent_mux_test_init, 123262306a36Sopenharmony_ci .exit = clk_single_parent_mux_test_exit, 123362306a36Sopenharmony_ci .test_cases = clk_single_parent_mux_test_cases, 123462306a36Sopenharmony_ci}; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_cistatic int clk_orphan_transparent_single_parent_mux_test_init(struct kunit *test) 123762306a36Sopenharmony_ci{ 123862306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx; 123962306a36Sopenharmony_ci struct clk_init_data init = { }; 124062306a36Sopenharmony_ci const char * const parents[] = { "orphan_parent" }; 124162306a36Sopenharmony_ci int ret; 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 124462306a36Sopenharmony_ci if (!ctx) 124562306a36Sopenharmony_ci return -ENOMEM; 124662306a36Sopenharmony_ci test->priv = ctx; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci init.name = "test_orphan_dummy_parent"; 124962306a36Sopenharmony_ci init.ops = &clk_dummy_single_parent_ops; 125062306a36Sopenharmony_ci init.parent_names = parents; 125162306a36Sopenharmony_ci init.num_parents = ARRAY_SIZE(parents); 125262306a36Sopenharmony_ci init.flags = CLK_SET_RATE_PARENT; 125362306a36Sopenharmony_ci ctx->hw.init = &init; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 125662306a36Sopenharmony_ci if (ret) 125762306a36Sopenharmony_ci return ret; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci memset(&init, 0, sizeof(init)); 126062306a36Sopenharmony_ci init.name = "orphan_parent"; 126162306a36Sopenharmony_ci init.ops = &clk_dummy_rate_ops; 126262306a36Sopenharmony_ci ctx->parent_ctx.hw.init = &init; 126362306a36Sopenharmony_ci ctx->parent_ctx.rate = DUMMY_CLOCK_INIT_RATE; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parent_ctx.hw); 126662306a36Sopenharmony_ci if (ret) 126762306a36Sopenharmony_ci return ret; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci return 0; 127062306a36Sopenharmony_ci} 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci/* 127362306a36Sopenharmony_ci * Test that a mux-only clock, with an initial rate within a range, 127462306a36Sopenharmony_ci * will still have the same rate after the range has been enforced. 127562306a36Sopenharmony_ci * 127662306a36Sopenharmony_ci * See: 127762306a36Sopenharmony_ci * https://lore.kernel.org/linux-clk/7720158d-10a7-a17b-73a4-a8615c9c6d5c@collabora.com/ 127862306a36Sopenharmony_ci */ 127962306a36Sopenharmony_cistatic void clk_test_orphan_transparent_parent_mux_set_range(struct kunit *test) 128062306a36Sopenharmony_ci{ 128162306a36Sopenharmony_ci struct clk_single_parent_ctx *ctx = test->priv; 128262306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 128362306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 128462306a36Sopenharmony_ci unsigned long rate, new_rate; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci rate = clk_get_rate(clk); 128762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 129062306a36Sopenharmony_ci clk_set_rate_range(clk, 129162306a36Sopenharmony_ci ctx->parent_ctx.rate - 1000, 129262306a36Sopenharmony_ci ctx->parent_ctx.rate + 1000), 129362306a36Sopenharmony_ci 0); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci new_rate = clk_get_rate(clk); 129662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, new_rate, 0); 129762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, new_rate); 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci clk_put(clk); 130062306a36Sopenharmony_ci} 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_cistatic struct kunit_case clk_orphan_transparent_single_parent_mux_test_cases[] = { 130362306a36Sopenharmony_ci KUNIT_CASE(clk_test_orphan_transparent_parent_mux_set_range), 130462306a36Sopenharmony_ci {} 130562306a36Sopenharmony_ci}; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci/* 130862306a36Sopenharmony_ci * Test suite for a basic mux clock with one parent. The parent is 130962306a36Sopenharmony_ci * registered after its child. The clock will thus be an orphan when 131062306a36Sopenharmony_ci * registered, but will no longer be when the tests run. 131162306a36Sopenharmony_ci * 131262306a36Sopenharmony_ci * These tests make sure a clock that used to be orphan has a sane, 131362306a36Sopenharmony_ci * consistent, behaviour. 131462306a36Sopenharmony_ci */ 131562306a36Sopenharmony_cistatic struct kunit_suite clk_orphan_transparent_single_parent_test_suite = { 131662306a36Sopenharmony_ci .name = "clk-orphan-transparent-single-parent-test", 131762306a36Sopenharmony_ci .init = clk_orphan_transparent_single_parent_mux_test_init, 131862306a36Sopenharmony_ci .exit = clk_single_parent_mux_test_exit, 131962306a36Sopenharmony_ci .test_cases = clk_orphan_transparent_single_parent_mux_test_cases, 132062306a36Sopenharmony_ci}; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_cistruct clk_single_parent_two_lvl_ctx { 132362306a36Sopenharmony_ci struct clk_dummy_context parent_parent_ctx; 132462306a36Sopenharmony_ci struct clk_dummy_context parent_ctx; 132562306a36Sopenharmony_ci struct clk_hw hw; 132662306a36Sopenharmony_ci}; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_cistatic int 132962306a36Sopenharmony_ciclk_orphan_two_level_root_last_test_init(struct kunit *test) 133062306a36Sopenharmony_ci{ 133162306a36Sopenharmony_ci struct clk_single_parent_two_lvl_ctx *ctx; 133262306a36Sopenharmony_ci int ret; 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 133562306a36Sopenharmony_ci if (!ctx) 133662306a36Sopenharmony_ci return -ENOMEM; 133762306a36Sopenharmony_ci test->priv = ctx; 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci ctx->parent_ctx.hw.init = 134062306a36Sopenharmony_ci CLK_HW_INIT("intermediate-parent", 134162306a36Sopenharmony_ci "root-parent", 134262306a36Sopenharmony_ci &clk_dummy_single_parent_ops, 134362306a36Sopenharmony_ci CLK_SET_RATE_PARENT); 134462306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parent_ctx.hw); 134562306a36Sopenharmony_ci if (ret) 134662306a36Sopenharmony_ci return ret; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci ctx->hw.init = 134962306a36Sopenharmony_ci CLK_HW_INIT("test-clk", "intermediate-parent", 135062306a36Sopenharmony_ci &clk_dummy_single_parent_ops, 135162306a36Sopenharmony_ci CLK_SET_RATE_PARENT); 135262306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 135362306a36Sopenharmony_ci if (ret) 135462306a36Sopenharmony_ci return ret; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci ctx->parent_parent_ctx.rate = DUMMY_CLOCK_INIT_RATE; 135762306a36Sopenharmony_ci ctx->parent_parent_ctx.hw.init = 135862306a36Sopenharmony_ci CLK_HW_INIT_NO_PARENT("root-parent", 135962306a36Sopenharmony_ci &clk_dummy_rate_ops, 136062306a36Sopenharmony_ci 0); 136162306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parent_parent_ctx.hw); 136262306a36Sopenharmony_ci if (ret) 136362306a36Sopenharmony_ci return ret; 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci return 0; 136662306a36Sopenharmony_ci} 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_cistatic void 136962306a36Sopenharmony_ciclk_orphan_two_level_root_last_test_exit(struct kunit *test) 137062306a36Sopenharmony_ci{ 137162306a36Sopenharmony_ci struct clk_single_parent_two_lvl_ctx *ctx = test->priv; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci clk_hw_unregister(&ctx->hw); 137462306a36Sopenharmony_ci clk_hw_unregister(&ctx->parent_ctx.hw); 137562306a36Sopenharmony_ci clk_hw_unregister(&ctx->parent_parent_ctx.hw); 137662306a36Sopenharmony_ci} 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci/* 137962306a36Sopenharmony_ci * Test that, for a clock whose parent used to be orphan, clk_get_rate() 138062306a36Sopenharmony_ci * will return the proper rate. 138162306a36Sopenharmony_ci */ 138262306a36Sopenharmony_cistatic void 138362306a36Sopenharmony_ciclk_orphan_two_level_root_last_test_get_rate(struct kunit *test) 138462306a36Sopenharmony_ci{ 138562306a36Sopenharmony_ci struct clk_single_parent_two_lvl_ctx *ctx = test->priv; 138662306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 138762306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 138862306a36Sopenharmony_ci unsigned long rate; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci rate = clk_get_rate(clk); 139162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_INIT_RATE); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci clk_put(clk); 139462306a36Sopenharmony_ci} 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci/* 139762306a36Sopenharmony_ci * Test that, for a clock whose parent used to be orphan, 139862306a36Sopenharmony_ci * clk_set_rate_range() won't affect its rate if it is already within 139962306a36Sopenharmony_ci * range. 140062306a36Sopenharmony_ci * 140162306a36Sopenharmony_ci * See (for Exynos 4210): 140262306a36Sopenharmony_ci * https://lore.kernel.org/linux-clk/366a0232-bb4a-c357-6aa8-636e398e05eb@samsung.com/ 140362306a36Sopenharmony_ci */ 140462306a36Sopenharmony_cistatic void 140562306a36Sopenharmony_ciclk_orphan_two_level_root_last_test_set_range(struct kunit *test) 140662306a36Sopenharmony_ci{ 140762306a36Sopenharmony_ci struct clk_single_parent_two_lvl_ctx *ctx = test->priv; 140862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 140962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 141062306a36Sopenharmony_ci unsigned long rate; 141162306a36Sopenharmony_ci int ret; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci ret = clk_set_rate_range(clk, 141462306a36Sopenharmony_ci DUMMY_CLOCK_INIT_RATE - 1000, 141562306a36Sopenharmony_ci DUMMY_CLOCK_INIT_RATE + 1000); 141662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci rate = clk_get_rate(clk); 141962306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 142062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_INIT_RATE); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci clk_put(clk); 142362306a36Sopenharmony_ci} 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_cistatic struct kunit_case 142662306a36Sopenharmony_ciclk_orphan_two_level_root_last_test_cases[] = { 142762306a36Sopenharmony_ci KUNIT_CASE(clk_orphan_two_level_root_last_test_get_rate), 142862306a36Sopenharmony_ci KUNIT_CASE(clk_orphan_two_level_root_last_test_set_range), 142962306a36Sopenharmony_ci {} 143062306a36Sopenharmony_ci}; 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci/* 143362306a36Sopenharmony_ci * Test suite for a basic, transparent, clock with a parent that is also 143462306a36Sopenharmony_ci * such a clock. The parent's parent is registered last, while the 143562306a36Sopenharmony_ci * parent and its child are registered in that order. The intermediate 143662306a36Sopenharmony_ci * and leaf clocks will thus be orphan when registered, but the leaf 143762306a36Sopenharmony_ci * clock itself will always have its parent and will never be 143862306a36Sopenharmony_ci * reparented. Indeed, it's only orphan because its parent is. 143962306a36Sopenharmony_ci * 144062306a36Sopenharmony_ci * These tests exercise the behaviour of the consumer API when dealing 144162306a36Sopenharmony_ci * with an orphan clock, and how we deal with the transition to a valid 144262306a36Sopenharmony_ci * parent. 144362306a36Sopenharmony_ci */ 144462306a36Sopenharmony_cistatic struct kunit_suite 144562306a36Sopenharmony_ciclk_orphan_two_level_root_last_test_suite = { 144662306a36Sopenharmony_ci .name = "clk-orphan-two-level-root-last-test", 144762306a36Sopenharmony_ci .init = clk_orphan_two_level_root_last_test_init, 144862306a36Sopenharmony_ci .exit = clk_orphan_two_level_root_last_test_exit, 144962306a36Sopenharmony_ci .test_cases = clk_orphan_two_level_root_last_test_cases, 145062306a36Sopenharmony_ci}; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci/* 145362306a36Sopenharmony_ci * Test that clk_set_rate_range won't return an error for a valid range 145462306a36Sopenharmony_ci * and that it will make sure the rate of the clock is within the 145562306a36Sopenharmony_ci * boundaries. 145662306a36Sopenharmony_ci */ 145762306a36Sopenharmony_cistatic void clk_range_test_set_range(struct kunit *test) 145862306a36Sopenharmony_ci{ 145962306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 146062306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 146162306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 146262306a36Sopenharmony_ci unsigned long rate; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 146562306a36Sopenharmony_ci clk_set_rate_range(clk, 146662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 146762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 146862306a36Sopenharmony_ci 0); 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci rate = clk_get_rate(clk); 147162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 147262306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 147362306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci clk_put(clk); 147662306a36Sopenharmony_ci} 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci/* 147962306a36Sopenharmony_ci * Test that calling clk_set_rate_range with a minimum rate higher than 148062306a36Sopenharmony_ci * the maximum rate returns an error. 148162306a36Sopenharmony_ci */ 148262306a36Sopenharmony_cistatic void clk_range_test_set_range_invalid(struct kunit *test) 148362306a36Sopenharmony_ci{ 148462306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 148562306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 148662306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci KUNIT_EXPECT_LT(test, 148962306a36Sopenharmony_ci clk_set_rate_range(clk, 149062306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1 + 1000, 149162306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1), 149262306a36Sopenharmony_ci 0); 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci clk_put(clk); 149562306a36Sopenharmony_ci} 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci/* 149862306a36Sopenharmony_ci * Test that users can't set multiple, disjoints, range that would be 149962306a36Sopenharmony_ci * impossible to meet. 150062306a36Sopenharmony_ci */ 150162306a36Sopenharmony_cistatic void clk_range_test_multiple_disjoints_range(struct kunit *test) 150262306a36Sopenharmony_ci{ 150362306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 150462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 150562306a36Sopenharmony_ci struct clk *user1, *user2; 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci user1 = clk_hw_get_clk(hw, NULL); 150862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1); 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci user2 = clk_hw_get_clk(hw, NULL); 151162306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2); 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 151462306a36Sopenharmony_ci clk_set_rate_range(user1, 1000, 2000), 151562306a36Sopenharmony_ci 0); 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci KUNIT_EXPECT_LT(test, 151862306a36Sopenharmony_ci clk_set_rate_range(user2, 3000, 4000), 151962306a36Sopenharmony_ci 0); 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci clk_put(user2); 152262306a36Sopenharmony_ci clk_put(user1); 152362306a36Sopenharmony_ci} 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci/* 152662306a36Sopenharmony_ci * Test that if our clock has some boundaries and we try to round a rate 152762306a36Sopenharmony_ci * lower than the minimum, the returned rate will be within range. 152862306a36Sopenharmony_ci */ 152962306a36Sopenharmony_cistatic void clk_range_test_set_range_round_rate_lower(struct kunit *test) 153062306a36Sopenharmony_ci{ 153162306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 153262306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 153362306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 153462306a36Sopenharmony_ci long rate; 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 153762306a36Sopenharmony_ci clk_set_rate_range(clk, 153862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 153962306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 154062306a36Sopenharmony_ci 0); 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000); 154362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 154462306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 154562306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci clk_put(clk); 154862306a36Sopenharmony_ci} 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci/* 155162306a36Sopenharmony_ci * Test that if our clock has some boundaries and we try to set a rate 155262306a36Sopenharmony_ci * higher than the maximum, the new rate will be within range. 155362306a36Sopenharmony_ci */ 155462306a36Sopenharmony_cistatic void clk_range_test_set_range_set_rate_lower(struct kunit *test) 155562306a36Sopenharmony_ci{ 155662306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 155762306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 155862306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 155962306a36Sopenharmony_ci unsigned long rate; 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 156262306a36Sopenharmony_ci clk_set_rate_range(clk, 156362306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 156462306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 156562306a36Sopenharmony_ci 0); 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 156862306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000), 156962306a36Sopenharmony_ci 0); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci rate = clk_get_rate(clk); 157262306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 157362306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 157462306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci clk_put(clk); 157762306a36Sopenharmony_ci} 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci/* 158062306a36Sopenharmony_ci * Test that if our clock has some boundaries and we try to round and 158162306a36Sopenharmony_ci * set a rate lower than the minimum, the rate returned by 158262306a36Sopenharmony_ci * clk_round_rate() will be consistent with the new rate set by 158362306a36Sopenharmony_ci * clk_set_rate(). 158462306a36Sopenharmony_ci */ 158562306a36Sopenharmony_cistatic void clk_range_test_set_range_set_round_rate_consistent_lower(struct kunit *test) 158662306a36Sopenharmony_ci{ 158762306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 158862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 158962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 159062306a36Sopenharmony_ci long rounded; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 159362306a36Sopenharmony_ci clk_set_rate_range(clk, 159462306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 159562306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 159662306a36Sopenharmony_ci 0); 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci rounded = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000); 159962306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rounded, 0); 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 160262306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000), 160362306a36Sopenharmony_ci 0); 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rounded, clk_get_rate(clk)); 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci clk_put(clk); 160862306a36Sopenharmony_ci} 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci/* 161162306a36Sopenharmony_ci * Test that if our clock has some boundaries and we try to round a rate 161262306a36Sopenharmony_ci * higher than the maximum, the returned rate will be within range. 161362306a36Sopenharmony_ci */ 161462306a36Sopenharmony_cistatic void clk_range_test_set_range_round_rate_higher(struct kunit *test) 161562306a36Sopenharmony_ci{ 161662306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 161762306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 161862306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 161962306a36Sopenharmony_ci long rate; 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 162262306a36Sopenharmony_ci clk_set_rate_range(clk, 162362306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 162462306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 162562306a36Sopenharmony_ci 0); 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_2 + 1000); 162862306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 162962306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 163062306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci clk_put(clk); 163362306a36Sopenharmony_ci} 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci/* 163662306a36Sopenharmony_ci * Test that if our clock has some boundaries and we try to set a rate 163762306a36Sopenharmony_ci * higher than the maximum, the new rate will be within range. 163862306a36Sopenharmony_ci */ 163962306a36Sopenharmony_cistatic void clk_range_test_set_range_set_rate_higher(struct kunit *test) 164062306a36Sopenharmony_ci{ 164162306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 164262306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 164362306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 164462306a36Sopenharmony_ci unsigned long rate; 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 164762306a36Sopenharmony_ci clk_set_rate_range(clk, 164862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 164962306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 165062306a36Sopenharmony_ci 0); 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 165362306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), 165462306a36Sopenharmony_ci 0); 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci rate = clk_get_rate(clk); 165762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 165862306a36Sopenharmony_ci KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1); 165962306a36Sopenharmony_ci KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2); 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci clk_put(clk); 166262306a36Sopenharmony_ci} 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci/* 166562306a36Sopenharmony_ci * Test that if our clock has some boundaries and we try to round and 166662306a36Sopenharmony_ci * set a rate higher than the maximum, the rate returned by 166762306a36Sopenharmony_ci * clk_round_rate() will be consistent with the new rate set by 166862306a36Sopenharmony_ci * clk_set_rate(). 166962306a36Sopenharmony_ci */ 167062306a36Sopenharmony_cistatic void clk_range_test_set_range_set_round_rate_consistent_higher(struct kunit *test) 167162306a36Sopenharmony_ci{ 167262306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 167362306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 167462306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 167562306a36Sopenharmony_ci long rounded; 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 167862306a36Sopenharmony_ci clk_set_rate_range(clk, 167962306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 168062306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 168162306a36Sopenharmony_ci 0); 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci rounded = clk_round_rate(clk, DUMMY_CLOCK_RATE_2 + 1000); 168462306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rounded, 0); 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 168762306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), 168862306a36Sopenharmony_ci 0); 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rounded, clk_get_rate(clk)); 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci clk_put(clk); 169362306a36Sopenharmony_ci} 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci/* 169662306a36Sopenharmony_ci * Test that if our clock has a rate lower than the minimum set by a 169762306a36Sopenharmony_ci * call to clk_set_rate_range(), the rate will be raised to match the 169862306a36Sopenharmony_ci * new minimum. 169962306a36Sopenharmony_ci * 170062306a36Sopenharmony_ci * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't 170162306a36Sopenharmony_ci * modify the requested rate, which is our case in clk_dummy_rate_ops. 170262306a36Sopenharmony_ci */ 170362306a36Sopenharmony_cistatic void clk_range_test_set_range_get_rate_raised(struct kunit *test) 170462306a36Sopenharmony_ci{ 170562306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 170662306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 170762306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 170862306a36Sopenharmony_ci unsigned long rate; 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 171162306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000), 171262306a36Sopenharmony_ci 0); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 171562306a36Sopenharmony_ci clk_set_rate_range(clk, 171662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 171762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 171862306a36Sopenharmony_ci 0); 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci rate = clk_get_rate(clk); 172162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 172262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci clk_put(clk); 172562306a36Sopenharmony_ci} 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci/* 172862306a36Sopenharmony_ci * Test that if our clock has a rate higher than the maximum set by a 172962306a36Sopenharmony_ci * call to clk_set_rate_range(), the rate will be lowered to match the 173062306a36Sopenharmony_ci * new maximum. 173162306a36Sopenharmony_ci * 173262306a36Sopenharmony_ci * This assumes that clk_ops.determine_rate or clk_ops.round_rate won't 173362306a36Sopenharmony_ci * modify the requested rate, which is our case in clk_dummy_rate_ops. 173462306a36Sopenharmony_ci */ 173562306a36Sopenharmony_cistatic void clk_range_test_set_range_get_rate_lowered(struct kunit *test) 173662306a36Sopenharmony_ci{ 173762306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 173862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 173962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 174062306a36Sopenharmony_ci unsigned long rate; 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 174362306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), 174462306a36Sopenharmony_ci 0); 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 174762306a36Sopenharmony_ci clk_set_rate_range(clk, 174862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 174962306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 175062306a36Sopenharmony_ci 0); 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci rate = clk_get_rate(clk); 175362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 175462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci clk_put(clk); 175762306a36Sopenharmony_ci} 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_cistatic struct kunit_case clk_range_test_cases[] = { 176062306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range), 176162306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_invalid), 176262306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_multiple_disjoints_range), 176362306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_round_rate_lower), 176462306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_set_rate_lower), 176562306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_set_round_rate_consistent_lower), 176662306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_round_rate_higher), 176762306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_set_rate_higher), 176862306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_set_round_rate_consistent_higher), 176962306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_get_rate_raised), 177062306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_get_rate_lowered), 177162306a36Sopenharmony_ci {} 177262306a36Sopenharmony_ci}; 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci/* 177562306a36Sopenharmony_ci * Test suite for a basic rate clock, without any parent. 177662306a36Sopenharmony_ci * 177762306a36Sopenharmony_ci * These tests exercise the rate range API: clk_set_rate_range(), 177862306a36Sopenharmony_ci * clk_set_min_rate(), clk_set_max_rate(), clk_drop_range(). 177962306a36Sopenharmony_ci */ 178062306a36Sopenharmony_cistatic struct kunit_suite clk_range_test_suite = { 178162306a36Sopenharmony_ci .name = "clk-range-test", 178262306a36Sopenharmony_ci .init = clk_test_init, 178362306a36Sopenharmony_ci .exit = clk_test_exit, 178462306a36Sopenharmony_ci .test_cases = clk_range_test_cases, 178562306a36Sopenharmony_ci}; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci/* 178862306a36Sopenharmony_ci * Test that if we have several subsequent calls to 178962306a36Sopenharmony_ci * clk_set_rate_range(), the core will reevaluate whether a new rate is 179062306a36Sopenharmony_ci * needed each and every time. 179162306a36Sopenharmony_ci * 179262306a36Sopenharmony_ci * With clk_dummy_maximize_rate_ops, this means that the rate will 179362306a36Sopenharmony_ci * trail along the maximum as it evolves. 179462306a36Sopenharmony_ci */ 179562306a36Sopenharmony_cistatic void clk_range_test_set_range_rate_maximized(struct kunit *test) 179662306a36Sopenharmony_ci{ 179762306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 179862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 179962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 180062306a36Sopenharmony_ci unsigned long rate; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 180362306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), 180462306a36Sopenharmony_ci 0); 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 180762306a36Sopenharmony_ci clk_set_rate_range(clk, 180862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 180962306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 181062306a36Sopenharmony_ci 0); 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci rate = clk_get_rate(clk); 181362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 181462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 181762306a36Sopenharmony_ci clk_set_rate_range(clk, 181862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 181962306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2 - 1000), 182062306a36Sopenharmony_ci 0); 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci rate = clk_get_rate(clk); 182362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 182462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2 - 1000); 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 182762306a36Sopenharmony_ci clk_set_rate_range(clk, 182862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 182962306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 183062306a36Sopenharmony_ci 0); 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci rate = clk_get_rate(clk); 183362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 183462306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci clk_put(clk); 183762306a36Sopenharmony_ci} 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci/* 184062306a36Sopenharmony_ci * Test that if we have several subsequent calls to 184162306a36Sopenharmony_ci * clk_set_rate_range(), across multiple users, the core will reevaluate 184262306a36Sopenharmony_ci * whether a new rate is needed each and every time. 184362306a36Sopenharmony_ci * 184462306a36Sopenharmony_ci * With clk_dummy_maximize_rate_ops, this means that the rate will 184562306a36Sopenharmony_ci * trail along the maximum as it evolves. 184662306a36Sopenharmony_ci */ 184762306a36Sopenharmony_cistatic void clk_range_test_multiple_set_range_rate_maximized(struct kunit *test) 184862306a36Sopenharmony_ci{ 184962306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 185062306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 185162306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 185262306a36Sopenharmony_ci struct clk *user1, *user2; 185362306a36Sopenharmony_ci unsigned long rate; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci user1 = clk_hw_get_clk(hw, NULL); 185662306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1); 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci user2 = clk_hw_get_clk(hw, NULL); 185962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2); 186062306a36Sopenharmony_ci 186162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 186262306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), 186362306a36Sopenharmony_ci 0); 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 186662306a36Sopenharmony_ci clk_set_rate_range(user1, 186762306a36Sopenharmony_ci 0, 186862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 186962306a36Sopenharmony_ci 0); 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci rate = clk_get_rate(clk); 187262306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 187362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 187662306a36Sopenharmony_ci clk_set_rate_range(user2, 187762306a36Sopenharmony_ci 0, 187862306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1), 187962306a36Sopenharmony_ci 0); 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci rate = clk_get_rate(clk); 188262306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 188362306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 188662306a36Sopenharmony_ci clk_drop_range(user2), 188762306a36Sopenharmony_ci 0); 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci rate = clk_get_rate(clk); 189062306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 189162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci clk_put(user2); 189462306a36Sopenharmony_ci clk_put(user1); 189562306a36Sopenharmony_ci clk_put(clk); 189662306a36Sopenharmony_ci} 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci/* 189962306a36Sopenharmony_ci * Test that if we have several subsequent calls to 190062306a36Sopenharmony_ci * clk_set_rate_range(), across multiple users, the core will reevaluate 190162306a36Sopenharmony_ci * whether a new rate is needed, including when a user drop its clock. 190262306a36Sopenharmony_ci * 190362306a36Sopenharmony_ci * With clk_dummy_maximize_rate_ops, this means that the rate will 190462306a36Sopenharmony_ci * trail along the maximum as it evolves. 190562306a36Sopenharmony_ci */ 190662306a36Sopenharmony_cistatic void clk_range_test_multiple_set_range_rate_put_maximized(struct kunit *test) 190762306a36Sopenharmony_ci{ 190862306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 190962306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 191062306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 191162306a36Sopenharmony_ci struct clk *user1, *user2; 191262306a36Sopenharmony_ci unsigned long rate; 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci user1 = clk_hw_get_clk(hw, NULL); 191562306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1); 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci user2 = clk_hw_get_clk(hw, NULL); 191862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2); 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 192162306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), 192262306a36Sopenharmony_ci 0); 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 192562306a36Sopenharmony_ci clk_set_rate_range(user1, 192662306a36Sopenharmony_ci 0, 192762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 192862306a36Sopenharmony_ci 0); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci rate = clk_get_rate(clk); 193162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 193262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 193562306a36Sopenharmony_ci clk_set_rate_range(user2, 193662306a36Sopenharmony_ci 0, 193762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1), 193862306a36Sopenharmony_ci 0); 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_ci rate = clk_get_rate(clk); 194162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 194262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci clk_put(user2); 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_ci rate = clk_get_rate(clk); 194762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 194862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci clk_put(user1); 195162306a36Sopenharmony_ci clk_put(clk); 195262306a36Sopenharmony_ci} 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_cistatic struct kunit_case clk_range_maximize_test_cases[] = { 195562306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_rate_maximized), 195662306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_multiple_set_range_rate_maximized), 195762306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_maximized), 195862306a36Sopenharmony_ci {} 195962306a36Sopenharmony_ci}; 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci/* 196262306a36Sopenharmony_ci * Test suite for a basic rate clock, without any parent. 196362306a36Sopenharmony_ci * 196462306a36Sopenharmony_ci * These tests exercise the rate range API: clk_set_rate_range(), 196562306a36Sopenharmony_ci * clk_set_min_rate(), clk_set_max_rate(), clk_drop_range(), with a 196662306a36Sopenharmony_ci * driver that will always try to run at the highest possible rate. 196762306a36Sopenharmony_ci */ 196862306a36Sopenharmony_cistatic struct kunit_suite clk_range_maximize_test_suite = { 196962306a36Sopenharmony_ci .name = "clk-range-maximize-test", 197062306a36Sopenharmony_ci .init = clk_maximize_test_init, 197162306a36Sopenharmony_ci .exit = clk_test_exit, 197262306a36Sopenharmony_ci .test_cases = clk_range_maximize_test_cases, 197362306a36Sopenharmony_ci}; 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci/* 197662306a36Sopenharmony_ci * Test that if we have several subsequent calls to 197762306a36Sopenharmony_ci * clk_set_rate_range(), the core will reevaluate whether a new rate is 197862306a36Sopenharmony_ci * needed each and every time. 197962306a36Sopenharmony_ci * 198062306a36Sopenharmony_ci * With clk_dummy_minimize_rate_ops, this means that the rate will 198162306a36Sopenharmony_ci * trail along the minimum as it evolves. 198262306a36Sopenharmony_ci */ 198362306a36Sopenharmony_cistatic void clk_range_test_set_range_rate_minimized(struct kunit *test) 198462306a36Sopenharmony_ci{ 198562306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 198662306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 198762306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 198862306a36Sopenharmony_ci unsigned long rate; 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 199162306a36Sopenharmony_ci clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000), 199262306a36Sopenharmony_ci 0); 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 199562306a36Sopenharmony_ci clk_set_rate_range(clk, 199662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 199762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 199862306a36Sopenharmony_ci 0); 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci rate = clk_get_rate(clk); 200162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 200262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 200562306a36Sopenharmony_ci clk_set_rate_range(clk, 200662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1 + 1000, 200762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 200862306a36Sopenharmony_ci 0); 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci rate = clk_get_rate(clk); 201162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 201262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1 + 1000); 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 201562306a36Sopenharmony_ci clk_set_rate_range(clk, 201662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 201762306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2), 201862306a36Sopenharmony_ci 0); 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci rate = clk_get_rate(clk); 202162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 202262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci clk_put(clk); 202562306a36Sopenharmony_ci} 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci/* 202862306a36Sopenharmony_ci * Test that if we have several subsequent calls to 202962306a36Sopenharmony_ci * clk_set_rate_range(), across multiple users, the core will reevaluate 203062306a36Sopenharmony_ci * whether a new rate is needed each and every time. 203162306a36Sopenharmony_ci * 203262306a36Sopenharmony_ci * With clk_dummy_minimize_rate_ops, this means that the rate will 203362306a36Sopenharmony_ci * trail along the minimum as it evolves. 203462306a36Sopenharmony_ci */ 203562306a36Sopenharmony_cistatic void clk_range_test_multiple_set_range_rate_minimized(struct kunit *test) 203662306a36Sopenharmony_ci{ 203762306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 203862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 203962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 204062306a36Sopenharmony_ci struct clk *user1, *user2; 204162306a36Sopenharmony_ci unsigned long rate; 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci user1 = clk_hw_get_clk(hw, NULL); 204462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1); 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci user2 = clk_hw_get_clk(hw, NULL); 204762306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2); 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 205062306a36Sopenharmony_ci clk_set_rate_range(user1, 205162306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 205262306a36Sopenharmony_ci ULONG_MAX), 205362306a36Sopenharmony_ci 0); 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci rate = clk_get_rate(clk); 205662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 205762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 206062306a36Sopenharmony_ci clk_set_rate_range(user2, 206162306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2, 206262306a36Sopenharmony_ci ULONG_MAX), 206362306a36Sopenharmony_ci 0); 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_ci rate = clk_get_rate(clk); 206662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 206762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 207062306a36Sopenharmony_ci clk_drop_range(user2), 207162306a36Sopenharmony_ci 0); 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ci rate = clk_get_rate(clk); 207462306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 207562306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci clk_put(user2); 207862306a36Sopenharmony_ci clk_put(user1); 207962306a36Sopenharmony_ci clk_put(clk); 208062306a36Sopenharmony_ci} 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci/* 208362306a36Sopenharmony_ci * Test that if we have several subsequent calls to 208462306a36Sopenharmony_ci * clk_set_rate_range(), across multiple users, the core will reevaluate 208562306a36Sopenharmony_ci * whether a new rate is needed, including when a user drop its clock. 208662306a36Sopenharmony_ci * 208762306a36Sopenharmony_ci * With clk_dummy_minimize_rate_ops, this means that the rate will 208862306a36Sopenharmony_ci * trail along the minimum as it evolves. 208962306a36Sopenharmony_ci */ 209062306a36Sopenharmony_cistatic void clk_range_test_multiple_set_range_rate_put_minimized(struct kunit *test) 209162306a36Sopenharmony_ci{ 209262306a36Sopenharmony_ci struct clk_dummy_context *ctx = test->priv; 209362306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 209462306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 209562306a36Sopenharmony_ci struct clk *user1, *user2; 209662306a36Sopenharmony_ci unsigned long rate; 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci user1 = clk_hw_get_clk(hw, NULL); 209962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1); 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci user2 = clk_hw_get_clk(hw, NULL); 210262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2); 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 210562306a36Sopenharmony_ci clk_set_rate_range(user1, 210662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_1, 210762306a36Sopenharmony_ci ULONG_MAX), 210862306a36Sopenharmony_ci 0); 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci rate = clk_get_rate(clk); 211162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 211262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, 211562306a36Sopenharmony_ci clk_set_rate_range(user2, 211662306a36Sopenharmony_ci DUMMY_CLOCK_RATE_2, 211762306a36Sopenharmony_ci ULONG_MAX), 211862306a36Sopenharmony_ci 0); 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci rate = clk_get_rate(clk); 212162306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 212262306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_ci clk_put(user2); 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci rate = clk_get_rate(clk); 212762306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 212862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci clk_put(user1); 213162306a36Sopenharmony_ci clk_put(clk); 213262306a36Sopenharmony_ci} 213362306a36Sopenharmony_ci 213462306a36Sopenharmony_cistatic struct kunit_case clk_range_minimize_test_cases[] = { 213562306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_set_range_rate_minimized), 213662306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_multiple_set_range_rate_minimized), 213762306a36Sopenharmony_ci KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_minimized), 213862306a36Sopenharmony_ci {} 213962306a36Sopenharmony_ci}; 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ci/* 214262306a36Sopenharmony_ci * Test suite for a basic rate clock, without any parent. 214362306a36Sopenharmony_ci * 214462306a36Sopenharmony_ci * These tests exercise the rate range API: clk_set_rate_range(), 214562306a36Sopenharmony_ci * clk_set_min_rate(), clk_set_max_rate(), clk_drop_range(), with a 214662306a36Sopenharmony_ci * driver that will always try to run at the lowest possible rate. 214762306a36Sopenharmony_ci */ 214862306a36Sopenharmony_cistatic struct kunit_suite clk_range_minimize_test_suite = { 214962306a36Sopenharmony_ci .name = "clk-range-minimize-test", 215062306a36Sopenharmony_ci .init = clk_minimize_test_init, 215162306a36Sopenharmony_ci .exit = clk_test_exit, 215262306a36Sopenharmony_ci .test_cases = clk_range_minimize_test_cases, 215362306a36Sopenharmony_ci}; 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_cistruct clk_leaf_mux_ctx { 215662306a36Sopenharmony_ci struct clk_multiple_parent_ctx mux_ctx; 215762306a36Sopenharmony_ci struct clk_hw hw; 215862306a36Sopenharmony_ci}; 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_cistatic int 216162306a36Sopenharmony_ciclk_leaf_mux_set_rate_parent_test_init(struct kunit *test) 216262306a36Sopenharmony_ci{ 216362306a36Sopenharmony_ci struct clk_leaf_mux_ctx *ctx; 216462306a36Sopenharmony_ci const char *top_parents[2] = { "parent-0", "parent-1" }; 216562306a36Sopenharmony_ci int ret; 216662306a36Sopenharmony_ci 216762306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 216862306a36Sopenharmony_ci if (!ctx) 216962306a36Sopenharmony_ci return -ENOMEM; 217062306a36Sopenharmony_ci test->priv = ctx; 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[0].hw.init = CLK_HW_INIT_NO_PARENT("parent-0", 217362306a36Sopenharmony_ci &clk_dummy_rate_ops, 217462306a36Sopenharmony_ci 0); 217562306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[0].rate = DUMMY_CLOCK_RATE_1; 217662306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->mux_ctx.parents_ctx[0].hw); 217762306a36Sopenharmony_ci if (ret) 217862306a36Sopenharmony_ci return ret; 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("parent-1", 218162306a36Sopenharmony_ci &clk_dummy_rate_ops, 218262306a36Sopenharmony_ci 0); 218362306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[1].rate = DUMMY_CLOCK_RATE_2; 218462306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->mux_ctx.parents_ctx[1].hw); 218562306a36Sopenharmony_ci if (ret) 218662306a36Sopenharmony_ci return ret; 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci ctx->mux_ctx.current_parent = 0; 218962306a36Sopenharmony_ci ctx->mux_ctx.hw.init = CLK_HW_INIT_PARENTS("test-mux", top_parents, 219062306a36Sopenharmony_ci &clk_multiple_parents_mux_ops, 219162306a36Sopenharmony_ci 0); 219262306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->mux_ctx.hw); 219362306a36Sopenharmony_ci if (ret) 219462306a36Sopenharmony_ci return ret; 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci ctx->hw.init = CLK_HW_INIT_HW("test-clock", &ctx->mux_ctx.hw, 219762306a36Sopenharmony_ci &clk_dummy_single_parent_ops, 219862306a36Sopenharmony_ci CLK_SET_RATE_PARENT); 219962306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 220062306a36Sopenharmony_ci if (ret) 220162306a36Sopenharmony_ci return ret; 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci return 0; 220462306a36Sopenharmony_ci} 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_cistatic void clk_leaf_mux_set_rate_parent_test_exit(struct kunit *test) 220762306a36Sopenharmony_ci{ 220862306a36Sopenharmony_ci struct clk_leaf_mux_ctx *ctx = test->priv; 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci clk_hw_unregister(&ctx->hw); 221162306a36Sopenharmony_ci clk_hw_unregister(&ctx->mux_ctx.hw); 221262306a36Sopenharmony_ci clk_hw_unregister(&ctx->mux_ctx.parents_ctx[0].hw); 221362306a36Sopenharmony_ci clk_hw_unregister(&ctx->mux_ctx.parents_ctx[1].hw); 221462306a36Sopenharmony_ci} 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_ci/* 221762306a36Sopenharmony_ci * Test that, for a clock that will forward any rate request to its 221862306a36Sopenharmony_ci * parent, the rate request structure returned by __clk_determine_rate 221962306a36Sopenharmony_ci * is sane and will be what we expect. 222062306a36Sopenharmony_ci */ 222162306a36Sopenharmony_cistatic void clk_leaf_mux_set_rate_parent_determine_rate(struct kunit *test) 222262306a36Sopenharmony_ci{ 222362306a36Sopenharmony_ci struct clk_leaf_mux_ctx *ctx = test->priv; 222462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 222562306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 222662306a36Sopenharmony_ci struct clk_rate_request req; 222762306a36Sopenharmony_ci unsigned long rate; 222862306a36Sopenharmony_ci int ret; 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci rate = clk_get_rate(clk); 223162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, rate, DUMMY_CLOCK_RATE_1); 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci clk_hw_init_rate_request(hw, &req, DUMMY_CLOCK_RATE_2); 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci ret = __clk_determine_rate(hw, &req); 223662306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, req.rate, DUMMY_CLOCK_RATE_2); 223962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, req.best_parent_rate, DUMMY_CLOCK_RATE_2); 224062306a36Sopenharmony_ci KUNIT_EXPECT_PTR_EQ(test, req.best_parent_hw, &ctx->mux_ctx.hw); 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_ci clk_put(clk); 224362306a36Sopenharmony_ci} 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_cistatic struct kunit_case clk_leaf_mux_set_rate_parent_test_cases[] = { 224662306a36Sopenharmony_ci KUNIT_CASE(clk_leaf_mux_set_rate_parent_determine_rate), 224762306a36Sopenharmony_ci {} 224862306a36Sopenharmony_ci}; 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci/* 225162306a36Sopenharmony_ci * Test suite for a clock whose parent is a mux with multiple parents. 225262306a36Sopenharmony_ci * The leaf clock has CLK_SET_RATE_PARENT, and will forward rate 225362306a36Sopenharmony_ci * requests to the mux, which will then select which parent is the best 225462306a36Sopenharmony_ci * fit for a given rate. 225562306a36Sopenharmony_ci * 225662306a36Sopenharmony_ci * These tests exercise the behaviour of muxes, and the proper selection 225762306a36Sopenharmony_ci * of parents. 225862306a36Sopenharmony_ci */ 225962306a36Sopenharmony_cistatic struct kunit_suite clk_leaf_mux_set_rate_parent_test_suite = { 226062306a36Sopenharmony_ci .name = "clk-leaf-mux-set-rate-parent", 226162306a36Sopenharmony_ci .init = clk_leaf_mux_set_rate_parent_test_init, 226262306a36Sopenharmony_ci .exit = clk_leaf_mux_set_rate_parent_test_exit, 226362306a36Sopenharmony_ci .test_cases = clk_leaf_mux_set_rate_parent_test_cases, 226462306a36Sopenharmony_ci}; 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_cistruct clk_mux_notifier_rate_change { 226762306a36Sopenharmony_ci bool done; 226862306a36Sopenharmony_ci unsigned long old_rate; 226962306a36Sopenharmony_ci unsigned long new_rate; 227062306a36Sopenharmony_ci wait_queue_head_t wq; 227162306a36Sopenharmony_ci}; 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_cistruct clk_mux_notifier_ctx { 227462306a36Sopenharmony_ci struct clk_multiple_parent_ctx mux_ctx; 227562306a36Sopenharmony_ci struct clk *clk; 227662306a36Sopenharmony_ci struct notifier_block clk_nb; 227762306a36Sopenharmony_ci struct clk_mux_notifier_rate_change pre_rate_change; 227862306a36Sopenharmony_ci struct clk_mux_notifier_rate_change post_rate_change; 227962306a36Sopenharmony_ci}; 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci#define NOTIFIER_TIMEOUT_MS 100 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_cistatic int clk_mux_notifier_callback(struct notifier_block *nb, 228462306a36Sopenharmony_ci unsigned long action, void *data) 228562306a36Sopenharmony_ci{ 228662306a36Sopenharmony_ci struct clk_notifier_data *clk_data = data; 228762306a36Sopenharmony_ci struct clk_mux_notifier_ctx *ctx = container_of(nb, 228862306a36Sopenharmony_ci struct clk_mux_notifier_ctx, 228962306a36Sopenharmony_ci clk_nb); 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci if (action & PRE_RATE_CHANGE) { 229262306a36Sopenharmony_ci ctx->pre_rate_change.old_rate = clk_data->old_rate; 229362306a36Sopenharmony_ci ctx->pre_rate_change.new_rate = clk_data->new_rate; 229462306a36Sopenharmony_ci ctx->pre_rate_change.done = true; 229562306a36Sopenharmony_ci wake_up_interruptible(&ctx->pre_rate_change.wq); 229662306a36Sopenharmony_ci } 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci if (action & POST_RATE_CHANGE) { 229962306a36Sopenharmony_ci ctx->post_rate_change.old_rate = clk_data->old_rate; 230062306a36Sopenharmony_ci ctx->post_rate_change.new_rate = clk_data->new_rate; 230162306a36Sopenharmony_ci ctx->post_rate_change.done = true; 230262306a36Sopenharmony_ci wake_up_interruptible(&ctx->post_rate_change.wq); 230362306a36Sopenharmony_ci } 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_ci return 0; 230662306a36Sopenharmony_ci} 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_cistatic int clk_mux_notifier_test_init(struct kunit *test) 230962306a36Sopenharmony_ci{ 231062306a36Sopenharmony_ci struct clk_mux_notifier_ctx *ctx; 231162306a36Sopenharmony_ci const char *top_parents[2] = { "parent-0", "parent-1" }; 231262306a36Sopenharmony_ci int ret; 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 231562306a36Sopenharmony_ci if (!ctx) 231662306a36Sopenharmony_ci return -ENOMEM; 231762306a36Sopenharmony_ci test->priv = ctx; 231862306a36Sopenharmony_ci ctx->clk_nb.notifier_call = clk_mux_notifier_callback; 231962306a36Sopenharmony_ci init_waitqueue_head(&ctx->pre_rate_change.wq); 232062306a36Sopenharmony_ci init_waitqueue_head(&ctx->post_rate_change.wq); 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[0].hw.init = CLK_HW_INIT_NO_PARENT("parent-0", 232362306a36Sopenharmony_ci &clk_dummy_rate_ops, 232462306a36Sopenharmony_ci 0); 232562306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[0].rate = DUMMY_CLOCK_RATE_1; 232662306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->mux_ctx.parents_ctx[0].hw); 232762306a36Sopenharmony_ci if (ret) 232862306a36Sopenharmony_ci return ret; 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("parent-1", 233162306a36Sopenharmony_ci &clk_dummy_rate_ops, 233262306a36Sopenharmony_ci 0); 233362306a36Sopenharmony_ci ctx->mux_ctx.parents_ctx[1].rate = DUMMY_CLOCK_RATE_2; 233462306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->mux_ctx.parents_ctx[1].hw); 233562306a36Sopenharmony_ci if (ret) 233662306a36Sopenharmony_ci return ret; 233762306a36Sopenharmony_ci 233862306a36Sopenharmony_ci ctx->mux_ctx.current_parent = 0; 233962306a36Sopenharmony_ci ctx->mux_ctx.hw.init = CLK_HW_INIT_PARENTS("test-mux", top_parents, 234062306a36Sopenharmony_ci &clk_multiple_parents_mux_ops, 234162306a36Sopenharmony_ci 0); 234262306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->mux_ctx.hw); 234362306a36Sopenharmony_ci if (ret) 234462306a36Sopenharmony_ci return ret; 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci ctx->clk = clk_hw_get_clk(&ctx->mux_ctx.hw, NULL); 234762306a36Sopenharmony_ci ret = clk_notifier_register(ctx->clk, &ctx->clk_nb); 234862306a36Sopenharmony_ci if (ret) 234962306a36Sopenharmony_ci return ret; 235062306a36Sopenharmony_ci 235162306a36Sopenharmony_ci return 0; 235262306a36Sopenharmony_ci} 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_cistatic void clk_mux_notifier_test_exit(struct kunit *test) 235562306a36Sopenharmony_ci{ 235662306a36Sopenharmony_ci struct clk_mux_notifier_ctx *ctx = test->priv; 235762306a36Sopenharmony_ci struct clk *clk = ctx->clk; 235862306a36Sopenharmony_ci 235962306a36Sopenharmony_ci clk_notifier_unregister(clk, &ctx->clk_nb); 236062306a36Sopenharmony_ci clk_put(clk); 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci clk_hw_unregister(&ctx->mux_ctx.hw); 236362306a36Sopenharmony_ci clk_hw_unregister(&ctx->mux_ctx.parents_ctx[0].hw); 236462306a36Sopenharmony_ci clk_hw_unregister(&ctx->mux_ctx.parents_ctx[1].hw); 236562306a36Sopenharmony_ci} 236662306a36Sopenharmony_ci 236762306a36Sopenharmony_ci/* 236862306a36Sopenharmony_ci * Test that if the we have a notifier registered on a mux, the core 236962306a36Sopenharmony_ci * will notify us when we switch to another parent, and with the proper 237062306a36Sopenharmony_ci * old and new rates. 237162306a36Sopenharmony_ci */ 237262306a36Sopenharmony_cistatic void clk_mux_notifier_set_parent_test(struct kunit *test) 237362306a36Sopenharmony_ci{ 237462306a36Sopenharmony_ci struct clk_mux_notifier_ctx *ctx = test->priv; 237562306a36Sopenharmony_ci struct clk_hw *hw = &ctx->mux_ctx.hw; 237662306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 237762306a36Sopenharmony_ci struct clk *new_parent = clk_hw_get_clk(&ctx->mux_ctx.parents_ctx[1].hw, NULL); 237862306a36Sopenharmony_ci int ret; 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci ret = clk_set_parent(clk, new_parent); 238162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci ret = wait_event_interruptible_timeout(ctx->pre_rate_change.wq, 238462306a36Sopenharmony_ci ctx->pre_rate_change.done, 238562306a36Sopenharmony_ci msecs_to_jiffies(NOTIFIER_TIMEOUT_MS)); 238662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, ret, 0); 238762306a36Sopenharmony_ci 238862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, ctx->pre_rate_change.old_rate, DUMMY_CLOCK_RATE_1); 238962306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, ctx->pre_rate_change.new_rate, DUMMY_CLOCK_RATE_2); 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci ret = wait_event_interruptible_timeout(ctx->post_rate_change.wq, 239262306a36Sopenharmony_ci ctx->post_rate_change.done, 239362306a36Sopenharmony_ci msecs_to_jiffies(NOTIFIER_TIMEOUT_MS)); 239462306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, ret, 0); 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, ctx->post_rate_change.old_rate, DUMMY_CLOCK_RATE_1); 239762306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, ctx->post_rate_change.new_rate, DUMMY_CLOCK_RATE_2); 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci clk_put(new_parent); 240062306a36Sopenharmony_ci clk_put(clk); 240162306a36Sopenharmony_ci} 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_cistatic struct kunit_case clk_mux_notifier_test_cases[] = { 240462306a36Sopenharmony_ci KUNIT_CASE(clk_mux_notifier_set_parent_test), 240562306a36Sopenharmony_ci {} 240662306a36Sopenharmony_ci}; 240762306a36Sopenharmony_ci 240862306a36Sopenharmony_ci/* 240962306a36Sopenharmony_ci * Test suite for a mux with multiple parents, and a notifier registered 241062306a36Sopenharmony_ci * on the mux. 241162306a36Sopenharmony_ci * 241262306a36Sopenharmony_ci * These tests exercise the behaviour of notifiers. 241362306a36Sopenharmony_ci */ 241462306a36Sopenharmony_cistatic struct kunit_suite clk_mux_notifier_test_suite = { 241562306a36Sopenharmony_ci .name = "clk-mux-notifier", 241662306a36Sopenharmony_ci .init = clk_mux_notifier_test_init, 241762306a36Sopenharmony_ci .exit = clk_mux_notifier_test_exit, 241862306a36Sopenharmony_ci .test_cases = clk_mux_notifier_test_cases, 241962306a36Sopenharmony_ci}; 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_cistatic int 242262306a36Sopenharmony_ciclk_mux_no_reparent_test_init(struct kunit *test) 242362306a36Sopenharmony_ci{ 242462306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx; 242562306a36Sopenharmony_ci const char *parents[2] = { "parent-0", "parent-1"}; 242662306a36Sopenharmony_ci int ret; 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_ci ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 242962306a36Sopenharmony_ci if (!ctx) 243062306a36Sopenharmony_ci return -ENOMEM; 243162306a36Sopenharmony_ci test->priv = ctx; 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_ci ctx->parents_ctx[0].hw.init = CLK_HW_INIT_NO_PARENT("parent-0", 243462306a36Sopenharmony_ci &clk_dummy_rate_ops, 243562306a36Sopenharmony_ci 0); 243662306a36Sopenharmony_ci ctx->parents_ctx[0].rate = DUMMY_CLOCK_RATE_1; 243762306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parents_ctx[0].hw); 243862306a36Sopenharmony_ci if (ret) 243962306a36Sopenharmony_ci return ret; 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci ctx->parents_ctx[1].hw.init = CLK_HW_INIT_NO_PARENT("parent-1", 244262306a36Sopenharmony_ci &clk_dummy_rate_ops, 244362306a36Sopenharmony_ci 0); 244462306a36Sopenharmony_ci ctx->parents_ctx[1].rate = DUMMY_CLOCK_RATE_2; 244562306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->parents_ctx[1].hw); 244662306a36Sopenharmony_ci if (ret) 244762306a36Sopenharmony_ci return ret; 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci ctx->current_parent = 0; 245062306a36Sopenharmony_ci ctx->hw.init = CLK_HW_INIT_PARENTS("test-mux", parents, 245162306a36Sopenharmony_ci &clk_multiple_parents_no_reparent_mux_ops, 245262306a36Sopenharmony_ci 0); 245362306a36Sopenharmony_ci ret = clk_hw_register(NULL, &ctx->hw); 245462306a36Sopenharmony_ci if (ret) 245562306a36Sopenharmony_ci return ret; 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ci return 0; 245862306a36Sopenharmony_ci} 245962306a36Sopenharmony_ci 246062306a36Sopenharmony_cistatic void 246162306a36Sopenharmony_ciclk_mux_no_reparent_test_exit(struct kunit *test) 246262306a36Sopenharmony_ci{ 246362306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci clk_hw_unregister(&ctx->hw); 246662306a36Sopenharmony_ci clk_hw_unregister(&ctx->parents_ctx[0].hw); 246762306a36Sopenharmony_ci clk_hw_unregister(&ctx->parents_ctx[1].hw); 246862306a36Sopenharmony_ci} 246962306a36Sopenharmony_ci 247062306a36Sopenharmony_ci/* 247162306a36Sopenharmony_ci * Test that if the we have a mux that cannot change parent and we call 247262306a36Sopenharmony_ci * clk_round_rate() on it with a rate that should cause it to change 247362306a36Sopenharmony_ci * parent, it won't. 247462306a36Sopenharmony_ci */ 247562306a36Sopenharmony_cistatic void clk_mux_no_reparent_round_rate(struct kunit *test) 247662306a36Sopenharmony_ci{ 247762306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 247862306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 247962306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 248062306a36Sopenharmony_ci struct clk *other_parent, *parent; 248162306a36Sopenharmony_ci unsigned long other_parent_rate; 248262306a36Sopenharmony_ci unsigned long parent_rate; 248362306a36Sopenharmony_ci long rounded_rate; 248462306a36Sopenharmony_ci 248562306a36Sopenharmony_ci parent = clk_get_parent(clk); 248662306a36Sopenharmony_ci KUNIT_ASSERT_PTR_NE(test, parent, NULL); 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci parent_rate = clk_get_rate(parent); 248962306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, parent_rate, 0); 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ci other_parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 249262306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, other_parent); 249362306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, clk_is_match(parent, other_parent)); 249462306a36Sopenharmony_ci 249562306a36Sopenharmony_ci other_parent_rate = clk_get_rate(other_parent); 249662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, other_parent_rate, 0); 249762306a36Sopenharmony_ci clk_put(other_parent); 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ci rounded_rate = clk_round_rate(clk, other_parent_rate); 250062306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rounded_rate, 0); 250162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rounded_rate, parent_rate); 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_ci clk_put(clk); 250462306a36Sopenharmony_ci} 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci/* 250762306a36Sopenharmony_ci * Test that if the we have a mux that cannot change parent and we call 250862306a36Sopenharmony_ci * clk_set_rate() on it with a rate that should cause it to change 250962306a36Sopenharmony_ci * parent, it won't. 251062306a36Sopenharmony_ci */ 251162306a36Sopenharmony_cistatic void clk_mux_no_reparent_set_rate(struct kunit *test) 251262306a36Sopenharmony_ci{ 251362306a36Sopenharmony_ci struct clk_multiple_parent_ctx *ctx = test->priv; 251462306a36Sopenharmony_ci struct clk_hw *hw = &ctx->hw; 251562306a36Sopenharmony_ci struct clk *clk = clk_hw_get_clk(hw, NULL); 251662306a36Sopenharmony_ci struct clk *other_parent, *parent; 251762306a36Sopenharmony_ci unsigned long other_parent_rate; 251862306a36Sopenharmony_ci unsigned long parent_rate; 251962306a36Sopenharmony_ci unsigned long rate; 252062306a36Sopenharmony_ci int ret; 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci parent = clk_get_parent(clk); 252362306a36Sopenharmony_ci KUNIT_ASSERT_PTR_NE(test, parent, NULL); 252462306a36Sopenharmony_ci 252562306a36Sopenharmony_ci parent_rate = clk_get_rate(parent); 252662306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, parent_rate, 0); 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci other_parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL); 252962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, other_parent); 253062306a36Sopenharmony_ci KUNIT_ASSERT_FALSE(test, clk_is_match(parent, other_parent)); 253162306a36Sopenharmony_ci 253262306a36Sopenharmony_ci other_parent_rate = clk_get_rate(other_parent); 253362306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, other_parent_rate, 0); 253462306a36Sopenharmony_ci clk_put(other_parent); 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci ret = clk_set_rate(clk, other_parent_rate); 253762306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci rate = clk_get_rate(clk); 254062306a36Sopenharmony_ci KUNIT_ASSERT_GT(test, rate, 0); 254162306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, rate, parent_rate); 254262306a36Sopenharmony_ci 254362306a36Sopenharmony_ci clk_put(clk); 254462306a36Sopenharmony_ci} 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_cistatic struct kunit_case clk_mux_no_reparent_test_cases[] = { 254762306a36Sopenharmony_ci KUNIT_CASE(clk_mux_no_reparent_round_rate), 254862306a36Sopenharmony_ci KUNIT_CASE(clk_mux_no_reparent_set_rate), 254962306a36Sopenharmony_ci {} 255062306a36Sopenharmony_ci}; 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_ci/* 255362306a36Sopenharmony_ci * Test suite for a clock mux that isn't allowed to change parent, using 255462306a36Sopenharmony_ci * the clk_hw_determine_rate_no_reparent() helper. 255562306a36Sopenharmony_ci * 255662306a36Sopenharmony_ci * These tests exercise that helper, and the proper selection of 255762306a36Sopenharmony_ci * rates and parents. 255862306a36Sopenharmony_ci */ 255962306a36Sopenharmony_cistatic struct kunit_suite clk_mux_no_reparent_test_suite = { 256062306a36Sopenharmony_ci .name = "clk-mux-no-reparent", 256162306a36Sopenharmony_ci .init = clk_mux_no_reparent_test_init, 256262306a36Sopenharmony_ci .exit = clk_mux_no_reparent_test_exit, 256362306a36Sopenharmony_ci .test_cases = clk_mux_no_reparent_test_cases, 256462306a36Sopenharmony_ci}; 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_cikunit_test_suites( 256762306a36Sopenharmony_ci &clk_leaf_mux_set_rate_parent_test_suite, 256862306a36Sopenharmony_ci &clk_test_suite, 256962306a36Sopenharmony_ci &clk_multiple_parents_mux_test_suite, 257062306a36Sopenharmony_ci &clk_mux_no_reparent_test_suite, 257162306a36Sopenharmony_ci &clk_mux_notifier_test_suite, 257262306a36Sopenharmony_ci &clk_orphan_transparent_multiple_parent_mux_test_suite, 257362306a36Sopenharmony_ci &clk_orphan_transparent_single_parent_test_suite, 257462306a36Sopenharmony_ci &clk_orphan_two_level_root_last_test_suite, 257562306a36Sopenharmony_ci &clk_range_test_suite, 257662306a36Sopenharmony_ci &clk_range_maximize_test_suite, 257762306a36Sopenharmony_ci &clk_range_minimize_test_suite, 257862306a36Sopenharmony_ci &clk_single_parent_mux_test_suite, 257962306a36Sopenharmony_ci &clk_uncached_test_suite 258062306a36Sopenharmony_ci); 258162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2582