diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-03 02:26:33 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-03 02:26:33 -0400 |
commit | c50e86ce7c2961a41f2f7aa6e4fd6c99229ba205 (patch) | |
tree | 4ea36009719bd8fc523239fe1bdccb90f0dce3ae /drivers/clk/clk-divider.c | |
parent | 14d33d384693eb6083396199de516fdef320f7af (diff) | |
parent | 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d (diff) |
Merge tag 'v3.6-rc4'
Merge 3.6-rc4 to get latest OMAP and device tree fixes.
Diffstat (limited to 'drivers/clk/clk-divider.c')
-rw-r--r-- | drivers/clk/clk-divider.c | 189 |
1 files changed, 155 insertions, 34 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 8ea11b444528..a9204c69148d 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
@@ -30,18 +30,89 @@ | |||
30 | #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) | 30 | #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) |
31 | 31 | ||
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) | ||
34 | |||
35 | static 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 | |||
46 | static unsigned int _get_maxdiv(struct clk_divider *divider) | ||
47 | { | ||
48 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | ||
49 | return div_mask(divider); | ||
50 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | ||
51 | return 1 << div_mask(divider); | ||
52 | if (divider->table) | ||
53 | return _get_table_maxdiv(divider->table); | ||
54 | return div_mask(divider) + 1; | ||
55 | } | ||
56 | |||
57 | static 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 | |||
68 | static unsigned int _get_div(struct clk_divider *divider, unsigned int val) | ||
69 | { | ||
70 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | ||
71 | return val; | ||
72 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | ||
73 | return 1 << val; | ||
74 | if (divider->table) | ||
75 | return _get_table_div(divider->table, val); | ||
76 | return val + 1; | ||
77 | } | ||
78 | |||
79 | static 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 | |||
90 | static unsigned int _get_val(struct clk_divider *divider, u8 div) | ||
91 | { | ||
92 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | ||
93 | return div; | ||
94 | if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) | ||
95 | return __ffs(div); | ||
96 | if (divider->table) | ||
97 | return _get_table_val(divider->table, div); | ||
98 | return div - 1; | ||
99 | } | ||
33 | 100 | ||
34 | static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | 101 | static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, |
35 | unsigned long parent_rate) | 102 | unsigned long parent_rate) |
36 | { | 103 | { |
37 | struct clk_divider *divider = to_clk_divider(hw); | 104 | struct clk_divider *divider = to_clk_divider(hw); |
38 | unsigned int div; | 105 | unsigned int div, val; |
39 | 106 | ||
40 | div = readl(divider->reg) >> divider->shift; | 107 | val = readl(divider->reg) >> divider->shift; |
41 | div &= div_mask(divider); | 108 | val &= div_mask(divider); |
42 | 109 | ||
43 | if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) | 110 | div = _get_div(divider, val); |
44 | div++; | 111 | if (!div) { |
112 | WARN(1, "%s: Invalid divisor for clock %s\n", __func__, | ||
113 | __clk_get_name(hw->clk)); | ||
114 | return parent_rate; | ||
115 | } | ||
45 | 116 | ||
46 | return parent_rate / div; | 117 | return parent_rate / div; |
47 | } | 118 | } |
@@ -52,6 +123,26 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | |||
52 | */ | 123 | */ |
53 | #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) | 124 | #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) |
54 | 125 | ||
126 | static 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 | |||
137 | static 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 | |||
55 | static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | 146 | static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, |
56 | unsigned long *best_parent_rate) | 147 | unsigned long *best_parent_rate) |
57 | { | 148 | { |
@@ -62,10 +153,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
62 | if (!rate) | 153 | if (!rate) |
63 | rate = 1; | 154 | rate = 1; |
64 | 155 | ||
65 | maxdiv = (1 << divider->width); | 156 | maxdiv = _get_maxdiv(divider); |
66 | |||
67 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | ||
68 | maxdiv--; | ||
69 | 157 | ||
70 | if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { | 158 | if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { |
71 | parent_rate = *best_parent_rate; | 159 | parent_rate = *best_parent_rate; |
@@ -82,6 +170,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
82 | maxdiv = min(ULONG_MAX / rate, maxdiv); | 170 | maxdiv = min(ULONG_MAX / rate, maxdiv); |
83 | 171 | ||
84 | for (i = 1; i <= maxdiv; i++) { | 172 | for (i = 1; i <= maxdiv; i++) { |
173 | if (!_is_valid_div(divider, i)) | ||
174 | continue; | ||
85 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), | 175 | parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), |
86 | MULT_ROUND_UP(rate, i)); | 176 | MULT_ROUND_UP(rate, i)); |
87 | now = parent_rate / i; | 177 | now = parent_rate / i; |
@@ -93,9 +183,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, | |||
93 | } | 183 | } |
94 | 184 | ||
95 | if (!bestdiv) { | 185 | if (!bestdiv) { |
96 | bestdiv = (1 << divider->width); | 186 | bestdiv = _get_maxdiv(divider); |
97 | if (divider->flags & CLK_DIVIDER_ONE_BASED) | ||
98 | bestdiv--; | ||
99 | *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1); | 187 | *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1); |
100 | } | 188 | } |
101 | 189 | ||
@@ -115,24 +203,22 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |||
115 | unsigned long parent_rate) | 203 | unsigned long parent_rate) |
116 | { | 204 | { |
117 | struct clk_divider *divider = to_clk_divider(hw); | 205 | struct clk_divider *divider = to_clk_divider(hw); |
118 | unsigned int div; | 206 | unsigned int div, value; |
119 | unsigned long flags = 0; | 207 | unsigned long flags = 0; |
120 | u32 val; | 208 | u32 val; |
121 | 209 | ||
122 | div = parent_rate / rate; | 210 | div = parent_rate / rate; |
211 | value = _get_val(divider, div); | ||
123 | 212 | ||
124 | if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) | 213 | if (value > div_mask(divider)) |
125 | div--; | 214 | value = div_mask(divider); |
126 | |||
127 | if (div > div_mask(divider)) | ||
128 | div = div_mask(divider); | ||
129 | 215 | ||
130 | if (divider->lock) | 216 | if (divider->lock) |
131 | spin_lock_irqsave(divider->lock, flags); | 217 | spin_lock_irqsave(divider->lock, flags); |
132 | 218 | ||
133 | val = readl(divider->reg); | 219 | val = readl(divider->reg); |
134 | val &= ~(div_mask(divider) << divider->shift); | 220 | val &= ~(div_mask(divider) << divider->shift); |
135 | val |= div << divider->shift; | 221 | val |= value << divider->shift; |
136 | writel(val, divider->reg); | 222 | writel(val, divider->reg); |
137 | 223 | ||
138 | if (divider->lock) | 224 | if (divider->lock) |
@@ -148,22 +234,11 @@ const struct clk_ops clk_divider_ops = { | |||
148 | }; | 234 | }; |
149 | EXPORT_SYMBOL_GPL(clk_divider_ops); | 235 | EXPORT_SYMBOL_GPL(clk_divider_ops); |
150 | 236 | ||
151 | /** | 237 | static struct clk *_register_divider(struct device *dev, const char *name, |
152 | * clk_register_divider - register a divider clock with the clock framework | ||
153 | * @dev: device registering this clock | ||
154 | * @name: name of this clock | ||
155 | * @parent_name: name of clock's parent | ||
156 | * @flags: framework-specific flags | ||
157 | * @reg: register address to adjust divider | ||
158 | * @shift: number of bits to shift the bitfield | ||
159 | * @width: width of the bitfield | ||
160 | * @clk_divider_flags: divider-specific flags for this clock | ||
161 | * @lock: shared register lock for this clock | ||
162 | */ | ||
163 | struct clk *clk_register_divider(struct device *dev, const char *name, | ||
164 | const char *parent_name, unsigned long flags, | 238 | const char *parent_name, unsigned long flags, |
165 | void __iomem *reg, u8 shift, u8 width, | 239 | void __iomem *reg, u8 shift, u8 width, |
166 | u8 clk_divider_flags, spinlock_t *lock) | 240 | u8 clk_divider_flags, const struct clk_div_table *table, |
241 | spinlock_t *lock) | ||
167 | { | 242 | { |
168 | struct clk_divider *div; | 243 | struct clk_divider *div; |
169 | struct clk *clk; | 244 | struct clk *clk; |
@@ -178,7 +253,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name, | |||
178 | 253 | ||
179 | init.name = name; | 254 | init.name = name; |
180 | init.ops = &clk_divider_ops; | 255 | init.ops = &clk_divider_ops; |
181 | init.flags = flags; | 256 | init.flags = flags | CLK_IS_BASIC; |
182 | init.parent_names = (parent_name ? &parent_name: NULL); | 257 | init.parent_names = (parent_name ? &parent_name: NULL); |
183 | init.num_parents = (parent_name ? 1 : 0); | 258 | init.num_parents = (parent_name ? 1 : 0); |
184 | 259 | ||
@@ -189,6 +264,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name, | |||
189 | div->flags = clk_divider_flags; | 264 | div->flags = clk_divider_flags; |
190 | div->lock = lock; | 265 | div->lock = lock; |
191 | div->hw.init = &init; | 266 | div->hw.init = &init; |
267 | div->table = table; | ||
192 | 268 | ||
193 | /* register the clock */ | 269 | /* register the clock */ |
194 | clk = clk_register(dev, &div->hw); | 270 | clk = clk_register(dev, &div->hw); |
@@ -198,3 +274,48 @@ struct clk *clk_register_divider(struct device *dev, const char *name, | |||
198 | 274 | ||
199 | return clk; | 275 | return clk; |
200 | } | 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 | */ | ||
290 | struct 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 | */ | ||
313 | struct 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 | } | ||