diff options
Diffstat (limited to 'arch/sh/kernel/cpu/sh4a/clock-sh7722.c')
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 221 |
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 | */ |
414 | static int sh7722_siu_which(struct clk *clk) | 415 | |
416 | #ifndef CONFIG_CPU_SUBTYPE_SH7343 | ||
417 | |||
418 | static 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 | ||
427 | static unsigned long sh7722_siu_regs[] = { | 432 | static 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 | ||
435 | static int sh7722_siu_start_stop(struct clk *clk, int enable) | 440 | static 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 | ||
462 | static 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 | |||
461 | static void sh7722_video_enable(struct clk *clk) | 471 | static 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 | ||
497 | static 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 | |||
515 | static 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 | |||
527 | static 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 | |||
534 | static struct clk_ops sh7722_video_clk_ops = { | 507 | static 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 | */ |
568 | static struct clk sh7722_siu_a_clock = { | 544 | static 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 | ||
573 | static struct clk sh7722_siu_b_clock = { | 550 | static 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) |
579 | static struct clk sh7722_irda_clock = { | 557 | static 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 | ||
585 | static struct clk sh7722_video_clock = { | 565 | static 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 | ||
570 | static 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 | |||
587 | static void sh7722_mstpcr0_enable(struct clk *clk) | ||
588 | { | ||
589 | sh7722_mstpcr_start_stop(clk, MSTPCR0, 1); | ||
590 | } | ||
591 | |||
592 | static void sh7722_mstpcr0_disable(struct clk *clk) | ||
593 | { | ||
594 | sh7722_mstpcr_start_stop(clk, MSTPCR0, 0); | ||
595 | } | ||
596 | |||
597 | static void sh7722_mstpcr1_enable(struct clk *clk) | ||
598 | { | ||
599 | sh7722_mstpcr_start_stop(clk, MSTPCR1, 1); | ||
600 | } | ||
601 | |||
602 | static void sh7722_mstpcr1_disable(struct clk *clk) | ||
603 | { | ||
604 | sh7722_mstpcr_start_stop(clk, MSTPCR1, 0); | ||
605 | } | ||
606 | |||
607 | static void sh7722_mstpcr2_enable(struct clk *clk) | ||
608 | { | ||
609 | sh7722_mstpcr_start_stop(clk, MSTPCR2, 1); | ||
610 | } | ||
611 | |||
612 | static void sh7722_mstpcr2_disable(struct clk *clk) | ||
613 | { | ||
614 | sh7722_mstpcr_start_stop(clk, MSTPCR2, 0); | ||
615 | } | ||
616 | |||
617 | static struct clk_ops sh7722_mstpcr0_clk_ops = { | ||
618 | .enable = sh7722_mstpcr0_enable, | ||
619 | .disable = sh7722_mstpcr0_disable, | ||
620 | }; | ||
621 | |||
622 | static struct clk_ops sh7722_mstpcr1_clk_ops = { | ||
623 | .enable = sh7722_mstpcr1_enable, | ||
624 | .disable = sh7722_mstpcr1_disable, | ||
625 | }; | ||
626 | |||
627 | static 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 | |||
673 | static struct clk sh7722_mstpcr[] = { | ||
674 | DECLARE_MSTPCR(0), | ||
675 | DECLARE_MSTPCR(1), | ||
676 | DECLARE_MSTPCR(2), | ||
677 | }; | ||
678 | |||
590 | static struct clk *sh7722_clocks[] = { | 679 | static 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 | } |