From 1234a2c40b8cf16041fb9acd730160e6c5b4ba13 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Aug 2022 13:25:24 +0200 Subject: 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 # imx8mp Tested-by: Marek Szyprowski # exynos4210, meson g12b Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220816112530.1837489-20-maxime@cerno.tech Tested-by: Linux Kernel Functional Testing Tested-by: Naresh Kamboju [sboyd@kernel.org: Move tmp declaration, fix conditional to check for current parent] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 37 ++++++++++++++++++++++--------------- drivers/clk/clk_test.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f8a8bdd552d6..8e4a8b9aa320 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -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); diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c index d1b1372f7aaa..7068517428e2 100644 --- a/drivers/clk/clk_test.c +++ b/drivers/clk/clk_test.c @@ -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), -- cgit v1.2.3