aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot/4xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/boot/4xx.c')
-rw-r--r--arch/powerpc/boot/4xx.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/arch/powerpc/boot/4xx.c b/arch/powerpc/boot/4xx.c
index 325b310573b9..27db8938827a 100644
--- a/arch/powerpc/boot/4xx.c
+++ b/arch/powerpc/boot/4xx.c
@@ -8,6 +8,10 @@
8 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> 8 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
9 * Copyright (c) 2003, 2004 Zultys Technologies 9 * Copyright (c) 2003, 2004 Zultys Technologies
10 * 10 *
11 * Copyright (C) 2009 Wind River Systems, Inc.
12 * Updated for supporting PPC405EX on Kilauea.
13 * Tiejun Chen <tiejun.chen@windriver.com>
14 *
11 * This program is free software; you can redistribute it and/or 15 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License 16 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 17 * as published by the Free Software Foundation; either version
@@ -659,3 +663,141 @@ void ibm405ep_fixup_clocks(unsigned int sys_clk)
659 dt_fixup_clock("/plb/opb/serial@ef600300", uart0); 663 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
660 dt_fixup_clock("/plb/opb/serial@ef600400", uart1); 664 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
661} 665}
666
667static u8 ibm405ex_fwdv_multi_bits[] = {
668 /* values for: 1 - 16 */
669 0x01, 0x02, 0x0e, 0x09, 0x04, 0x0b, 0x10, 0x0d, 0x0c, 0x05,
670 0x06, 0x0f, 0x0a, 0x07, 0x08, 0x03
671};
672
673u32 ibm405ex_get_fwdva(unsigned long cpr_fwdv)
674{
675 u32 index;
676
677 for (index = 0; index < ARRAY_SIZE(ibm405ex_fwdv_multi_bits); index++)
678 if (cpr_fwdv == (u32)ibm405ex_fwdv_multi_bits[index])
679 return index + 1;
680
681 return 0;
682}
683
684static u8 ibm405ex_fbdv_multi_bits[] = {
685 /* values for: 1 - 100 */
686 0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
687 0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
688 0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
689 0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
690 0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
691 0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
692 0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
693 0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
694 0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
695 0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
696 /* values for: 101 - 200 */
697 0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
698 0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
699 0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
700 0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
701 0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
702 0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
703 0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
704 0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
705 0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
706 0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
707 /* values for: 201 - 255 */
708 0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
709 0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
710 0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
711 0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
712 0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
713 0x03, 0x87, 0x0f, 0x9f, 0x3f /* END */
714};
715
716u32 ibm405ex_get_fbdv(unsigned long cpr_fbdv)
717{
718 u32 index;
719
720 for (index = 0; index < ARRAY_SIZE(ibm405ex_fbdv_multi_bits); index++)
721 if (cpr_fbdv == (u32)ibm405ex_fbdv_multi_bits[index])
722 return index + 1;
723
724 return 0;
725}
726
727void ibm405ex_fixup_clocks(unsigned int sys_clk, unsigned int uart_clk)
728{
729 /* PLL config */
730 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
731 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
732 u32 cpud = CPR0_READ(DCRN_CPR0_PRIMAD);
733 u32 plbd = CPR0_READ(DCRN_CPR0_PRIMBD);
734 u32 opbd = CPR0_READ(DCRN_CPR0_OPBD);
735 u32 perd = CPR0_READ(DCRN_CPR0_PERD);
736
737 /* Dividers */
738 u32 fbdv = ibm405ex_get_fbdv(__fix_zero((plld >> 24) & 0xff, 1));
739
740 u32 fwdva = ibm405ex_get_fwdva(__fix_zero((plld >> 16) & 0x0f, 1));
741
742 u32 cpudv0 = __fix_zero((cpud >> 24) & 7, 8);
743
744 /* PLBDV0 is hardwared to 010. */
745 u32 plbdv0 = 2;
746 u32 plb2xdv0 = __fix_zero((plbd >> 16) & 7, 8);
747
748 u32 opbdv0 = __fix_zero((opbd >> 24) & 3, 4);
749
750 u32 perdv0 = __fix_zero((perd >> 24) & 3, 4);
751
752 /* Resulting clocks */
753 u32 cpu, plb, opb, ebc, vco, tb, uart0, uart1;
754
755 /* PLL's VCO is the source for primary forward ? */
756 if (pllc & 0x40000000) {
757 u32 m;
758
759 /* Feedback path */
760 switch ((pllc >> 24) & 7) {
761 case 0:
762 /* PLLOUTx */
763 m = fbdv;
764 break;
765 case 1:
766 /* CPU */
767 m = fbdv * fwdva * cpudv0;
768 break;
769 case 5:
770 /* PERClk */
771 m = fbdv * fwdva * plb2xdv0 * plbdv0 * opbdv0 * perdv0;
772 break;
773 default:
774 printf("WARNING ! Invalid PLL feedback source !\n");
775 goto bypass;
776 }
777
778 vco = (unsigned int)(sys_clk * m);
779 } else {
780bypass:
781 /* Bypass system PLL */
782 vco = 0;
783 }
784
785 /* CPU = VCO / ( FWDVA x CPUDV0) */
786 cpu = vco / (fwdva * cpudv0);
787 /* PLB = VCO / ( FWDVA x PLB2XDV0 x PLBDV0) */
788 plb = vco / (fwdva * plb2xdv0 * plbdv0);
789 /* OPB = PLB / OPBDV0 */
790 opb = plb / opbdv0;
791 /* EBC = OPB / PERDV0 */
792 ebc = opb / perdv0;
793
794 tb = cpu;
795 uart0 = uart1 = uart_clk;
796
797 dt_fixup_cpu_clocks(cpu, tb, 0);
798 dt_fixup_clock("/plb", plb);
799 dt_fixup_clock("/plb/opb", opb);
800 dt_fixup_clock("/plb/opb/ebc", ebc);
801 dt_fixup_clock("/plb/opb/serial@ef600200", uart0);
802 dt_fixup_clock("/plb/opb/serial@ef600300", uart1);
803}