aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2010-10-17 23:50:39 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-10-31 10:40:45 -0400
commitf2ace4a5d754c07503326d66ec85bf65e03d729d (patch)
treee309065e67fead6359102ae9609bcff86cd83851 /arch/arm/mach-shmobile
parent03ff858c09c81a659b2a90a08826bc0abdbb784c (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.c101
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h2
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 */
54struct clk sh7372_dv_clki_clk = { 57struct 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 */
424static 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
440static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
441{
442 return clk_rate_div_range_round(clk, 2, 0xffff, rate);
443}
444
445static void fsidiv_disable(struct clk *clk)
446{
447 __raw_writel(0, clk->mapping->base);
448}
449
450static 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
465static 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
483static 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
491static struct clk_mapping sh7372_fsidiva_clk_mapping = {
492 .phys = FSIDIVA,
493 .len = 8,
494};
495
496struct 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
502static struct clk_mapping sh7372_fsidivb_clk_mapping = {
503 .phys = FSIDIVB,
504 .len = 8,
505};
506
507struct 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
513static struct clk *late_main_clks[] = {
514 &sh7372_fsidiva_clk,
515 &sh7372_fsidivb_clk,
516};
517
420enum { MSTP001, 518enum { 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;
464extern struct clk sh7372_pllc2_clk; 464extern struct clk sh7372_pllc2_clk;
465extern struct clk sh7372_fsiack_clk; 465extern struct clk sh7372_fsiack_clk;
466extern struct clk sh7372_fsibck_clk; 466extern struct clk sh7372_fsibck_clk;
467extern struct clk sh7372_fsidiva_clk;
468extern struct clk sh7372_fsidivb_clk;
467 469
468#endif /* __ASM_SH7372_H__ */ 470#endif /* __ASM_SH7372_H__ */