0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <stddef.h>
0017 #include "types.h"
0018 #include "string.h"
0019 #include "stdio.h"
0020 #include "ops.h"
0021 #include "reg.h"
0022 #include "dcr.h"
0023
0024 static unsigned long chip_11_errata(unsigned long memsize)
0025 {
0026 unsigned long pvr;
0027
0028 pvr = mfpvr();
0029
0030 switch (pvr & 0xf0000ff0) {
0031 case 0x40000850:
0032 case 0x400008d0:
0033 case 0x200008d0:
0034 memsize -= 4096;
0035 break;
0036 default:
0037 break;
0038 }
0039
0040 return memsize;
0041 }
0042
0043
0044 void ibm4xx_sdram_fixup_memsize(void)
0045 {
0046 int i;
0047 unsigned long memsize, bank_config;
0048
0049 memsize = 0;
0050 for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
0051 bank_config = SDRAM0_READ(sdram_bxcr[i]);
0052 if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
0053 memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
0054 }
0055
0056 memsize = chip_11_errata(memsize);
0057 dt_fixup_memory(0, memsize);
0058 }
0059
0060
0061 #define DCRN_MQ0_B0BAS 0x40
0062 #define DCRN_MQ0_B1BAS 0x41
0063 #define DCRN_MQ0_B2BAS 0x42
0064 #define DCRN_MQ0_B3BAS 0x43
0065
0066 static u64 ibm440spe_decode_bas(u32 bas)
0067 {
0068 u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
0069
0070
0071 switch ((bas >> 4) & 0xFFF) {
0072 case 0:
0073 return 0;
0074 case 0xffc:
0075 return base + 0x000800000ull;
0076 case 0xff8:
0077 return base + 0x001000000ull;
0078 case 0xff0:
0079 return base + 0x002000000ull;
0080 case 0xfe0:
0081 return base + 0x004000000ull;
0082 case 0xfc0:
0083 return base + 0x008000000ull;
0084 case 0xf80:
0085 return base + 0x010000000ull;
0086 case 0xf00:
0087 return base + 0x020000000ull;
0088 case 0xe00:
0089 return base + 0x040000000ull;
0090 case 0xc00:
0091 return base + 0x080000000ull;
0092 case 0x800:
0093 return base + 0x100000000ull;
0094 }
0095 printf("Memory BAS value 0x%08x unsupported !\n", bas);
0096 return 0;
0097 }
0098
0099 void ibm440spe_fixup_memsize(void)
0100 {
0101 u64 banktop, memsize = 0;
0102
0103
0104
0105
0106 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
0107 if (banktop > memsize)
0108 memsize = banktop;
0109 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
0110 if (banktop > memsize)
0111 memsize = banktop;
0112 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
0113 if (banktop > memsize)
0114 memsize = banktop;
0115 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
0116 if (banktop > memsize)
0117 memsize = banktop;
0118
0119 dt_fixup_memory(0, memsize);
0120 }
0121
0122
0123
0124
0125 #define DDR0_02 2
0126 #define DDR0_08 8
0127 #define DDR0_10 10
0128 #define DDR0_14 14
0129 #define DDR0_42 42
0130 #define DDR0_43 43
0131
0132
0133 #define DDR_START 0x1
0134 #define DDR_START_SHIFT 0
0135 #define DDR_MAX_CS_REG 0x3
0136 #define DDR_MAX_CS_REG_SHIFT 24
0137 #define DDR_MAX_COL_REG 0xf
0138 #define DDR_MAX_COL_REG_SHIFT 16
0139 #define DDR_MAX_ROW_REG 0xf
0140 #define DDR_MAX_ROW_REG_SHIFT 8
0141
0142 #define DDR_DDR2_MODE 0x1
0143 #define DDR_DDR2_MODE_SHIFT 0
0144
0145 #define DDR_CS_MAP 0x3
0146 #define DDR_CS_MAP_SHIFT 8
0147
0148 #define DDR_REDUC 0x1
0149 #define DDR_REDUC_SHIFT 16
0150
0151 #define DDR_APIN 0x7
0152 #define DDR_APIN_SHIFT 24
0153
0154 #define DDR_COL_SZ 0x7
0155 #define DDR_COL_SZ_SHIFT 8
0156 #define DDR_BANK8 0x1
0157 #define DDR_BANK8_SHIFT 0
0158
0159 #define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
0160
0161
0162
0163
0164
0165
0166
0167
0168 static inline u32 ibm4xx_denali_get_cs(void)
0169 {
0170 void *devp;
0171 char model[64];
0172 u32 val, cs;
0173
0174 devp = finddevice("/");
0175 if (!devp)
0176 goto read_cs;
0177
0178 if (getprop(devp, "model", model, sizeof(model)) <= 0)
0179 goto read_cs;
0180
0181 model[sizeof(model)-1] = 0;
0182
0183 if (!strcmp(model, "amcc,sequoia") ||
0184 !strcmp(model, "amcc,rainier"))
0185 return 1;
0186
0187 read_cs:
0188
0189 val = SDRAM0_READ(DDR0_10);
0190
0191 val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
0192 cs = 0;
0193 while (val) {
0194 if (val & 0x1)
0195 cs++;
0196 val = val >> 1;
0197 }
0198 return cs;
0199 }
0200
0201 void ibm4xx_denali_fixup_memsize(void)
0202 {
0203 u32 val, max_cs, max_col, max_row;
0204 u32 cs, col, row, bank, dpath;
0205 unsigned long memsize;
0206
0207 val = SDRAM0_READ(DDR0_02);
0208 if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
0209 fatal("DDR controller is not initialized\n");
0210
0211
0212 max_cs = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
0213 max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
0214 max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
0215
0216 cs = ibm4xx_denali_get_cs();
0217 if (!cs)
0218 fatal("No memory installed\n");
0219 if (cs > max_cs)
0220 fatal("DDR wrong CS configuration\n");
0221
0222
0223 val = SDRAM0_READ(DDR0_14);
0224
0225 if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
0226 dpath = 4;
0227 else
0228 dpath = 8;
0229
0230
0231 val = SDRAM0_READ(DDR0_42);
0232
0233 row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
0234 if (row > max_row)
0235 fatal("DDR wrong APIN configuration\n");
0236 row = max_row - row;
0237
0238
0239 val = SDRAM0_READ(DDR0_43);
0240
0241 col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
0242 if (col > max_col)
0243 fatal("DDR wrong COL configuration\n");
0244 col = max_col - col;
0245
0246 if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
0247 bank = 8;
0248 else
0249 bank = 4;
0250
0251 memsize = cs * (1 << (col+row)) * bank * dpath;
0252 memsize = chip_11_errata(memsize);
0253 dt_fixup_memory(0, memsize);
0254 }
0255
0256 #define SPRN_DBCR0_40X 0x3F2
0257 #define SPRN_DBCR0_44X 0x134
0258 #define DBCR0_RST_SYSTEM 0x30000000
0259
0260 void ibm44x_dbcr_reset(void)
0261 {
0262 unsigned long tmp;
0263
0264 asm volatile (
0265 "mfspr %0,%1\n"
0266 "oris %0,%0,%2@h\n"
0267 "mtspr %1,%0"
0268 : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
0269 );
0270
0271 }
0272
0273 void ibm40x_dbcr_reset(void)
0274 {
0275 unsigned long tmp;
0276
0277 asm volatile (
0278 "mfspr %0,%1\n"
0279 "oris %0,%0,%2@h\n"
0280 "mtspr %1,%0"
0281 : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
0282 );
0283 }
0284
0285 #define EMAC_RESET 0x20000000
0286 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
0287 {
0288
0289
0290
0291 if (emac0)
0292 *emac0 = EMAC_RESET;
0293 if (emac1)
0294 *emac1 = EMAC_RESET;
0295
0296 mtdcr(DCRN_MAL0_CFG, MAL_RESET);
0297 while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
0298 ;
0299 }
0300
0301
0302
0303 void ibm4xx_fixup_ebc_ranges(const char *ebc)
0304 {
0305 void *devp;
0306 u32 bxcr;
0307 u32 ranges[EBC_NUM_BANKS*4];
0308 u32 *p = ranges;
0309 int i;
0310
0311 for (i = 0; i < EBC_NUM_BANKS; i++) {
0312 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
0313 bxcr = mfdcr(DCRN_EBC0_CFGDATA);
0314
0315 if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
0316 *p++ = i;
0317 *p++ = 0;
0318 *p++ = bxcr & EBC_BXCR_BAS;
0319 *p++ = EBC_BXCR_BANK_SIZE(bxcr);
0320 }
0321 }
0322
0323 devp = finddevice(ebc);
0324 if (! devp)
0325 fatal("Couldn't locate EBC node %s\n\r", ebc);
0326
0327 setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
0328 }
0329
0330
0331 void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
0332 {
0333 u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
0334 u32 cr0 = mfdcr(DCRN_CPC0_CR0);
0335 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
0336 u32 opdv = CPC0_SYS0_OPDV(sys0);
0337 u32 epdv = CPC0_SYS0_EPDV(sys0);
0338
0339 if (sys0 & CPC0_SYS0_BYPASS) {
0340
0341 cpu = plb = sys_clk;
0342 } else {
0343 if (sys0 & CPC0_SYS0_EXTSL)
0344
0345 m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
0346 else
0347
0348 m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
0349 cpu = sys_clk * m / CPC0_SYS0_FWDVA(sys0);
0350 plb = sys_clk * m / CPC0_SYS0_FWDVB(sys0);
0351 }
0352
0353 opb = plb / opdv;
0354 ebc = opb / epdv;
0355
0356
0357 if ((mfpvr() & 0xf0000fff) == 0x40000440)
0358
0359 tb = sys_clk;
0360 else
0361
0362 tb = cpu;
0363
0364 if (cr0 & CPC0_CR0_U0EC)
0365
0366 uart0 = ser_clk;
0367 else
0368
0369 uart0 = plb / CPC0_CR0_UDIV(cr0);
0370
0371 if (cr0 & CPC0_CR0_U1EC)
0372
0373 uart1 = ser_clk;
0374 else
0375
0376 uart1 = plb / CPC0_CR0_UDIV(cr0);
0377
0378 printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
0379 (sys_clk + 500000) / 1000000, sys_clk);
0380
0381 dt_fixup_cpu_clocks(cpu, tb, 0);
0382
0383 dt_fixup_clock("/plb", plb);
0384 dt_fixup_clock("/plb/opb", opb);
0385 dt_fixup_clock("/plb/opb/ebc", ebc);
0386 dt_fixup_clock("/plb/opb/serial@40000200", uart0);
0387 dt_fixup_clock("/plb/opb/serial@40000300", uart1);
0388 }
0389
0390 #define SPRN_CCR1 0x378
0391
0392 static inline u32 __fix_zero(u32 v, u32 def)
0393 {
0394 return v ? v : def;
0395 }
0396
0397 static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
0398 unsigned int tmr_clk,
0399 int per_clk_from_opb)
0400 {
0401
0402 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
0403 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
0404
0405
0406 u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32);
0407 u32 fwdva = __fix_zero((plld >> 16) & 0xf, 16);
0408 u32 fwdvb = __fix_zero((plld >> 8) & 7, 8);
0409 u32 lfbdv = __fix_zero(plld & 0x3f, 64);
0410 u32 pradv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMAD) >> 24) & 7, 8);
0411 u32 prbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMBD) >> 24) & 7, 8);
0412 u32 opbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_OPBD) >> 24) & 3, 4);
0413 u32 perdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PERD) >> 24) & 3, 4);
0414
0415
0416 u32 clk_a, clk_b;
0417
0418
0419 u32 cpu, plb, opb, ebc, vco;
0420
0421
0422 u32 ccr1, tb = tmr_clk;
0423
0424 if (pllc & 0x40000000) {
0425 u32 m;
0426
0427
0428 switch ((pllc >> 24) & 7) {
0429 case 0:
0430
0431 m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
0432 break;
0433 case 1:
0434
0435 m = fwdva * pradv0;
0436 break;
0437 case 5:
0438
0439 m = fwdvb * prbdv0 * opbdv0 * perdv0;
0440 break;
0441 default:
0442 printf("WARNING ! Invalid PLL feedback source !\n");
0443 goto bypass;
0444 }
0445 m *= fbdv;
0446 vco = sys_clk * m;
0447 clk_a = vco / fwdva;
0448 clk_b = vco / fwdvb;
0449 } else {
0450 bypass:
0451
0452 vco = 0;
0453 clk_a = clk_b = sys_clk;
0454 }
0455
0456 cpu = clk_a / pradv0;
0457 plb = clk_b / prbdv0;
0458 opb = plb / opbdv0;
0459 ebc = (per_clk_from_opb ? opb : plb) / perdv0;
0460
0461
0462 ccr1 = mfspr(SPRN_CCR1);
0463
0464
0465 if (tb == 0) {
0466 ccr1 &= ~0x80u;
0467 mtspr(SPRN_CCR1, ccr1);
0468 }
0469 if ((ccr1 & 0x0080) == 0)
0470 tb = cpu;
0471
0472 dt_fixup_cpu_clocks(cpu, tb, 0);
0473 dt_fixup_clock("/plb", plb);
0474 dt_fixup_clock("/plb/opb", opb);
0475 dt_fixup_clock("/plb/opb/ebc", ebc);
0476
0477 return plb;
0478 }
0479
0480 static void eplike_fixup_uart_clk(int index, const char *path,
0481 unsigned int ser_clk,
0482 unsigned int plb_clk)
0483 {
0484 unsigned int sdr;
0485 unsigned int clock;
0486
0487 switch (index) {
0488 case 0:
0489 sdr = SDR0_READ(DCRN_SDR0_UART0);
0490 break;
0491 case 1:
0492 sdr = SDR0_READ(DCRN_SDR0_UART1);
0493 break;
0494 case 2:
0495 sdr = SDR0_READ(DCRN_SDR0_UART2);
0496 break;
0497 case 3:
0498 sdr = SDR0_READ(DCRN_SDR0_UART3);
0499 break;
0500 default:
0501 return;
0502 }
0503
0504 if (sdr & 0x00800000u)
0505 clock = ser_clk;
0506 else
0507 clock = plb_clk / __fix_zero(sdr & 0xff, 256);
0508
0509 dt_fixup_clock(path, clock);
0510 }
0511
0512 void ibm440ep_fixup_clocks(unsigned int sys_clk,
0513 unsigned int ser_clk,
0514 unsigned int tmr_clk)
0515 {
0516 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
0517
0518
0519 eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
0520 eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
0521 eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
0522 eplike_fixup_uart_clk(3, "/plb/opb/serial@ef600600", ser_clk, plb_clk);
0523 }
0524
0525 void ibm440gx_fixup_clocks(unsigned int sys_clk,
0526 unsigned int ser_clk,
0527 unsigned int tmr_clk)
0528 {
0529 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
0530
0531
0532 eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
0533 eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
0534 }
0535
0536 void ibm440spe_fixup_clocks(unsigned int sys_clk,
0537 unsigned int ser_clk,
0538 unsigned int tmr_clk)
0539 {
0540 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
0541
0542
0543 eplike_fixup_uart_clk(0, "/plb/opb/serial@f0000200", ser_clk, plb_clk);
0544 eplike_fixup_uart_clk(1, "/plb/opb/serial@f0000300", ser_clk, plb_clk);
0545 eplike_fixup_uart_clk(2, "/plb/opb/serial@f0000600", ser_clk, plb_clk);
0546 }
0547
0548 void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
0549 {
0550 u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
0551 u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
0552 u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
0553 u32 psr = mfdcr(DCRN_405_CPC0_PSR);
0554 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
0555 u32 fwdv, fwdvb, fbdv, cbdv, opdv, epdv, ppdv, udiv;
0556
0557 fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
0558 fbdv = (pllmr & 0x1e000000) >> 25;
0559 if (fbdv == 0)
0560 fbdv = 16;
0561 cbdv = ((pllmr & 0x00060000) >> 17) + 1;
0562 opdv = ((pllmr & 0x00018000) >> 15) + 1;
0563 ppdv = ((pllmr & 0x00006000) >> 13) + 1;
0564 epdv = ((pllmr & 0x00001800) >> 11) + 2;
0565 udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
0566
0567
0568 if ((mfpvr() & 0xfffffff0) == (0x50910951 & 0xfffffff0)) {
0569 fwdvb = 8 - (pllmr & 0x00000007);
0570 if (!(psr & 0x00001000))
0571 if (psr & 0x00000020)
0572 m = fwdvb * 2 * ppdv;
0573 else
0574 m = fwdvb * cbdv * ppdv;
0575 else if (psr & 0x00000020)
0576 if (psr & 0x00000800)
0577 m = fwdvb * 2 * epdv;
0578 else
0579 m = fbdv * fwdv;
0580 else if (epdv == fbdv)
0581 m = fbdv * cbdv * epdv;
0582 else
0583 m = fbdv * fwdvb * cbdv;
0584
0585 cpu = sys_clk * m / fwdv;
0586 plb = sys_clk * m / (fwdvb * cbdv);
0587 } else {
0588 m = fwdv * fbdv * cbdv;
0589 cpu = sys_clk * m / fwdv;
0590 plb = cpu / cbdv;
0591 }
0592 opb = plb / opdv;
0593 ebc = plb / epdv;
0594
0595 if (cpc0_cr0 & 0x80)
0596
0597 uart0 = ser_clk;
0598 else
0599 uart0 = cpu / udiv;
0600
0601 if (cpc0_cr0 & 0x40)
0602
0603 uart1 = ser_clk;
0604 else
0605 uart1 = cpu / udiv;
0606
0607
0608 cpc0_cr1 = cpc0_cr1 & ~0x00800000;
0609 mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
0610 tb = cpu;
0611
0612 dt_fixup_cpu_clocks(cpu, tb, 0);
0613 dt_fixup_clock("/plb", plb);
0614 dt_fixup_clock("/plb/opb", opb);
0615 dt_fixup_clock("/plb/ebc", ebc);
0616 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
0617 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
0618 }
0619
0620
0621 void ibm405ep_fixup_clocks(unsigned int sys_clk)
0622 {
0623 u32 pllmr0 = mfdcr(DCRN_CPC0_PLLMR0);
0624 u32 pllmr1 = mfdcr(DCRN_CPC0_PLLMR1);
0625 u32 cpc0_ucr = mfdcr(DCRN_CPC0_UCR);
0626 u32 cpu, plb, opb, ebc, uart0, uart1;
0627 u32 fwdva, fwdvb, fbdv, cbdv, opdv, epdv;
0628 u32 pllmr0_ccdv, tb, m;
0629
0630 fwdva = 8 - ((pllmr1 & 0x00070000) >> 16);
0631 fwdvb = 8 - ((pllmr1 & 0x00007000) >> 12);
0632 fbdv = (pllmr1 & 0x00f00000) >> 20;
0633 if (fbdv == 0)
0634 fbdv = 16;
0635
0636 cbdv = ((pllmr0 & 0x00030000) >> 16) + 1;
0637 epdv = ((pllmr0 & 0x00000300) >> 8) + 2;
0638 opdv = ((pllmr0 & 0x00003000) >> 12) + 1;
0639
0640 m = fbdv * fwdvb;
0641
0642 pllmr0_ccdv = ((pllmr0 & 0x00300000) >> 20) + 1;
0643 if (pllmr1 & 0x80000000)
0644 cpu = sys_clk * m / (fwdva * pllmr0_ccdv);
0645 else
0646 cpu = sys_clk / pllmr0_ccdv;
0647
0648 plb = cpu / cbdv;
0649 opb = plb / opdv;
0650 ebc = plb / epdv;
0651 tb = cpu;
0652 uart0 = cpu / (cpc0_ucr & 0x0000007f);
0653 uart1 = cpu / ((cpc0_ucr & 0x00007f00) >> 8);
0654
0655 dt_fixup_cpu_clocks(cpu, tb, 0);
0656 dt_fixup_clock("/plb", plb);
0657 dt_fixup_clock("/plb/opb", opb);
0658 dt_fixup_clock("/plb/ebc", ebc);
0659 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
0660 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
0661 }
0662
0663 static u8 ibm405ex_fwdv_multi_bits[] = {
0664
0665 0x01, 0x02, 0x0e, 0x09, 0x04, 0x0b, 0x10, 0x0d, 0x0c, 0x05,
0666 0x06, 0x0f, 0x0a, 0x07, 0x08, 0x03
0667 };
0668
0669 u32 ibm405ex_get_fwdva(unsigned long cpr_fwdv)
0670 {
0671 u32 index;
0672
0673 for (index = 0; index < ARRAY_SIZE(ibm405ex_fwdv_multi_bits); index++)
0674 if (cpr_fwdv == (u32)ibm405ex_fwdv_multi_bits[index])
0675 return index + 1;
0676
0677 return 0;
0678 }
0679
0680 static u8 ibm405ex_fbdv_multi_bits[] = {
0681
0682 0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
0683 0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
0684 0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
0685 0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
0686 0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
0687 0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
0688 0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
0689 0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
0690 0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
0691 0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
0692
0693 0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
0694 0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
0695 0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
0696 0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
0697 0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
0698 0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
0699 0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
0700 0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
0701 0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
0702 0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
0703
0704 0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
0705 0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
0706 0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
0707 0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
0708 0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
0709 0x03, 0x87, 0x0f, 0x9f, 0x3f
0710 };
0711
0712 u32 ibm405ex_get_fbdv(unsigned long cpr_fbdv)
0713 {
0714 u32 index;
0715
0716 for (index = 0; index < ARRAY_SIZE(ibm405ex_fbdv_multi_bits); index++)
0717 if (cpr_fbdv == (u32)ibm405ex_fbdv_multi_bits[index])
0718 return index + 1;
0719
0720 return 0;
0721 }
0722
0723 void ibm405ex_fixup_clocks(unsigned int sys_clk, unsigned int uart_clk)
0724 {
0725
0726 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
0727 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
0728 u32 cpud = CPR0_READ(DCRN_CPR0_PRIMAD);
0729 u32 plbd = CPR0_READ(DCRN_CPR0_PRIMBD);
0730 u32 opbd = CPR0_READ(DCRN_CPR0_OPBD);
0731 u32 perd = CPR0_READ(DCRN_CPR0_PERD);
0732
0733
0734 u32 fbdv = ibm405ex_get_fbdv(__fix_zero((plld >> 24) & 0xff, 1));
0735
0736 u32 fwdva = ibm405ex_get_fwdva(__fix_zero((plld >> 16) & 0x0f, 1));
0737
0738 u32 cpudv0 = __fix_zero((cpud >> 24) & 7, 8);
0739
0740
0741 u32 plbdv0 = 2;
0742 u32 plb2xdv0 = __fix_zero((plbd >> 16) & 7, 8);
0743
0744 u32 opbdv0 = __fix_zero((opbd >> 24) & 3, 4);
0745
0746 u32 perdv0 = __fix_zero((perd >> 24) & 3, 4);
0747
0748
0749 u32 cpu, plb, opb, ebc, vco, tb, uart0, uart1;
0750
0751
0752 if (pllc & 0x40000000) {
0753 u32 m;
0754
0755
0756 switch ((pllc >> 24) & 7) {
0757 case 0:
0758
0759 m = fbdv;
0760 break;
0761 case 1:
0762
0763 m = fbdv * fwdva * cpudv0;
0764 break;
0765 case 5:
0766
0767 m = fbdv * fwdva * plb2xdv0 * plbdv0 * opbdv0 * perdv0;
0768 break;
0769 default:
0770 printf("WARNING ! Invalid PLL feedback source !\n");
0771 goto bypass;
0772 }
0773
0774 vco = (unsigned int)(sys_clk * m);
0775 } else {
0776 bypass:
0777
0778 vco = 0;
0779 }
0780
0781
0782 cpu = vco / (fwdva * cpudv0);
0783
0784 plb = vco / (fwdva * plb2xdv0 * plbdv0);
0785
0786 opb = plb / opbdv0;
0787
0788 ebc = opb / perdv0;
0789
0790 tb = cpu;
0791 uart0 = uart1 = uart_clk;
0792
0793 dt_fixup_cpu_clocks(cpu, tb, 0);
0794 dt_fixup_clock("/plb", plb);
0795 dt_fixup_clock("/plb/opb", opb);
0796 dt_fixup_clock("/plb/opb/ebc", ebc);
0797 dt_fixup_clock("/plb/opb/serial@ef600200", uart0);
0798 dt_fixup_clock("/plb/opb/serial@ef600300", uart1);
0799 }