aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorBoris BREZILLON <b.brezillon@overkiz.com>2014-03-11 05:00:32 -0400
committerMike Turquette <mturquette@linaro.org>2014-03-19 18:21:39 -0400
commit419f612932674d5f72b1995eda52ca15d87361ef (patch)
tree21b9bf077747370798922dbffaeb2662c4426d3e /drivers/clk
parent843bad8361bb0d7e5ed6254c84abd8d2ec61b6a4 (diff)
clk: at91: replace prog clk round_rate with determine_rate
Implement the determine_rate callback to choose the best parent clk that fulfills the requested rate. Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/at91/clk-programmable.c56
1 files changed, 28 insertions, 28 deletions
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index fd792b203eaf..eff701665f04 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -102,40 +102,40 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
102 return parent_rate >> prog->pres; 102 return parent_rate >> prog->pres;
103} 103}
104 104
105static long clk_programmable_round_rate(struct clk_hw *hw, unsigned long rate, 105static long clk_programmable_determine_rate(struct clk_hw *hw,
106 unsigned long *parent_rate) 106 unsigned long rate,
107 unsigned long *best_parent_rate,
108 struct clk **best_parent_clk)
107{ 109{
108 unsigned long best_rate = *parent_rate; 110 struct clk *parent = NULL;
109 unsigned long best_diff; 111 long best_rate = -EINVAL;
110 unsigned long new_diff; 112 unsigned long parent_rate;
111 unsigned long cur_rate; 113 unsigned long tmp_rate;
112 int shift = shift; 114 int shift;
113 115 int i;
114 if (rate > *parent_rate)
115 return *parent_rate;
116 else
117 best_diff = *parent_rate - rate;
118
119 if (!best_diff)
120 return best_rate;
121 116
122 for (shift = 1; shift < PROG_PRES_MASK; shift++) { 117 for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
123 cur_rate = *parent_rate >> shift; 118 parent = clk_get_parent_by_index(hw->clk, i);
119 if (!parent)
120 continue;
124 121
125 if (cur_rate > rate) 122 parent_rate = __clk_get_rate(parent);
126 new_diff = cur_rate - rate; 123 for (shift = 0; shift < PROG_PRES_MASK; shift++) {
127 else 124 tmp_rate = parent_rate >> shift;
128 new_diff = rate - cur_rate; 125 if (tmp_rate <= rate)
126 break;
127 }
129 128
130 if (!new_diff) 129 if (tmp_rate > rate)
131 return cur_rate; 130 continue;
132 131
133 if (new_diff < best_diff) { 132 if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) {
134 best_diff = new_diff; 133 best_rate = tmp_rate;
135 best_rate = cur_rate; 134 *best_parent_rate = parent_rate;
135 *best_parent_clk = parent;
136 } 136 }
137 137
138 if (rate > cur_rate) 138 if (!best_rate)
139 break; 139 break;
140 } 140 }
141 141
@@ -228,7 +228,7 @@ static const struct clk_ops programmable_ops = {
228 .prepare = clk_programmable_prepare, 228 .prepare = clk_programmable_prepare,
229 .is_prepared = clk_programmable_is_ready, 229 .is_prepared = clk_programmable_is_ready,
230 .recalc_rate = clk_programmable_recalc_rate, 230 .recalc_rate = clk_programmable_recalc_rate,
231 .round_rate = clk_programmable_round_rate, 231 .determine_rate = clk_programmable_determine_rate,
232 .get_parent = clk_programmable_get_parent, 232 .get_parent = clk_programmable_get_parent,
233 .set_parent = clk_programmable_set_parent, 233 .set_parent = clk_programmable_set_parent,
234 .set_rate = clk_programmable_set_rate, 234 .set_rate = clk_programmable_set_rate,