aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/clk/clk-divider.c125
-rw-r--r--include/linux/clk-private.h20
-rw-r--r--include/linux/clk-provider.h12
3 files changed, 139 insertions, 18 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}
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index eb3f84bc5325..cc9972d1429c 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -103,9 +103,9 @@ struct clk {
103 DEFINE_CLK(_name, clk_gate_ops, _flags, \ 103 DEFINE_CLK(_name, clk_gate_ops, _flags, \
104 _name##_parent_names, _name##_parents); 104 _name##_parent_names, _name##_parents);
105 105
106#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \ 106#define _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
107 _flags, _reg, _shift, _width, \ 107 _flags, _reg, _shift, _width, \
108 _divider_flags, _lock) \ 108 _divider_flags, _table, _lock) \
109 static struct clk _name; \ 109 static struct clk _name; \
110 static const char *_name##_parent_names[] = { \ 110 static const char *_name##_parent_names[] = { \
111 _parent_name, \ 111 _parent_name, \
@@ -121,11 +121,27 @@ struct clk {
121 .shift = _shift, \ 121 .shift = _shift, \
122 .width = _width, \ 122 .width = _width, \
123 .flags = _divider_flags, \ 123 .flags = _divider_flags, \
124 .table = _table, \
124 .lock = _lock, \ 125 .lock = _lock, \
125 }; \ 126 }; \
126 DEFINE_CLK(_name, clk_divider_ops, _flags, \ 127 DEFINE_CLK(_name, clk_divider_ops, _flags, \
127 _name##_parent_names, _name##_parents); 128 _name##_parent_names, _name##_parents);
128 129
130#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
131 _flags, _reg, _shift, _width, \
132 _divider_flags, _lock) \
133 _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
134 _flags, _reg, _shift, _width, \
135 _divider_flags, NULL, _lock)
136
137#define DEFINE_CLK_DIVIDER_TABLE(_name, _parent_name, \
138 _parent_ptr, _flags, _reg, \
139 _shift, _width, _divider_flags, \
140 _table, _lock) \
141 _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
142 _flags, _reg, _shift, _width, \
143 _divider_flags, _table, _lock) \
144
129#define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags, \ 145#define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags, \
130 _reg, _shift, _width, \ 146 _reg, _shift, _width, \
131 _mux_flags, _lock) \ 147 _mux_flags, _lock) \
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 4a0b483986c3..79caee9f1489 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -203,6 +203,11 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
203 void __iomem *reg, u8 bit_idx, 203 void __iomem *reg, u8 bit_idx,
204 u8 clk_gate_flags, spinlock_t *lock); 204 u8 clk_gate_flags, spinlock_t *lock);
205 205
206struct clk_div_table {
207 unsigned int val;
208 unsigned int div;
209};
210
206/** 211/**
207 * struct clk_divider - adjustable divider clock 212 * struct clk_divider - adjustable divider clock
208 * 213 *
@@ -210,6 +215,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
210 * @reg: register containing the divider 215 * @reg: register containing the divider
211 * @shift: shift to the divider bit field 216 * @shift: shift to the divider bit field
212 * @width: width of the divider bit field 217 * @width: width of the divider bit field
218 * @table: array of value/divider pairs, last entry should have div = 0
213 * @lock: register lock 219 * @lock: register lock
214 * 220 *
215 * Clock with an adjustable divider affecting its output frequency. Implements 221 * Clock with an adjustable divider affecting its output frequency. Implements
@@ -229,6 +235,7 @@ struct clk_divider {
229 u8 shift; 235 u8 shift;
230 u8 width; 236 u8 width;
231 u8 flags; 237 u8 flags;
238 const struct clk_div_table *table;
232 spinlock_t *lock; 239 spinlock_t *lock;
233}; 240};
234 241
@@ -240,6 +247,11 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
240 const char *parent_name, unsigned long flags, 247 const char *parent_name, unsigned long flags,
241 void __iomem *reg, u8 shift, u8 width, 248 void __iomem *reg, u8 shift, u8 width,
242 u8 clk_divider_flags, spinlock_t *lock); 249 u8 clk_divider_flags, spinlock_t *lock);
250struct clk *clk_register_divider_table(struct device *dev, const char *name,
251 const char *parent_name, unsigned long flags,
252 void __iomem *reg, u8 shift, u8 width,
253 u8 clk_divider_flags, const struct clk_div_table *table,
254 spinlock_t *lock);
243 255
244/** 256/**
245 * struct clk_mux - multiplexer clock 257 * struct clk_mux - multiplexer clock