diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2010-10-17 23:50:39 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-10-31 10:40:45 -0400 |
commit | f2ace4a5d754c07503326d66ec85bf65e03d729d (patch) | |
tree | e309065e67fead6359102ae9609bcff86cd83851 /arch/arm/mach-shmobile | |
parent | 03ff858c09c81a659b2a90a08826bc0abdbb784c (diff) |
ARM: mach-shmobile: clock-sh7372: Add FSIDIV clock support
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r-- | arch/arm/mach-shmobile/clock-sh7372.c | 101 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/sh7372.h | 2 |
2 files changed, 103 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 8565aefa21fd..fe7fa1550d36 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c | |||
@@ -50,6 +50,9 @@ | |||
50 | #define SMSTPCR3 0xe615013c | 50 | #define SMSTPCR3 0xe615013c |
51 | #define SMSTPCR4 0xe6150140 | 51 | #define SMSTPCR4 0xe6150140 |
52 | 52 | ||
53 | #define FSIDIVA 0xFE1F8000 | ||
54 | #define FSIDIVB 0xFE1F8008 | ||
55 | |||
53 | /* Platforms must set frequency on their DV_CLKI pin */ | 56 | /* Platforms must set frequency on their DV_CLKI pin */ |
54 | struct clk sh7372_dv_clki_clk = { | 57 | struct clk sh7372_dv_clki_clk = { |
55 | }; | 58 | }; |
@@ -417,6 +420,101 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { | |||
417 | fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2), | 420 | fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2), |
418 | }; | 421 | }; |
419 | 422 | ||
423 | /* FSI DIV */ | ||
424 | static unsigned long fsidiv_recalc(struct clk *clk) | ||
425 | { | ||
426 | unsigned long value; | ||
427 | |||
428 | value = __raw_readl(clk->mapping->base); | ||
429 | |||
430 | if ((value & 0x3) != 0x3) | ||
431 | return 0; | ||
432 | |||
433 | value >>= 16; | ||
434 | if (value < 2) | ||
435 | return 0; | ||
436 | |||
437 | return clk->parent->rate / value; | ||
438 | } | ||
439 | |||
440 | static long fsidiv_round_rate(struct clk *clk, unsigned long rate) | ||
441 | { | ||
442 | return clk_rate_div_range_round(clk, 2, 0xffff, rate); | ||
443 | } | ||
444 | |||
445 | static void fsidiv_disable(struct clk *clk) | ||
446 | { | ||
447 | __raw_writel(0, clk->mapping->base); | ||
448 | } | ||
449 | |||
450 | static int fsidiv_enable(struct clk *clk) | ||
451 | { | ||
452 | unsigned long value; | ||
453 | |||
454 | value = __raw_readl(clk->mapping->base) >> 16; | ||
455 | if (value < 2) { | ||
456 | fsidiv_disable(clk); | ||
457 | return -ENOENT; | ||
458 | } | ||
459 | |||
460 | __raw_writel((value << 16) | 0x3, clk->mapping->base); | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int fsidiv_set_rate(struct clk *clk, | ||
466 | unsigned long rate, int algo_id) | ||
467 | { | ||
468 | int idx; | ||
469 | |||
470 | if (clk->parent->rate == rate) { | ||
471 | fsidiv_disable(clk); | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | idx = (clk->parent->rate / rate) & 0xffff; | ||
476 | if (idx < 2) | ||
477 | return -ENOENT; | ||
478 | |||
479 | __raw_writel(idx << 16, clk->mapping->base); | ||
480 | return fsidiv_enable(clk); | ||
481 | } | ||
482 | |||
483 | static struct clk_ops fsidiv_clk_ops = { | ||
484 | .recalc = fsidiv_recalc, | ||
485 | .round_rate = fsidiv_round_rate, | ||
486 | .set_rate = fsidiv_set_rate, | ||
487 | .enable = fsidiv_enable, | ||
488 | .disable = fsidiv_disable, | ||
489 | }; | ||
490 | |||
491 | static struct clk_mapping sh7372_fsidiva_clk_mapping = { | ||
492 | .phys = FSIDIVA, | ||
493 | .len = 8, | ||
494 | }; | ||
495 | |||
496 | struct clk sh7372_fsidiva_clk = { | ||
497 | .ops = &fsidiv_clk_ops, | ||
498 | .parent = &div6_reparent_clks[DIV6_FSIA], /* late install */ | ||
499 | .mapping = &sh7372_fsidiva_clk_mapping, | ||
500 | }; | ||
501 | |||
502 | static struct clk_mapping sh7372_fsidivb_clk_mapping = { | ||
503 | .phys = FSIDIVB, | ||
504 | .len = 8, | ||
505 | }; | ||
506 | |||
507 | struct clk sh7372_fsidivb_clk = { | ||
508 | .ops = &fsidiv_clk_ops, | ||
509 | .parent = &div6_reparent_clks[DIV6_FSIB], /* late install */ | ||
510 | .mapping = &sh7372_fsidivb_clk_mapping, | ||
511 | }; | ||
512 | |||
513 | static struct clk *late_main_clks[] = { | ||
514 | &sh7372_fsidiva_clk, | ||
515 | &sh7372_fsidivb_clk, | ||
516 | }; | ||
517 | |||
420 | enum { MSTP001, | 518 | enum { MSTP001, |
421 | MSTP131, MSTP130, | 519 | MSTP131, MSTP130, |
422 | MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, | 520 | MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, |
@@ -585,6 +683,9 @@ void __init sh7372_clock_init(void) | |||
585 | if (!ret) | 683 | if (!ret) |
586 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); | 684 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); |
587 | 685 | ||
686 | for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) | ||
687 | ret = clk_register(late_main_clks[k]); | ||
688 | |||
588 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | 689 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); |
589 | 690 | ||
590 | if (!ret) | 691 | if (!ret) |
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 147775a94bce..e4f9004e7103 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h | |||
@@ -464,5 +464,7 @@ extern struct clk sh7372_dv_clki_div2_clk; | |||
464 | extern struct clk sh7372_pllc2_clk; | 464 | extern struct clk sh7372_pllc2_clk; |
465 | extern struct clk sh7372_fsiack_clk; | 465 | extern struct clk sh7372_fsiack_clk; |
466 | extern struct clk sh7372_fsibck_clk; | 466 | extern struct clk sh7372_fsibck_clk; |
467 | extern struct clk sh7372_fsidiva_clk; | ||
468 | extern struct clk sh7372_fsidivb_clk; | ||
467 | 469 | ||
468 | #endif /* __ASM_SH7372_H__ */ | 470 | #endif /* __ASM_SH7372_H__ */ |