aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-divider.c
diff options
context:
space:
mode:
authorRajendra Nayak <rnayak@ti.com>2012-06-29 09:36:32 -0400
committerMike Turquette <mturquette@linaro.org>2012-07-11 18:36:42 -0400
commit357c3f0a6c7613f7230fcaf1eb16190ed2a4b0af (patch)
treeab2067f4d31b734a0e5e01bbcd32fad190e0baea /drivers/clk/clk-divider.c
parent6d9252bd9a4bb1dadc1f199fd276e3464a251085 (diff)
clk: Add support for rate table based dividers
Some divider clks do not have any obvious relationship between the divider and the value programmed in the register. For instance, say a value of 1 could signify divide by 6 and a value of 2 could signify divide by 4 etc. Also there are dividers where not all values possible based on the bitfield width are valid. For instance a 3 bit wide bitfield can be used to program a value from 0 to 7. However its possible that only 0 to 4 are valid values. All these cases need the platform code to pass a simple table of divider/value tuple, so the framework knows the exact value to be written based on the divider calculation and can also do better error checking. This patch adds support for such rate table based dividers and as part of the support adds a new registration function 'clk_register_divider_table()' and a new macro for static definition 'DEFINE_CLK_DIVIDER_TABLE'. Signed-off-by: Rajendra Nayak <rnayak@ti.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clk-divider.c')
-rw-r--r--drivers/clk/clk-divider.c125
1 files changed, 109 insertions, 16 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index e548c4328f3c..02a4da98176b 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -32,30 +32,69 @@
32#define div_mask(d) ((1 << (d->width)) - 1) 32#define div_mask(d) ((1 << (d->width)) - 1)
33#define is_power_of_two(i) !(i & ~i) 33#define is_power_of_two(i) !(i & ~i)
34 34
35static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
36{
37 unsigned int maxdiv = 0;
38 const struct clk_div_table *clkt;
39
40 for (clkt = table; clkt->div; clkt++)
41 if (clkt->div > maxdiv)
42 maxdiv = clkt->div;
43 return maxdiv;
44}
45
35static unsigned int _get_maxdiv(struct clk_divider *divider) 46static unsigned int _get_maxdiv(struct clk_divider *divider)
36{ 47{
37 if (divider->flags & CLK_DIVIDER_ONE_BASED) 48 if (divider->flags & CLK_DIVIDER_ONE_BASED)
38 return div_mask(divider); 49 return div_mask(divider);
39 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) 50 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
40 return 1 << div_mask(divider); 51 return 1 << div_mask(divider);
52 if (divider->table)
53 return _get_table_maxdiv(divider->table);
41 return div_mask(divider) + 1; 54 return div_mask(divider) + 1;
42} 55}
43 56
57static unsigned int _get_table_div(const struct clk_div_table *table,
58 unsigned int val)
59{
60 const struct clk_div_table *clkt;
61
62 for (clkt = table; clkt->div; clkt++)
63 if (clkt->val == val)
64 return clkt->div;
65 return 0;
66}
67
44static unsigned int _get_div(struct clk_divider *divider, unsigned int val) 68static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
45{ 69{
46 if (divider->flags & CLK_DIVIDER_ONE_BASED) 70 if (divider->flags & CLK_DIVIDER_ONE_BASED)
47 return val; 71 return val;
48 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) 72 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
49 return 1 << val; 73 return 1 << val;
74 if (divider->table)
75 return _get_table_div(divider->table, val);
50 return val + 1; 76 return val + 1;
51} 77}
52 78
79static unsigned int _get_table_val(const struct clk_div_table *table,
80 unsigned int div)
81{
82 const struct clk_div_table *clkt;
83
84 for (clkt = table; clkt->div; clkt++)
85 if (clkt->div == div)
86 return clkt->val;
87 return 0;
88}
89
53static unsigned int _get_val(struct clk_divider *divider, u8 div) 90static unsigned int _get_val(struct clk_divider *divider, u8 div)
54{ 91{
55 if (divider->flags & CLK_DIVIDER_ONE_BASED) 92 if (divider->flags & CLK_DIVIDER_ONE_BASED)
56 return div; 93 return div;
57 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) 94 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
58 return __ffs(div); 95 return __ffs(div);
96 if (divider->table)
97 return _get_table_val(divider->table, div);
59 return div - 1; 98 return div - 1;
60} 99}
61 100
@@ -84,6 +123,26 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
84 */ 123 */
85#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) 124#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
86 125
126static bool _is_valid_table_div(const struct clk_div_table *table,
127 unsigned int div)
128{
129 const struct clk_div_table *clkt;
130
131 for (clkt = table; clkt->div; clkt++)
132 if (clkt->div == div)
133 return true;
134 return false;
135}
136
137static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
138{
139 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
140 return is_power_of_two(div);
141 if (divider->table)
142 return _is_valid_table_div(divider->table, div);
143 return true;
144}
145
87static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, 146static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
88 unsigned long *best_parent_rate) 147 unsigned long *best_parent_rate)
89{ 148{
@@ -111,8 +170,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
111 maxdiv = min(ULONG_MAX / rate, maxdiv); 170 maxdiv = min(ULONG_MAX / rate, maxdiv);
112 171
113 for (i = 1; i <= maxdiv; i++) { 172 for (i = 1; i <= maxdiv; i++) {
114 if ((divider->flags & CLK_DIVIDER_POWER_OF_TWO) 173 if (!_is_valid_div(divider, i))
115 && (!is_power_of_two(i)))
116 continue; 174 continue;
117 parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 175 parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
118 MULT_ROUND_UP(rate, i)); 176 MULT_ROUND_UP(rate, i));
@@ -176,22 +234,11 @@ const struct clk_ops clk_divider_ops = {
176}; 234};
177EXPORT_SYMBOL_GPL(clk_divider_ops); 235EXPORT_SYMBOL_GPL(clk_divider_ops);
178 236
179/** 237static struct clk *_register_divider(struct device *dev, const char *name,
180 * clk_register_divider - register a divider clock with the clock framework
181 * @dev: device registering this clock
182 * @name: name of this clock
183 * @parent_name: name of clock's parent
184 * @flags: framework-specific flags
185 * @reg: register address to adjust divider
186 * @shift: number of bits to shift the bitfield
187 * @width: width of the bitfield
188 * @clk_divider_flags: divider-specific flags for this clock
189 * @lock: shared register lock for this clock
190 */
191struct clk *clk_register_divider(struct device *dev, const char *name,
192 const char *parent_name, unsigned long flags, 238 const char *parent_name, unsigned long flags,
193 void __iomem *reg, u8 shift, u8 width, 239 void __iomem *reg, u8 shift, u8 width,
194 u8 clk_divider_flags, spinlock_t *lock) 240 u8 clk_divider_flags, const struct clk_div_table *table,
241 spinlock_t *lock)
195{ 242{
196 struct clk_divider *div; 243 struct clk_divider *div;
197 struct clk *clk; 244 struct clk *clk;
@@ -217,6 +264,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
217 div->flags = clk_divider_flags; 264 div->flags = clk_divider_flags;
218 div->lock = lock; 265 div->lock = lock;
219 div->hw.init = &init; 266 div->hw.init = &init;
267 div->table = table;
220 268
221 /* register the clock */ 269 /* register the clock */
222 clk = clk_register(dev, &div->hw); 270 clk = clk_register(dev, &div->hw);
@@ -226,3 +274,48 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
226 274
227 return clk; 275 return clk;
228} 276}
277
278/**
279 * clk_register_divider - register a divider clock with the clock framework
280 * @dev: device registering this clock
281 * @name: name of this clock
282 * @parent_name: name of clock's parent
283 * @flags: framework-specific flags
284 * @reg: register address to adjust divider
285 * @shift: number of bits to shift the bitfield
286 * @width: width of the bitfield
287 * @clk_divider_flags: divider-specific flags for this clock
288 * @lock: shared register lock for this clock
289 */
290struct clk *clk_register_divider(struct device *dev, const char *name,
291 const char *parent_name, unsigned long flags,
292 void __iomem *reg, u8 shift, u8 width,
293 u8 clk_divider_flags, spinlock_t *lock)
294{
295 return _register_divider(dev, name, parent_name, flags, reg, shift,
296 width, clk_divider_flags, NULL, lock);
297}
298
299/**
300 * clk_register_divider_table - register a table based divider clock with
301 * the clock framework
302 * @dev: device registering this clock
303 * @name: name of this clock
304 * @parent_name: name of clock's parent
305 * @flags: framework-specific flags
306 * @reg: register address to adjust divider
307 * @shift: number of bits to shift the bitfield
308 * @width: width of the bitfield
309 * @clk_divider_flags: divider-specific flags for this clock
310 * @table: array of divider/value pairs ending with a div set to 0
311 * @lock: shared register lock for this clock
312 */
313struct clk *clk_register_divider_table(struct device *dev, const char *name,
314 const char *parent_name, unsigned long flags,
315 void __iomem *reg, u8 shift, u8 width,
316 u8 clk_divider_flags, const struct clk_div_table *table,
317 spinlock_t *lock)
318{
319 return _register_divider(dev, name, parent_name, flags, reg, shift,
320 width, clk_divider_flags, table, lock);
321}