@@ -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,
@@ -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,
@@ -516,6 +516,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;
@@ -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);
@@ -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
@@ -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);
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@linaro.org> Signed-off-by: Michael Trimarchi <michael@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(-)