[PATCH 1/5] clk: composite: Initialize inner hw clocks during registration
From: Miquel Raynal
Date: Wed Oct 21 2026 - 09:17:29 EST
The mux, rate and gate clk_hws of a composite are not registered as
clocks on their own. Only the ->clk pointer was set to the composite
clk, but their ->core remained unassigned.
Provider ops may call into clk_hw_* helpers, such as clk_hw_get_flags()
or clk_hw_get_rate() for instance. In these cases, hw->core will be
dereferenced.
The composite callbacks kind of papered with this situation by (almost)
always calling __clk_hw_set_clk() before
use. clk_composite_determine_rate() never did it, but it probably did
not fail because the core likely called callbacks like get_parent() or
recalc_rate() before.
Add a clk_composite_init() callback that sets up the inner core pointers
once for all just after the core clock registration, and before any
other callback call from the core. Thanks to this, each per-callback
assignement can be dropped.
Signed-off-by: Miquel Raynal <miquel.raynal@xxxxxxxxxxx>
---
drivers/clk/clk-composite.c | 34 +++++++++++++++-------------------
1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 11842bce5918..332b38a326fa 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -8,14 +8,26 @@
#include <linux/err.h>
#include <linux/slab.h>
+static int clk_composite_init(struct clk_hw *hw)
+{
+ struct clk_composite *composite = to_clk_composite(hw);
+
+ if (composite->mux_hw)
+ __clk_hw_set_clk(composite->mux_hw, hw);
+ if (composite->rate_hw)
+ __clk_hw_set_clk(composite->rate_hw, hw);
+ if (composite->gate_hw)
+ __clk_hw_set_clk(composite->gate_hw, hw);
+
+ return 0;
+}
+
static u8 clk_composite_get_parent(struct clk_hw *hw)
{
struct clk_composite *composite = to_clk_composite(hw);
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *mux_hw = composite->mux_hw;
- __clk_hw_set_clk(mux_hw, hw);
-
return mux_ops->get_parent(mux_hw);
}
@@ -25,8 +37,6 @@ static int clk_composite_set_parent(struct clk_hw *hw, u8 index)
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *mux_hw = composite->mux_hw;
- __clk_hw_set_clk(mux_hw, hw);
-
return mux_ops->set_parent(mux_hw, index);
}
@@ -37,8 +47,6 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
const struct clk_ops *rate_ops = composite->rate_ops;
struct clk_hw *rate_hw = composite->rate_hw;
- __clk_hw_set_clk(rate_hw, hw);
-
return rate_ops->recalc_rate(rate_hw, parent_rate);
}
@@ -126,10 +134,8 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
req->rate = best_rate;
return 0;
} else if (rate_hw && rate_ops && rate_ops->determine_rate) {
- __clk_hw_set_clk(rate_hw, hw);
return rate_ops->determine_rate(rate_hw, req);
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
- __clk_hw_set_clk(mux_hw, hw);
return mux_ops->determine_rate(mux_hw, req);
} else {
pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
@@ -144,8 +150,6 @@ static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *rate_ops = composite->rate_ops;
struct clk_hw *rate_hw = composite->rate_hw;
- __clk_hw_set_clk(rate_hw, hw);
-
return rate_ops->set_rate(rate_hw, rate, parent_rate);
}
@@ -161,9 +165,6 @@ static int clk_composite_set_rate_and_parent(struct clk_hw *hw,
struct clk_hw *mux_hw = composite->mux_hw;
unsigned long temp_rate;
- __clk_hw_set_clk(rate_hw, hw);
- __clk_hw_set_clk(mux_hw, hw);
-
temp_rate = rate_ops->recalc_rate(rate_hw, parent_rate);
if (temp_rate > rate) {
rate_ops->set_rate(rate_hw, rate, parent_rate);
@@ -182,8 +183,6 @@ static int clk_composite_is_enabled(struct clk_hw *hw)
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk_hw *gate_hw = composite->gate_hw;
- __clk_hw_set_clk(gate_hw, hw);
-
return gate_ops->is_enabled(gate_hw);
}
@@ -193,8 +192,6 @@ static int clk_composite_enable(struct clk_hw *hw)
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk_hw *gate_hw = composite->gate_hw;
- __clk_hw_set_clk(gate_hw, hw);
-
return gate_ops->enable(gate_hw);
}
@@ -204,8 +201,6 @@ static void clk_composite_disable(struct clk_hw *hw)
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk_hw *gate_hw = composite->gate_hw;
- __clk_hw_set_clk(gate_hw, hw);
-
gate_ops->disable(gate_hw);
}
@@ -237,6 +232,7 @@ static struct clk_hw *__clk_hw_register_composite(struct device *dev,
hw = &composite->hw;
clk_composite_ops = &composite->ops;
+ clk_composite_ops->init = clk_composite_init;
if (mux_hw && mux_ops) {
if (!mux_ops->get_parent) {
--
2.56.0