diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2012-10-30 23:06:55 -0400 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2012-11-08 01:21:30 -0500 |
commit | 9d626eccb1de90a310f3fb9bc5e8803706be1a95 (patch) | |
tree | 3f85ffb397427e040b4d047d53d3d4726852dd0f /drivers/sh | |
parent | 9d69f5b87e7f6df51ad2a70557474093de934a8c (diff) |
sh: clkfwk: add sh_clk_fsidiv_register()
This patch adds sh_clk_fsidiv_register() to share FSI-DIV clock code
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/clk/cpg.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 07e9fb4f8041..b3dc44146ca0 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c | |||
@@ -361,3 +361,89 @@ int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, | |||
361 | return sh_clk_div_register_ops(clks, nr, table, | 361 | return sh_clk_div_register_ops(clks, nr, table, |
362 | &sh_clk_div4_reparent_clk_ops); | 362 | &sh_clk_div4_reparent_clk_ops); |
363 | } | 363 | } |
364 | |||
365 | /* FSI-DIV */ | ||
366 | static unsigned long fsidiv_recalc(struct clk *clk) | ||
367 | { | ||
368 | u32 value; | ||
369 | |||
370 | value = __raw_readl(clk->mapping->base); | ||
371 | |||
372 | value >>= 16; | ||
373 | if (value < 2) | ||
374 | return clk->parent->rate; | ||
375 | |||
376 | return clk->parent->rate / value; | ||
377 | } | ||
378 | |||
379 | static long fsidiv_round_rate(struct clk *clk, unsigned long rate) | ||
380 | { | ||
381 | return clk_rate_div_range_round(clk, 1, 0xffff, rate); | ||
382 | } | ||
383 | |||
384 | static void fsidiv_disable(struct clk *clk) | ||
385 | { | ||
386 | __raw_writel(0, clk->mapping->base); | ||
387 | } | ||
388 | |||
389 | static int fsidiv_enable(struct clk *clk) | ||
390 | { | ||
391 | u32 value; | ||
392 | |||
393 | value = __raw_readl(clk->mapping->base) >> 16; | ||
394 | if (value < 2) | ||
395 | return 0; | ||
396 | |||
397 | __raw_writel((value << 16) | 0x3, clk->mapping->base); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int fsidiv_set_rate(struct clk *clk, unsigned long rate) | ||
403 | { | ||
404 | u32 val; | ||
405 | int idx; | ||
406 | |||
407 | idx = (clk->parent->rate / rate) & 0xffff; | ||
408 | if (idx < 2) | ||
409 | __raw_writel(0, clk->mapping->base); | ||
410 | else | ||
411 | __raw_writel(idx << 16, clk->mapping->base); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static struct sh_clk_ops fsidiv_clk_ops = { | ||
417 | .recalc = fsidiv_recalc, | ||
418 | .round_rate = fsidiv_round_rate, | ||
419 | .set_rate = fsidiv_set_rate, | ||
420 | .enable = fsidiv_enable, | ||
421 | .disable = fsidiv_disable, | ||
422 | }; | ||
423 | |||
424 | int __init sh_clk_fsidiv_register(struct clk *clks, int nr) | ||
425 | { | ||
426 | struct clk_mapping *map; | ||
427 | int i; | ||
428 | |||
429 | for (i = 0; i < nr; i++) { | ||
430 | |||
431 | map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL); | ||
432 | if (!map) { | ||
433 | pr_err("%s: unable to alloc memory\n", __func__); | ||
434 | return -ENOMEM; | ||
435 | } | ||
436 | |||
437 | /* clks[i].enable_reg came from SH_CLK_FSIDIV() */ | ||
438 | map->phys = (phys_addr_t)clks[i].enable_reg; | ||
439 | map->len = 8; | ||
440 | |||
441 | clks[i].enable_reg = 0; /* remove .enable_reg */ | ||
442 | clks[i].ops = &fsidiv_clk_ops; | ||
443 | clks[i].mapping = map; | ||
444 | |||
445 | clk_register(&clks[i]); | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||