diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-05-25 03:55:05 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-05-25 03:55:05 -0400 |
commit | 609d7558f232e583a31951c65a6ee43d81c65720 (patch) | |
tree | f19d5ca7f1317aeec347b79010d49b5599bf7d0c /drivers/sh | |
parent | e3c87607731e1a8937567e92a52eedee1bec622d (diff) |
sh: clkfwk: Consolidate div clk registration helper.
This consolidates the div6/4 versions of the clk registration wrapper.
The existing wrappers with their own sh_clk_ops are maintained for API
compatability, though in the future it should be possible to be rid of
them entirely.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/clk/cpg.c | 182 |
1 files changed, 75 insertions, 107 deletions
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index eeaec796a395..07e9fb4f8041 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c | |||
@@ -162,6 +162,72 @@ static struct sh_clk_ops sh_clk_div_enable_clk_ops = { | |||
162 | .disable = sh_clk_div_disable, | 162 | .disable = sh_clk_div_disable, |
163 | }; | 163 | }; |
164 | 164 | ||
165 | static int __init sh_clk_init_parent(struct clk *clk) | ||
166 | { | ||
167 | u32 val; | ||
168 | |||
169 | if (clk->parent) | ||
170 | return 0; | ||
171 | |||
172 | if (!clk->parent_table || !clk->parent_num) | ||
173 | return 0; | ||
174 | |||
175 | if (!clk->src_width) { | ||
176 | pr_err("sh_clk_init_parent: cannot select parent clock\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | val = (sh_clk_read(clk) >> clk->src_shift); | ||
181 | val &= (1 << clk->src_width) - 1; | ||
182 | |||
183 | if (val >= clk->parent_num) { | ||
184 | pr_err("sh_clk_init_parent: parent table size failed\n"); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | clk_reparent(clk, clk->parent_table[val]); | ||
189 | if (!clk->parent) { | ||
190 | pr_err("sh_clk_init_parent: unable to set parent"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int __init sh_clk_div_register_ops(struct clk *clks, int nr, | ||
198 | struct clk_div_table *table, struct sh_clk_ops *ops) | ||
199 | { | ||
200 | struct clk *clkp; | ||
201 | void *freq_table; | ||
202 | int nr_divs = table->div_mult_table->nr_divisors; | ||
203 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
204 | int ret = 0; | ||
205 | int k; | ||
206 | |||
207 | freq_table_size *= (nr_divs + 1); | ||
208 | freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); | ||
209 | if (!freq_table) { | ||
210 | pr_err("%s: unable to alloc memory\n", __func__); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | |||
214 | for (k = 0; !ret && (k < nr); k++) { | ||
215 | clkp = clks + k; | ||
216 | |||
217 | clkp->ops = ops; | ||
218 | clkp->priv = table; | ||
219 | |||
220 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
221 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
222 | |||
223 | ret = clk_register(clkp); | ||
224 | if (ret == 0) | ||
225 | ret = sh_clk_init_parent(clkp); | ||
226 | } | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | |||
165 | /* | 231 | /* |
166 | * div6 support | 232 | * div6 support |
167 | */ | 233 | */ |
@@ -223,82 +289,16 @@ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = { | |||
223 | .set_parent = sh_clk_div6_set_parent, | 289 | .set_parent = sh_clk_div6_set_parent, |
224 | }; | 290 | }; |
225 | 291 | ||
226 | static int __init sh_clk_init_parent(struct clk *clk) | ||
227 | { | ||
228 | u32 val; | ||
229 | |||
230 | if (clk->parent) | ||
231 | return 0; | ||
232 | |||
233 | if (!clk->parent_table || !clk->parent_num) | ||
234 | return 0; | ||
235 | |||
236 | if (!clk->src_width) { | ||
237 | pr_err("sh_clk_init_parent: cannot select parent clock\n"); | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | val = (sh_clk_read(clk) >> clk->src_shift); | ||
242 | val &= (1 << clk->src_width) - 1; | ||
243 | |||
244 | if (val >= clk->parent_num) { | ||
245 | pr_err("sh_clk_init_parent: parent table size failed\n"); | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | clk_reparent(clk, clk->parent_table[val]); | ||
250 | if (!clk->parent) { | ||
251 | pr_err("sh_clk_init_parent: unable to set parent"); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, | ||
259 | struct sh_clk_ops *ops) | ||
260 | { | ||
261 | struct clk *clkp; | ||
262 | void *freq_table; | ||
263 | struct clk_div_table *table = &sh_clk_div6_table; | ||
264 | int nr_divs = table->div_mult_table->nr_divisors; | ||
265 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
266 | int ret = 0; | ||
267 | int k; | ||
268 | |||
269 | freq_table_size *= (nr_divs + 1); | ||
270 | freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); | ||
271 | if (!freq_table) { | ||
272 | pr_err("sh_clk_div6_register: unable to alloc memory\n"); | ||
273 | return -ENOMEM; | ||
274 | } | ||
275 | |||
276 | for (k = 0; !ret && (k < nr); k++) { | ||
277 | clkp = clks + k; | ||
278 | |||
279 | clkp->ops = ops; | ||
280 | clkp->priv = table; | ||
281 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
282 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
283 | ret = clk_register(clkp); | ||
284 | if (ret < 0) | ||
285 | break; | ||
286 | |||
287 | ret = sh_clk_init_parent(clkp); | ||
288 | } | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | int __init sh_clk_div6_register(struct clk *clks, int nr) | 292 | int __init sh_clk_div6_register(struct clk *clks, int nr) |
294 | { | 293 | { |
295 | return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops); | 294 | return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, |
295 | &sh_clk_div_enable_clk_ops); | ||
296 | } | 296 | } |
297 | 297 | ||
298 | int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) | 298 | int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) |
299 | { | 299 | { |
300 | return sh_clk_div6_register_ops(clks, nr, | 300 | return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table, |
301 | &sh_clk_div6_reparent_clk_ops); | 301 | &sh_clk_div6_reparent_clk_ops); |
302 | } | 302 | } |
303 | 303 | ||
304 | /* | 304 | /* |
@@ -342,54 +342,22 @@ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = { | |||
342 | .set_parent = sh_clk_div4_set_parent, | 342 | .set_parent = sh_clk_div4_set_parent, |
343 | }; | 343 | }; |
344 | 344 | ||
345 | static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, | ||
346 | struct clk_div4_table *table, struct sh_clk_ops *ops) | ||
347 | { | ||
348 | struct clk *clkp; | ||
349 | void *freq_table; | ||
350 | int nr_divs = table->div_mult_table->nr_divisors; | ||
351 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
352 | int ret = 0; | ||
353 | int k; | ||
354 | |||
355 | freq_table_size *= (nr_divs + 1); | ||
356 | freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); | ||
357 | if (!freq_table) { | ||
358 | pr_err("sh_clk_div4_register: unable to alloc memory\n"); | ||
359 | return -ENOMEM; | ||
360 | } | ||
361 | |||
362 | for (k = 0; !ret && (k < nr); k++) { | ||
363 | clkp = clks + k; | ||
364 | |||
365 | clkp->ops = ops; | ||
366 | clkp->priv = table; | ||
367 | |||
368 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
369 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
370 | |||
371 | ret = clk_register(clkp); | ||
372 | } | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | int __init sh_clk_div4_register(struct clk *clks, int nr, | 345 | int __init sh_clk_div4_register(struct clk *clks, int nr, |
378 | struct clk_div4_table *table) | 346 | struct clk_div4_table *table) |
379 | { | 347 | { |
380 | return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops); | 348 | return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops); |
381 | } | 349 | } |
382 | 350 | ||
383 | int __init sh_clk_div4_enable_register(struct clk *clks, int nr, | 351 | int __init sh_clk_div4_enable_register(struct clk *clks, int nr, |
384 | struct clk_div4_table *table) | 352 | struct clk_div4_table *table) |
385 | { | 353 | { |
386 | return sh_clk_div4_register_ops(clks, nr, table, | 354 | return sh_clk_div_register_ops(clks, nr, table, |
387 | &sh_clk_div_enable_clk_ops); | 355 | &sh_clk_div_enable_clk_ops); |
388 | } | 356 | } |
389 | 357 | ||
390 | int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, | 358 | int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, |
391 | struct clk_div4_table *table) | 359 | struct clk_div4_table *table) |
392 | { | 360 | { |
393 | return sh_clk_div4_register_ops(clks, nr, table, | 361 | return sh_clk_div_register_ops(clks, nr, table, |
394 | &sh_clk_div4_reparent_clk_ops); | 362 | &sh_clk_div4_reparent_clk_ops); |
395 | } | 363 | } |