Commit 1234a2c4 authored by Maxime Ripard's avatar Maxime Ripard Committed by Stephen Boyd
Browse files

clk: Introduce clk_core_has_parent()



We will need to know if a clk_core pointer has a given parent in other
functions, so let's create a clk_core_has_parent() function that
clk_has_parent() will call into.

For good measure, let's add some unit tests as well to make sure it
works properly.

Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> # imx8mp
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> # exynos4210, meson g12b
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220816112530.1837489-20-maxime@cerno.tech


Tested-by: default avatarLinux Kernel Functional Testing <lkft@linaro.org>
Tested-by: default avatarNaresh Kamboju <naresh.kamboju@linaro.org>
[sboyd@kernel.org: Move tmp declaration, fix conditional to check for
current parent]
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent 666650b2
Loading
Loading
Loading
Loading
+22 −15
Original line number Diff line number Diff line
@@ -539,6 +539,27 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
static int clk_core_round_rate_nolock(struct clk_core *core,
				      struct clk_rate_request *req);

static bool clk_core_has_parent(struct clk_core *core, const struct clk_core *parent)
{
	struct clk_core *tmp;
	unsigned int i;

	/* Optimize for the case where the parent is already the parent. */
	if (core->parent == parent)
		return true;

	for (i = 0; i < core->num_parents; i++) {
		tmp = clk_core_get_parent_by_index(core, i);
		if (!tmp)
			continue;

		if (tmp == parent)
			return true;
	}

	return false;
}

int clk_mux_determine_rate_flags(struct clk_hw *hw,
				 struct clk_rate_request *req,
				 unsigned long flags)
@@ -2574,25 +2595,11 @@ void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
 */
bool clk_has_parent(struct clk *clk, struct clk *parent)
{
	struct clk_core *core, *parent_core;
	int i;

	/* NULL clocks should be nops, so return success if either is NULL. */
	if (!clk || !parent)
		return true;

	core = clk->core;
	parent_core = parent->core;

	/* Optimize for the case where the parent is already the parent. */
	if (core->parent == parent_core)
		return true;

	for (i = 0; i < core->num_parents; i++)
		if (!strcmp(core->parents[i].name, parent_core->name))
			return true;

	return false;
	return clk_core_has_parent(clk->core, parent->core);
}
EXPORT_SYMBOL_GPL(clk_has_parent);

+43 −0
Original line number Diff line number Diff line
@@ -491,8 +491,32 @@ clk_test_multiple_parents_mux_get_parent(struct kunit *test)
	clk_put(clk);
}

/*
 * Test that for a clock with a multiple parents, clk_has_parent()
 * actually reports all of them as parents.
 */
static void
clk_test_multiple_parents_mux_has_parent(struct kunit *test)
{
	struct clk_multiple_parent_ctx *ctx = test->priv;
	struct clk_hw *hw = &ctx->hw;
	struct clk *clk = clk_hw_get_clk(hw, NULL);
	struct clk *parent;

	parent = clk_hw_get_clk(&ctx->parents_ctx[0].hw, NULL);
	KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, parent));
	clk_put(parent);

	parent = clk_hw_get_clk(&ctx->parents_ctx[1].hw, NULL);
	KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, parent));
	clk_put(parent);

	clk_put(clk);
}

static struct kunit_case clk_multiple_parents_mux_test_cases[] = {
	KUNIT_CASE(clk_test_multiple_parents_mux_get_parent),
	KUNIT_CASE(clk_test_multiple_parents_mux_has_parent),
	{}
};

@@ -918,6 +942,24 @@ clk_test_single_parent_mux_get_parent(struct kunit *test)
	clk_put(clk);
}

/*
 * Test that for a clock with a single parent, clk_has_parent() actually
 * reports it as a parent.
 */
static void
clk_test_single_parent_mux_has_parent(struct kunit *test)
{
	struct clk_single_parent_ctx *ctx = test->priv;
	struct clk_hw *hw = &ctx->hw;
	struct clk *clk = clk_hw_get_clk(hw, NULL);
	struct clk *parent = clk_hw_get_clk(&ctx->parent_ctx.hw, NULL);

	KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, parent));

	clk_put(parent);
	clk_put(clk);
}

/*
 * Test that for a clock that can't modify its rate and with a single
 * parent, if we set disjoints range on the parent and then the child,
@@ -1022,6 +1064,7 @@ clk_test_single_parent_mux_set_range_round_rate_child_smaller(struct kunit *test

static struct kunit_case clk_single_parent_mux_test_cases[] = {
	KUNIT_CASE(clk_test_single_parent_mux_get_parent),
	KUNIT_CASE(clk_test_single_parent_mux_has_parent),
	KUNIT_CASE(clk_test_single_parent_mux_set_range_disjoint_child_last),
	KUNIT_CASE(clk_test_single_parent_mux_set_range_disjoint_parent_last),
	KUNIT_CASE(clk_test_single_parent_mux_set_range_round_rate_child_smaller),