aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/clk/cpg.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-05-25 03:55:05 -0400
committerPaul Mundt <lethal@linux-sh.org>2012-05-25 03:55:05 -0400
commit609d7558f232e583a31951c65a6ee43d81c65720 (patch)
treef19d5ca7f1317aeec347b79010d49b5599bf7d0c /drivers/sh/clk/cpg.c
parente3c87607731e1a8937567e92a52eedee1bec622d (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/clk/cpg.c')
-rw-r--r--drivers/sh/clk/cpg.c182
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
165static 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
197static 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
226static 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
258static 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
293int __init sh_clk_div6_register(struct clk *clks, int nr) 292int __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
298int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) 298int __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
345static 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
377int __init sh_clk_div4_register(struct clk *clks, int nr, 345int __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
383int __init sh_clk_div4_enable_register(struct clk *clks, int nr, 351int __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
390int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, 358int __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}