aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2013-07-29 07:25:02 -0400
committerMike Turquette <mturquette@linaro.org>2013-08-19 15:27:18 -0400
commite366fdd72529c545ccf327569ee250c1673be221 (patch)
tree69139adc59e6ab101555f09544669793c385c250
parent819c1de344c5b8350bffd35be9a0fa74541292d3 (diff)
clk: clk-mux: implement remuxing on set_rate
Implement clk-mux remuxing if the CLK_SET_RATE_NO_REPARENT flag isn't set. This implements determine_rate for clk-mux to propagate to each parent and to choose the best one (like clk-divider this chooses the parent which provides the fastest rate <= the requested rate). The determine_rate op is implemented as a core helper function so that it can be easily used by more complex clocks which incorporate muxes. Signed-off-by: James Hogan <james.hogan@imgtec.com> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Cc: Mike Turquette <mturquette@linaro.org> Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r--drivers/clk/clk-mux.c1
-rw-r--r--drivers/clk/clk.c49
-rw-r--r--include/linux/clk-provider.h3
3 files changed, 53 insertions, 0 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index b918dc370bd0..0811633fcc4d 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -104,6 +104,7 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
104const struct clk_ops clk_mux_ops = { 104const struct clk_ops clk_mux_ops = {
105 .get_parent = clk_mux_get_parent, 105 .get_parent = clk_mux_get_parent,
106 .set_parent = clk_mux_set_parent, 106 .set_parent = clk_mux_set_parent,
107 .determine_rate = __clk_mux_determine_rate,
107}; 108};
108EXPORT_SYMBOL_GPL(clk_mux_ops); 109EXPORT_SYMBOL_GPL(clk_mux_ops);
109 110
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f33f1ccf1b2f..bc020372106b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -692,6 +692,55 @@ struct clk *__clk_lookup(const char *name)
692 return NULL; 692 return NULL;
693} 693}
694 694
695/*
696 * Helper for finding best parent to provide a given frequency. This can be used
697 * directly as a determine_rate callback (e.g. for a mux), or from a more
698 * complex clock that may combine a mux with other operations.
699 */
700long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
701 unsigned long *best_parent_rate,
702 struct clk **best_parent_p)
703{
704 struct clk *clk = hw->clk, *parent, *best_parent = NULL;
705 int i, num_parents;
706 unsigned long parent_rate, best = 0;
707
708 /* if NO_REPARENT flag set, pass through to current parent */
709 if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
710 parent = clk->parent;
711 if (clk->flags & CLK_SET_RATE_PARENT)
712 best = __clk_round_rate(parent, rate);
713 else if (parent)
714 best = __clk_get_rate(parent);
715 else
716 best = __clk_get_rate(clk);
717 goto out;
718 }
719
720 /* find the parent that can provide the fastest rate <= rate */
721 num_parents = clk->num_parents;
722 for (i = 0; i < num_parents; i++) {
723 parent = clk_get_parent_by_index(clk, i);
724 if (!parent)
725 continue;
726 if (clk->flags & CLK_SET_RATE_PARENT)
727 parent_rate = __clk_round_rate(parent, rate);
728 else
729 parent_rate = __clk_get_rate(parent);
730 if (parent_rate <= rate && parent_rate > best) {
731 best_parent = parent;
732 best = parent_rate;
733 }
734 }
735
736out:
737 if (best_parent)
738 *best_parent_p = best_parent;
739 *best_parent_rate = best;
740
741 return best;
742}
743
695/*** clk api ***/ 744/*** clk api ***/
696 745
697void __clk_unprepare(struct clk *clk) 746void __clk_unprepare(struct clk *clk)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5c0bc3904c9b..1f0285b2f422 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -436,6 +436,9 @@ unsigned long __clk_get_flags(struct clk *clk);
436bool __clk_is_prepared(struct clk *clk); 436bool __clk_is_prepared(struct clk *clk);
437bool __clk_is_enabled(struct clk *clk); 437bool __clk_is_enabled(struct clk *clk);
438struct clk *__clk_lookup(const char *name); 438struct clk *__clk_lookup(const char *name);
439long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
440 unsigned long *best_parent_rate,
441 struct clk **best_parent_p);
439 442
440/* 443/*
441 * FIXME clock api without lock protection 444 * FIXME clock api without lock protection