0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "ops.h"
0011 #include "io.h"
0012 #include "dcr.h"
0013 #include "stdio.h"
0014 #include "4xx.h"
0015 #include "44x.h"
0016 #include "cuboot.h"
0017
0018 #define TARGET_4xx
0019 #include "ppcboot.h"
0020
0021 static bd_t bd;
0022
0023 #define CPR_PERD0_SPIDV_MASK 0x000F0000
0024
0025 #define PLLC_SRC_MASK 0x20000000
0026
0027 #define PLLD_FBDV_MASK 0x1F000000
0028 #define PLLD_FWDVA_MASK 0x000F0000
0029 #define PLLD_FWDVB_MASK 0x00000700
0030
0031 #define PRIMAD_CPUDV_MASK 0x0F000000
0032 #define PRIMAD_PLBDV_MASK 0x000F0000
0033 #define PRIMAD_OPBDV_MASK 0x00000F00
0034 #define PRIMAD_EBCDV_MASK 0x0000000F
0035
0036 #define PERD0_PWMDV_MASK 0xFF000000
0037 #define PERD0_SPIDV_MASK 0x000F0000
0038 #define PERD0_U0DV_MASK 0x0000FF00
0039 #define PERD0_U1DV_MASK 0x000000FF
0040
0041 static void get_clocks(void)
0042 {
0043 unsigned long sysclk, cpr_plld, cpr_pllc, cpr_primad, plloutb, i;
0044 unsigned long pllFwdDiv, pllFwdDivB, pllFbkDiv, pllPlbDiv, pllExtBusDiv;
0045 unsigned long pllOpbDiv, freqEBC, freqUART, freqOPB;
0046 unsigned long div;
0047 unsigned long umin;
0048 unsigned short diff;
0049 unsigned long udiv;
0050 unsigned short idiff;
0051 unsigned short ibdiv;
0052 unsigned long est;
0053 unsigned long baud;
0054 void *np;
0055
0056
0057 sysclk = (in_8((unsigned char *)0x80000000) == 0xc) ? 66666666 : 33333000;
0058
0059
0060
0061
0062 cpr_plld = CPR0_READ(DCRN_CPR0_PLLD);
0063 cpr_pllc = CPR0_READ(DCRN_CPR0_PLLC);
0064
0065
0066
0067
0068 pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
0069
0070
0071
0072
0073 pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
0074 if (pllFwdDivB == 0)
0075 pllFwdDivB = 8;
0076
0077
0078
0079
0080 pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
0081 if (pllFbkDiv == 0)
0082 pllFbkDiv = 256;
0083
0084
0085
0086
0087 cpr_primad = CPR0_READ(DCRN_CPR0_PRIMAD);
0088
0089
0090
0091
0092 pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
0093 if (pllPlbDiv == 0)
0094 pllPlbDiv = 16;
0095
0096
0097
0098
0099 pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
0100 if (pllExtBusDiv == 0)
0101 pllExtBusDiv = 16;
0102
0103
0104
0105
0106 pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
0107 if (pllOpbDiv == 0)
0108 pllOpbDiv = 16;
0109
0110
0111
0112
0113
0114 freqOPB = (sysclk *pllFbkDiv) /pllOpbDiv;
0115
0116 freqEBC = (sysclk * pllFbkDiv) / pllExtBusDiv;
0117
0118 plloutb = ((sysclk * ((cpr_pllc & PLLC_SRC_MASK) ?
0119 pllFwdDivB : pllFwdDiv) *
0120 pllFbkDiv) / pllFwdDivB);
0121
0122 np = find_node_by_alias("serial0");
0123 if (getprop(np, "current-speed", &baud, sizeof(baud)) != sizeof(baud))
0124 fatal("no current-speed property\n\r");
0125
0126 udiv = 256;
0127 div = plloutb / (16 * baud);
0128 umin = (plloutb / freqOPB) << 1;
0129 diff = 256;
0130
0131
0132
0133
0134
0135 for (i = 256; i > umin; i--) {
0136 ibdiv = div / i;
0137 est = i * ibdiv;
0138 idiff = (est > div) ? (est-div) : (div-est);
0139 if (idiff == 0) {
0140 udiv = i;
0141 break;
0142 } else if (idiff < diff) {
0143 udiv = i;
0144 diff = idiff;
0145 }
0146 }
0147 freqUART = plloutb / udiv;
0148
0149 dt_fixup_cpu_clocks(bd.bi_procfreq, bd.bi_intfreq, bd.bi_plb_busfreq);
0150 dt_fixup_clock("/plb/ebc", freqEBC);
0151 dt_fixup_clock("/plb/opb", freqOPB);
0152 dt_fixup_clock("/plb/opb/serial@ef600300", freqUART);
0153 dt_fixup_clock("/plb/opb/serial@ef600400", freqUART);
0154 }
0155
0156 static void acadia_fixups(void)
0157 {
0158 dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
0159 get_clocks();
0160 dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
0161 }
0162
0163 void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
0164 unsigned long r6, unsigned long r7)
0165 {
0166 CUBOOT_INIT();
0167 platform_ops.fixups = acadia_fixups;
0168 platform_ops.exit = ibm40x_dbcr_reset;
0169 fdt_init(_dtb_start);
0170 serial_console_init();
0171 }