From: Michael Trimarchi <mich...@amarulasolutions.com>

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.

Signed-off-by: Michael Trimarchi <mich...@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binac...@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 +++++++++
 include/clk.h                |  9 +++++++++
 include/linux/clk-provider.h |  1 +
 6 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index bf1c6a93b468..bd0d3d44ac8c 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -115,6 +115,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 62477e15d27a..4feb8e8c821d 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -150,13 +150,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 16169dac2340..e8db9b0ff2fd 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -515,6 +515,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 b8c2e8d531b9..67c6b23231ff 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -13,6 +13,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)
@@ -60,6 +61,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);
diff --git a/include/clk.h b/include/clk.h
index 045e923a529b..f0fd524ee519 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -452,6 +452,15 @@ struct clk *clk_get_parent(struct clk *clk);
  */
 ulong clk_get_parent_rate(struct clk *clk);
 
+/**
+ * clk_set_parent_rate() - Set parent of current clock rate.
+ * @clk:       A clock struct that was previously successfully requested by
+ *             clk_request/get_by_*().
+ *
+ * Return: clock rate in Hz, or -ve error code.
+ */
+ulong clk_set_parent_rate(struct clk *clk, ulong rate);
+
 /**
  * clk_round_rate() - Adjust a rate to the exact rate a clock can provide
  * @clk: A clock struct that was previously successfully requested by
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 59f9c241b846..459fa2d15ceb 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -253,6 +253,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, 
const char *name,
 
 const char *clk_hw_get_name(const struct clk *hw);
 ulong clk_generic_get_rate(struct clk *clk);
+ulong clk_generic_set_rate(struct clk *clk, ulong rate);
 
 struct clk *dev_get_clk_ptr(struct udevice *dev);
 
-- 
2.43.0

Reply via email to