diff options
author | Emilio López <emilio@elopez.com.ar> | 2014-05-02 11:57:15 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2014-05-05 18:55:56 -0400 |
commit | 862b728387aef3a3776ad2a261e484aff36c5e67 (patch) | |
tree | 2a6cf568537a30530a5ca554376759b2d565b22d /drivers/clk/sunxi | |
parent | 2c07e3c7dd487fa40983aa20704b2755c9aac477 (diff) |
clk: sunxi: factors: automatic reparenting support
This commit implements .determine_rate, so that our factor clocks can be
reparented when needed.
Signed-off-by: Emilio López <emilio@elopez.com.ar>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/sunxi')
-rw-r--r-- | drivers/clk/sunxi/clk-factors.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index 9e232644f07e..3806d97e529b 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c | |||
@@ -77,6 +77,41 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, | |||
77 | return rate; | 77 | return rate; |
78 | } | 78 | } |
79 | 79 | ||
80 | static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
81 | unsigned long *best_parent_rate, | ||
82 | struct clk **best_parent_p) | ||
83 | { | ||
84 | struct clk *clk = hw->clk, *parent, *best_parent = NULL; | ||
85 | int i, num_parents; | ||
86 | unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; | ||
87 | |||
88 | /* find the parent that can help provide the fastest rate <= rate */ | ||
89 | num_parents = __clk_get_num_parents(clk); | ||
90 | for (i = 0; i < num_parents; i++) { | ||
91 | parent = clk_get_parent_by_index(clk, i); | ||
92 | if (!parent) | ||
93 | continue; | ||
94 | if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT) | ||
95 | parent_rate = __clk_round_rate(parent, rate); | ||
96 | else | ||
97 | parent_rate = __clk_get_rate(parent); | ||
98 | |||
99 | child_rate = clk_factors_round_rate(hw, rate, &parent_rate); | ||
100 | |||
101 | if (child_rate <= rate && child_rate > best_child_rate) { | ||
102 | best_parent = parent; | ||
103 | best = parent_rate; | ||
104 | best_child_rate = child_rate; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | if (best_parent) | ||
109 | *best_parent_p = best_parent; | ||
110 | *best_parent_rate = best; | ||
111 | |||
112 | return best_child_rate; | ||
113 | } | ||
114 | |||
80 | static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, | 115 | static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, |
81 | unsigned long parent_rate) | 116 | unsigned long parent_rate) |
82 | { | 117 | { |
@@ -113,6 +148,7 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, | |||
113 | } | 148 | } |
114 | 149 | ||
115 | const struct clk_ops clk_factors_ops = { | 150 | const struct clk_ops clk_factors_ops = { |
151 | .determine_rate = clk_factors_determine_rate, | ||
116 | .recalc_rate = clk_factors_recalc_rate, | 152 | .recalc_rate = clk_factors_recalc_rate, |
117 | .round_rate = clk_factors_round_rate, | 153 | .round_rate = clk_factors_round_rate, |
118 | .set_rate = clk_factors_set_rate, | 154 | .set_rate = clk_factors_set_rate, |