[PATCH] clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present for gate and mux

Michael Trimarchi michael at amarulasolutions.com
Thu Jul 4 16:48:38 CEST 2024


Gate and mux does not have .set_rate operation, but they could have
CLK_SET_PARENT_RATE flag set. In that case it's usually possible to find a
parent up the tree which is capable of setting the rate (div, pll, etc).
Add clk_generic_set_rate to allow them to trasverse the clock tree.

Cc: Sam Protsenko <semen.protsenko at linaro.org>
Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
---
 drivers/clk/clk-gate.c   |  1 +
 drivers/clk/clk-mux.c    |  2 +-
 drivers/clk/clk-uclass.c | 20 ++++++++++++++++++++
 drivers/clk/clk.c        |  9 +++++++++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index cfd90b717e7..c86083ac5a3 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -116,6 +116,7 @@ const struct clk_ops clk_gate_ops = {
 	.enable = clk_gate_enable,
 	.disable = clk_gate_disable,
 	.get_rate = clk_generic_get_rate,
+	.set_rate = clk_generic_set_rate,
 };
 
 struct clk *clk_register_gate(struct device *dev, const char *name,
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index e3481be95fa..f99a67ebd35 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -151,13 +151,13 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
 #else
 	writel(reg, mux->reg);
 #endif
-
 	return 0;
 }
 
 const struct clk_ops clk_mux_ops = {
 	.get_rate = clk_generic_get_rate,
 	.set_parent = clk_mux_set_parent,
+	.set_rate = clk_generic_set_rate,
 };
 
 struct clk *clk_hw_register_mux_table(struct device *dev, const char *name,
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index ed6e60bc484..638864e6774 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -517,6 +517,26 @@ ulong clk_get_parent_rate(struct clk *clk)
 	return pclk->rate;
 }
 
+ulong clk_set_parent_rate(struct clk *clk, ulong rate)
+{
+	const struct clk_ops *ops;
+	struct clk *pclk;
+
+	debug("%s(clk=%p)\n", __func__, clk);
+	if (!clk_valid(clk))
+		return 0;
+
+	pclk = clk_get_parent(clk);
+	if (IS_ERR(pclk))
+		return -ENODEV;
+
+	ops = clk_dev_ops(pclk->dev);
+	if (!ops->set_rate)
+		return -ENOSYS;
+
+	return clk_set_rate(pclk, rate);
+}
+
 ulong clk_round_rate(struct clk *clk, ulong rate)
 {
 	const struct clk_ops *ops;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 6ede1b4d4dc..febd5314df2 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -14,6 +14,7 @@
 #include <dm/uclass.h>
 #include <dm/lists.h>
 #include <dm/device-internal.h>
+#include <linux/clk-provider.h>
 
 int clk_register(struct clk *clk, const char *drv_name,
 		 const char *name, const char *parent_name)
@@ -61,6 +62,14 @@ ulong clk_generic_get_rate(struct clk *clk)
 	return clk_get_parent_rate(clk);
 }
 
+ulong clk_generic_set_rate(struct clk *clk, ulong rate)
+{
+	if (clk->flags & CLK_SET_RATE_PARENT)
+		return clk_set_parent_rate(clk, rate);
+
+	return clk_get_parent_rate(clk);
+}
+
 const char *clk_hw_get_name(const struct clk *hw)
 {
 	assert(hw);
-- 
2.43.0



More information about the U-Boot mailing list