134 lines
4.2 KiB
Diff
134 lines
4.2 KiB
Diff
From ca0a8c7c024409a0c83afdab7e436348d1a7390f Mon Sep 17 00:00:00 2001
|
|
From: Maxime Ripard <maxime@cerno.tech>
|
|
Date: Thu, 7 Apr 2022 14:11:37 +0200
|
|
Subject: [PATCH] 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: Maxime Ripard <maxime@cerno.tech>
|
|
---
|
|
drivers/clk/clk.c | 36 +++++++++++++++++++++---------------
|
|
drivers/clk/clk_test.c | 32 ++++++++++++++++++++++++++++++++
|
|
2 files changed, 53 insertions(+), 15 deletions(-)
|
|
|
|
--- a/drivers/clk/clk.c
|
|
+++ b/drivers/clk/clk.c
|
|
@@ -559,6 +559,26 @@ static bool mux_is_better_rate(unsigned
|
|
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, struct clk_core *parent)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ /* Optimize for the case where the parent is already the parent. */
|
|
+ if (core == parent)
|
|
+ return true;
|
|
+
|
|
+ for (i = 0; i < core->num_parents; i++) {
|
|
+ struct clk_core *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)
|
|
@@ -2582,25 +2602,11 @@ void clk_hw_reparent(struct clk_hw *hw,
|
|
*/
|
|
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);
|
|
|
|
--- a/drivers/clk/clk_test.c
|
|
+++ b/drivers/clk/clk_test.c
|
|
@@ -473,8 +473,24 @@ clk_test_multiple_parents_mux_get_parent
|
|
KUNIT_EXPECT_TRUE(test, clk_is_match(parent, ctx->parents_ctx[0].hw.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 = hw->clk;
|
|
+
|
|
+ KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, ctx->parents_ctx[0].hw.clk));
|
|
+ KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, ctx->parents_ctx[1].hw.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),
|
|
{}
|
|
};
|
|
|
|
@@ -907,6 +923,21 @@ clk_test_single_parent_mux_get_parent(st
|
|
}
|
|
|
|
/*
|
|
+ * 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 = hw->clk;
|
|
+ struct clk *parent = ctx->parent_ctx.hw.clk;
|
|
+
|
|
+ KUNIT_EXPECT_TRUE(test, clk_has_parent(clk, parent));
|
|
+}
|
|
+
|
|
+/*
|
|
* 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,
|
|
* the second will return an error.
|
|
@@ -1004,6 +1035,7 @@ clk_test_single_parent_mux_set_range_rou
|
|
|
|
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),
|