aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/sh4a/clock-sh7722.c')
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c221
1 files changed, 159 insertions, 62 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 299138ebe160..db913855c2fd 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/sh/kernel/cpu/sh4a/clock-sh7722.c 2 * arch/sh/kernel/cpu/sh4a/clock-sh7722.c
3 * 3 *
4 * SH7722 & SH7366 support for the clock framework 4 * SH7343, SH7722, SH7723 & SH7366 support for the clock framework
5 * 5 *
6 * Copyright (c) 2006-2007 Nomad Global Solutions Inc 6 * Copyright (c) 2006-2007 Nomad Global Solutions Inc
7 * Based on code for sh7343 by Paul Mundt 7 * Based on code for sh7343 by Paul Mundt
@@ -14,6 +14,7 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <linux/stringify.h>
17#include <asm/clock.h> 18#include <asm/clock.h>
18#include <asm/freq.h> 19#include <asm/freq.h>
19 20
@@ -411,40 +412,40 @@ static struct clk_ops sh7722_frqcr_clk_ops = {
411 * clock ops methods for SIU A/B and IrDA clock 412 * clock ops methods for SIU A/B and IrDA clock
412 * 413 *
413 */ 414 */
414static int sh7722_siu_which(struct clk *clk) 415
416#ifndef CONFIG_CPU_SUBTYPE_SH7343
417
418static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id)
415{ 419{
416 if (!strcmp(clk->name, "siu_a_clk")) 420 unsigned long r;
417 return 0; 421 int div;
418 if (!strcmp(clk->name, "siu_b_clk")) 422
419 return 1; 423 r = ctrl_inl(clk->arch_flags);
420#if defined(CONFIG_CPU_SUBTYPE_SH7722) 424 div = sh7722_find_divisors(clk->parent->rate, rate);
421 if (!strcmp(clk->name, "irda_clk")) 425 if (div < 0)
422 return 2; 426 return div;
423#endif 427 r = (r & ~0xF) | div;
424 return -EINVAL; 428 ctrl_outl(r, clk->arch_flags);
429 return 0;
425} 430}
426 431
427static unsigned long sh7722_siu_regs[] = { 432static void sh7722_siu_recalc(struct clk *clk)
428 [0] = SCLKACR, 433{
429 [1] = SCLKBCR, 434 unsigned long r;
430#if defined(CONFIG_CPU_SUBTYPE_SH7722) 435
431 [2] = IrDACLKCR, 436 r = ctrl_inl(clk->arch_flags);
432#endif 437 clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
433}; 438}
434 439
435static int sh7722_siu_start_stop(struct clk *clk, int enable) 440static int sh7722_siu_start_stop(struct clk *clk, int enable)
436{ 441{
437 int siu = sh7722_siu_which(clk);
438 unsigned long r; 442 unsigned long r;
439 443
440 if (siu < 0) 444 r = ctrl_inl(clk->arch_flags);
441 return siu;
442 BUG_ON(siu > 2);
443 r = ctrl_inl(sh7722_siu_regs[siu]);
444 if (enable) 445 if (enable)
445 ctrl_outl(r & ~(1 << 8), sh7722_siu_regs[siu]); 446 ctrl_outl(r & ~(1 << 8), clk->arch_flags);
446 else 447 else
447 ctrl_outl(r | (1 << 8), sh7722_siu_regs[siu]); 448 ctrl_outl(r | (1 << 8), clk->arch_flags);
448 return 0; 449 return 0;
449} 450}
450 451
@@ -458,6 +459,15 @@ static void sh7722_siu_disable(struct clk *clk)
458 sh7722_siu_start_stop(clk, 0); 459 sh7722_siu_start_stop(clk, 0);
459} 460}
460 461
462static struct clk_ops sh7722_siu_clk_ops = {
463 .recalc = sh7722_siu_recalc,
464 .set_rate = sh7722_siu_set_rate,
465 .enable = sh7722_siu_enable,
466 .disable = sh7722_siu_disable,
467};
468
469#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
470
461static void sh7722_video_enable(struct clk *clk) 471static void sh7722_video_enable(struct clk *clk)
462{ 472{
463 unsigned long r; 473 unsigned long r;
@@ -494,43 +504,6 @@ static void sh7722_video_recalc(struct clk *clk)
494 clk->rate = clk->parent->rate / ((r & 0x3F) + 1); 504 clk->rate = clk->parent->rate / ((r & 0x3F) + 1);
495} 505}
496 506
497static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id)
498{
499 int siu = sh7722_siu_which(clk);
500 unsigned long r;
501 int div;
502
503 if (siu < 0)
504 return siu;
505 BUG_ON(siu > 2);
506 r = ctrl_inl(sh7722_siu_regs[siu]);
507 div = sh7722_find_divisors(clk->parent->rate, rate);
508 if (div < 0)
509 return div;
510 r = (r & ~0xF) | div;
511 ctrl_outl(r, sh7722_siu_regs[siu]);
512 return 0;
513}
514
515static void sh7722_siu_recalc(struct clk *clk)
516{
517 int siu = sh7722_siu_which(clk);
518 unsigned long r;
519
520 if (siu < 0)
521 return /* siu */ ;
522 BUG_ON(siu > 2);
523 r = ctrl_inl(sh7722_siu_regs[siu]);
524 clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
525}
526
527static struct clk_ops sh7722_siu_clk_ops = {
528 .recalc = sh7722_siu_recalc,
529 .set_rate = sh7722_siu_set_rate,
530 .enable = sh7722_siu_enable,
531 .disable = sh7722_siu_disable,
532};
533
534static struct clk_ops sh7722_video_clk_ops = { 507static struct clk_ops sh7722_video_clk_ops = {
535 .recalc = sh7722_video_recalc, 508 .recalc = sh7722_video_recalc,
536 .set_rate = sh7722_video_set_rate, 509 .set_rate = sh7722_video_set_rate,
@@ -560,6 +533,9 @@ static struct clk sh7722_sdram_clock = {
560 .ops = &sh7722_frqcr_clk_ops, 533 .ops = &sh7722_frqcr_clk_ops,
561}; 534};
562 535
536
537#ifndef CONFIG_CPU_SUBTYPE_SH7343
538
563/* 539/*
564 * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops 540 * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops
565 * methods of clk_ops determine which register they should access by 541 * methods of clk_ops determine which register they should access by
@@ -567,36 +543,151 @@ static struct clk sh7722_sdram_clock = {
567 */ 543 */
568static struct clk sh7722_siu_a_clock = { 544static struct clk sh7722_siu_a_clock = {
569 .name = "siu_a_clk", 545 .name = "siu_a_clk",
546 .arch_flags = SCLKACR,
570 .ops = &sh7722_siu_clk_ops, 547 .ops = &sh7722_siu_clk_ops,
571}; 548};
572 549
573static struct clk sh7722_siu_b_clock = { 550static struct clk sh7722_siu_b_clock = {
574 .name = "siu_b_clk", 551 .name = "siu_b_clk",
552 .arch_flags = SCLKBCR,
575 .ops = &sh7722_siu_clk_ops, 553 .ops = &sh7722_siu_clk_ops,
576}; 554};
577 555
578#if defined(CONFIG_CPU_SUBTYPE_SH7722) 556#if defined(CONFIG_CPU_SUBTYPE_SH7722)
579static struct clk sh7722_irda_clock = { 557static struct clk sh7722_irda_clock = {
580 .name = "irda_clk", 558 .name = "irda_clk",
559 .arch_flags = IrDACLKCR,
581 .ops = &sh7722_siu_clk_ops, 560 .ops = &sh7722_siu_clk_ops,
582}; 561};
583#endif 562#endif
563#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
584 564
585static struct clk sh7722_video_clock = { 565static struct clk sh7722_video_clock = {
586 .name = "video_clk", 566 .name = "video_clk",
587 .ops = &sh7722_video_clk_ops, 567 .ops = &sh7722_video_clk_ops,
588}; 568};
589 569
570static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg,
571 int enable)
572{
573 unsigned long bit = clk->arch_flags;
574 unsigned long r;
575
576 r = ctrl_inl(reg);
577
578 if (enable)
579 r &= ~(1 << bit);
580 else
581 r |= (1 << bit);
582
583 ctrl_outl(r, reg);
584 return 0;
585}
586
587static void sh7722_mstpcr0_enable(struct clk *clk)
588{
589 sh7722_mstpcr_start_stop(clk, MSTPCR0, 1);
590}
591
592static void sh7722_mstpcr0_disable(struct clk *clk)
593{
594 sh7722_mstpcr_start_stop(clk, MSTPCR0, 0);
595}
596
597static void sh7722_mstpcr1_enable(struct clk *clk)
598{
599 sh7722_mstpcr_start_stop(clk, MSTPCR1, 1);
600}
601
602static void sh7722_mstpcr1_disable(struct clk *clk)
603{
604 sh7722_mstpcr_start_stop(clk, MSTPCR1, 0);
605}
606
607static void sh7722_mstpcr2_enable(struct clk *clk)
608{
609 sh7722_mstpcr_start_stop(clk, MSTPCR2, 1);
610}
611
612static void sh7722_mstpcr2_disable(struct clk *clk)
613{
614 sh7722_mstpcr_start_stop(clk, MSTPCR2, 0);
615}
616
617static struct clk_ops sh7722_mstpcr0_clk_ops = {
618 .enable = sh7722_mstpcr0_enable,
619 .disable = sh7722_mstpcr0_disable,
620};
621
622static struct clk_ops sh7722_mstpcr1_clk_ops = {
623 .enable = sh7722_mstpcr1_enable,
624 .disable = sh7722_mstpcr1_disable,
625};
626
627static struct clk_ops sh7722_mstpcr2_clk_ops = {
628 .enable = sh7722_mstpcr2_enable,
629 .disable = sh7722_mstpcr2_disable,
630};
631
632#define DECLARE_MSTPCRN(regnr, bitnr, bitstr) \
633{ \
634 .name = "mstp" __stringify(regnr) bitstr, \
635 .arch_flags = bitnr, \
636 .ops = &sh7722_mstpcr ## regnr ## _clk_ops, \
637}
638
639#define DECLARE_MSTPCR(regnr) \
640 DECLARE_MSTPCRN(regnr, 31, "31"), \
641 DECLARE_MSTPCRN(regnr, 30, "30"), \
642 DECLARE_MSTPCRN(regnr, 29, "29"), \
643 DECLARE_MSTPCRN(regnr, 28, "28"), \
644 DECLARE_MSTPCRN(regnr, 27, "27"), \
645 DECLARE_MSTPCRN(regnr, 26, "26"), \
646 DECLARE_MSTPCRN(regnr, 25, "25"), \
647 DECLARE_MSTPCRN(regnr, 24, "24"), \
648 DECLARE_MSTPCRN(regnr, 23, "23"), \
649 DECLARE_MSTPCRN(regnr, 22, "22"), \
650 DECLARE_MSTPCRN(regnr, 21, "21"), \
651 DECLARE_MSTPCRN(regnr, 20, "20"), \
652 DECLARE_MSTPCRN(regnr, 19, "19"), \
653 DECLARE_MSTPCRN(regnr, 18, "18"), \
654 DECLARE_MSTPCRN(regnr, 17, "17"), \
655 DECLARE_MSTPCRN(regnr, 16, "16"), \
656 DECLARE_MSTPCRN(regnr, 15, "15"), \
657 DECLARE_MSTPCRN(regnr, 14, "14"), \
658 DECLARE_MSTPCRN(regnr, 13, "13"), \
659 DECLARE_MSTPCRN(regnr, 12, "12"), \
660 DECLARE_MSTPCRN(regnr, 11, "11"), \
661 DECLARE_MSTPCRN(regnr, 10, "10"), \
662 DECLARE_MSTPCRN(regnr, 9, "09"), \
663 DECLARE_MSTPCRN(regnr, 8, "08"), \
664 DECLARE_MSTPCRN(regnr, 7, "07"), \
665 DECLARE_MSTPCRN(regnr, 6, "06"), \
666 DECLARE_MSTPCRN(regnr, 5, "05"), \
667 DECLARE_MSTPCRN(regnr, 4, "04"), \
668 DECLARE_MSTPCRN(regnr, 3, "03"), \
669 DECLARE_MSTPCRN(regnr, 2, "02"), \
670 DECLARE_MSTPCRN(regnr, 1, "01"), \
671 DECLARE_MSTPCRN(regnr, 0, "00")
672
673static struct clk sh7722_mstpcr[] = {
674 DECLARE_MSTPCR(0),
675 DECLARE_MSTPCR(1),
676 DECLARE_MSTPCR(2),
677};
678
590static struct clk *sh7722_clocks[] = { 679static struct clk *sh7722_clocks[] = {
591 &sh7722_umem_clock, 680 &sh7722_umem_clock,
592 &sh7722_sh_clock, 681 &sh7722_sh_clock,
593 &sh7722_peripheral_clock, 682 &sh7722_peripheral_clock,
594 &sh7722_sdram_clock, 683 &sh7722_sdram_clock,
684#ifndef CONFIG_CPU_SUBTYPE_SH7343
595 &sh7722_siu_a_clock, 685 &sh7722_siu_a_clock,
596 &sh7722_siu_b_clock, 686 &sh7722_siu_b_clock,
597#if defined(CONFIG_CPU_SUBTYPE_SH7722) 687#if defined(CONFIG_CPU_SUBTYPE_SH7722)
598 &sh7722_irda_clock, 688 &sh7722_irda_clock,
599#endif 689#endif
690#endif
600 &sh7722_video_clock, 691 &sh7722_video_clock,
601}; 692};
602 693
@@ -629,5 +720,11 @@ int __init arch_clk_init(void)
629 clk_register(sh7722_clocks[i]); 720 clk_register(sh7722_clocks[i]);
630 } 721 }
631 clk_put(master); 722 clk_put(master);
723
724 for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr); i++) {
725 pr_debug( "Registering mstpcr '%s'\n", sh7722_mstpcr[i].name);
726 clk_register(&sh7722_mstpcr[i]);
727 }
728
632 return 0; 729 return 0;
633} 730}