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