GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / arch / powerpc / boot / 4xx.c
blobc0ce7575ac58063ad18c7090ce01a40e58954081
1 /*
2 * Copyright 2007 David Gibson, IBM Corporation.
4 * Based on earlier code:
5 * Matt Porter <mporter@kernel.crashing.org>
6 * Copyright 2002-2005 MontaVista Software Inc.
8 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
9 * Copyright (c) 2003, 2004 Zultys Technologies
11 * Copyright (C) 2009 Wind River Systems, Inc.
12 * Updated for supporting PPC405EX on Kilauea.
13 * Tiejun Chen <tiejun.chen@windriver.com>
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
20 #include <stddef.h>
21 #include "types.h"
22 #include "string.h"
23 #include "stdio.h"
24 #include "ops.h"
25 #include "reg.h"
26 #include "dcr.h"
28 static unsigned long chip_11_errata(unsigned long memsize)
30 unsigned long pvr;
32 pvr = mfpvr();
34 switch (pvr & 0xf0000ff0) {
35 case 0x40000850:
36 case 0x400008d0:
37 case 0x200008d0:
38 memsize -= 4096;
39 break;
40 default:
41 break;
44 return memsize;
47 /* Read the 4xx SDRAM controller to get size of system memory. */
48 void ibm4xx_sdram_fixup_memsize(void)
50 int i;
51 unsigned long memsize, bank_config;
53 memsize = 0;
54 for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
55 bank_config = SDRAM0_READ(sdram_bxcr[i]);
56 if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
57 memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
60 memsize = chip_11_errata(memsize);
61 dt_fixup_memory(0, memsize);
64 /* Read the 440SPe MQ controller to get size of system memory. */
65 #define DCRN_MQ0_B0BAS 0x40
66 #define DCRN_MQ0_B1BAS 0x41
67 #define DCRN_MQ0_B2BAS 0x42
68 #define DCRN_MQ0_B3BAS 0x43
70 static u64 ibm440spe_decode_bas(u32 bas)
72 u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
74 /* open coded because I'm paranoid about invalid values */
75 switch ((bas >> 4) & 0xFFF) {
76 case 0:
77 return 0;
78 case 0xffc:
79 return base + 0x000800000ull;
80 case 0xff8:
81 return base + 0x001000000ull;
82 case 0xff0:
83 return base + 0x002000000ull;
84 case 0xfe0:
85 return base + 0x004000000ull;
86 case 0xfc0:
87 return base + 0x008000000ull;
88 case 0xf80:
89 return base + 0x010000000ull;
90 case 0xf00:
91 return base + 0x020000000ull;
92 case 0xe00:
93 return base + 0x040000000ull;
94 case 0xc00:
95 return base + 0x080000000ull;
96 case 0x800:
97 return base + 0x100000000ull;
99 printf("Memory BAS value 0x%08x unsupported !\n", bas);
100 return 0;
103 void ibm440spe_fixup_memsize(void)
105 u64 banktop, memsize = 0;
107 /* Ultimately, we should directly construct the memory node
108 * so we are able to handle holes in the memory address space
110 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
111 if (banktop > memsize)
112 memsize = banktop;
113 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
114 if (banktop > memsize)
115 memsize = banktop;
116 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
117 if (banktop > memsize)
118 memsize = banktop;
119 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
120 if (banktop > memsize)
121 memsize = banktop;
123 dt_fixup_memory(0, memsize);
127 /* 4xx DDR1/2 Denali memory controller support */
128 /* DDR0 registers */
129 #define DDR0_02 2
130 #define DDR0_08 8
131 #define DDR0_10 10
132 #define DDR0_14 14
133 #define DDR0_42 42
134 #define DDR0_43 43
136 /* DDR0_02 */
137 #define DDR_START 0x1
138 #define DDR_START_SHIFT 0
139 #define DDR_MAX_CS_REG 0x3
140 #define DDR_MAX_CS_REG_SHIFT 24
141 #define DDR_MAX_COL_REG 0xf
142 #define DDR_MAX_COL_REG_SHIFT 16
143 #define DDR_MAX_ROW_REG 0xf
144 #define DDR_MAX_ROW_REG_SHIFT 8
145 /* DDR0_08 */
146 #define DDR_DDR2_MODE 0x1
147 #define DDR_DDR2_MODE_SHIFT 0
148 /* DDR0_10 */
149 #define DDR_CS_MAP 0x3
150 #define DDR_CS_MAP_SHIFT 8
151 /* DDR0_14 */
152 #define DDR_REDUC 0x1
153 #define DDR_REDUC_SHIFT 16
154 /* DDR0_42 */
155 #define DDR_APIN 0x7
156 #define DDR_APIN_SHIFT 24
157 /* DDR0_43 */
158 #define DDR_COL_SZ 0x7
159 #define DDR_COL_SZ_SHIFT 8
160 #define DDR_BANK8 0x1
161 #define DDR_BANK8_SHIFT 0
163 #define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
166 * Some U-Boot versions set the number of chipselects to two
167 * for Sequoia/Rainier boards while they only have one chipselect
168 * hardwired. Hardcode the number of chipselects to one
169 * for sequioa/rainer board models or read the actual value
170 * from the memory controller register DDR0_10 otherwise.
172 static inline u32 ibm4xx_denali_get_cs(void)
174 void *devp;
175 char model[64];
176 u32 val, cs;
178 devp = finddevice("/");
179 if (!devp)
180 goto read_cs;
182 if (getprop(devp, "model", model, sizeof(model)) <= 0)
183 goto read_cs;
185 model[sizeof(model)-1] = 0;
187 if (!strcmp(model, "amcc,sequoia") ||
188 !strcmp(model, "amcc,rainier"))
189 return 1;
191 read_cs:
192 /* get CS value */
193 val = SDRAM0_READ(DDR0_10);
195 val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
196 cs = 0;
197 while (val) {
198 if (val & 0x1)
199 cs++;
200 val = val >> 1;
202 return cs;
205 void ibm4xx_denali_fixup_memsize(void)
207 u32 val, max_cs, max_col, max_row;
208 u32 cs, col, row, bank, dpath;
209 unsigned long memsize;
211 val = SDRAM0_READ(DDR0_02);
212 if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
213 fatal("DDR controller is not initialized\n");
215 /* get maximum cs col and row values */
216 max_cs = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
217 max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
218 max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
220 cs = ibm4xx_denali_get_cs();
221 if (!cs)
222 fatal("No memory installed\n");
223 if (cs > max_cs)
224 fatal("DDR wrong CS configuration\n");
226 /* get data path bytes */
227 val = SDRAM0_READ(DDR0_14);
229 if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
230 dpath = 4; /* 32 bits */
231 else
232 dpath = 8; /* 64 bits */
234 /* get address pins (rows) */
235 val = SDRAM0_READ(DDR0_42);
237 row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
238 if (row > max_row)
239 fatal("DDR wrong APIN configuration\n");
240 row = max_row - row;
242 /* get collomn size and banks */
243 val = SDRAM0_READ(DDR0_43);
245 col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
246 if (col > max_col)
247 fatal("DDR wrong COL configuration\n");
248 col = max_col - col;
250 if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
251 bank = 8; /* 8 banks */
252 else
253 bank = 4; /* 4 banks */
255 memsize = cs * (1 << (col+row)) * bank * dpath;
256 memsize = chip_11_errata(memsize);
257 dt_fixup_memory(0, memsize);
260 #define SPRN_DBCR0_40X 0x3F2
261 #define SPRN_DBCR0_44X 0x134
262 #define DBCR0_RST_SYSTEM 0x30000000
264 void ibm44x_dbcr_reset(void)
266 unsigned long tmp;
268 asm volatile (
269 "mfspr %0,%1\n"
270 "oris %0,%0,%2@h\n"
271 "mtspr %1,%0"
272 : "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
277 void ibm40x_dbcr_reset(void)
279 unsigned long tmp;
281 asm volatile (
282 "mfspr %0,%1\n"
283 "oris %0,%0,%2@h\n"
284 "mtspr %1,%0"
285 : "=&r"(tmp) : "i"(SPRN_DBCR0_40X), "i"(DBCR0_RST_SYSTEM)
289 #define EMAC_RESET 0x20000000
290 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
292 /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
293 * do this for us
295 if (emac0)
296 *emac0 = EMAC_RESET;
297 if (emac1)
298 *emac1 = EMAC_RESET;
300 mtdcr(DCRN_MAL0_CFG, MAL_RESET);
301 while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
302 ; /* loop until reset takes effect */
305 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
306 * banks into the OPB address space */
307 void ibm4xx_fixup_ebc_ranges(const char *ebc)
309 void *devp;
310 u32 bxcr;
311 u32 ranges[EBC_NUM_BANKS*4];
312 u32 *p = ranges;
313 int i;
315 for (i = 0; i < EBC_NUM_BANKS; i++) {
316 mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
317 bxcr = mfdcr(DCRN_EBC0_CFGDATA);
319 if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
320 *p++ = i;
321 *p++ = 0;
322 *p++ = bxcr & EBC_BXCR_BAS;
323 *p++ = EBC_BXCR_BANK_SIZE(bxcr);
327 devp = finddevice(ebc);
328 if (! devp)
329 fatal("Couldn't locate EBC node %s\n\r", ebc);
331 setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
334 /* Calculate 440GP clocks */
335 void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
337 u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
338 u32 cr0 = mfdcr(DCRN_CPC0_CR0);
339 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
340 u32 opdv = CPC0_SYS0_OPDV(sys0);
341 u32 epdv = CPC0_SYS0_EPDV(sys0);
343 if (sys0 & CPC0_SYS0_BYPASS) {
344 /* Bypass system PLL */
345 cpu = plb = sys_clk;
346 } else {
347 if (sys0 & CPC0_SYS0_EXTSL)
348 /* PerClk */
349 m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
350 else
351 /* CPU clock */
352 m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
353 cpu = sys_clk * m / CPC0_SYS0_FWDVA(sys0);
354 plb = sys_clk * m / CPC0_SYS0_FWDVB(sys0);
357 opb = plb / opdv;
358 ebc = opb / epdv;
360 if ((mfpvr() & 0xf0000fff) == 0x40000440)
361 /* Rev. B 440GP, use external system clock */
362 tb = sys_clk;
363 else
364 /* Rev. C 440GP, errata force us to use internal clock */
365 tb = cpu;
367 if (cr0 & CPC0_CR0_U0EC)
368 /* External UART clock */
369 uart0 = ser_clk;
370 else
371 /* Internal UART clock */
372 uart0 = plb / CPC0_CR0_UDIV(cr0);
374 if (cr0 & CPC0_CR0_U1EC)
375 /* External UART clock */
376 uart1 = ser_clk;
377 else
378 /* Internal UART clock */
379 uart1 = plb / CPC0_CR0_UDIV(cr0);
381 printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
382 (sys_clk + 500000) / 1000000, sys_clk);
384 dt_fixup_cpu_clocks(cpu, tb, 0);
386 dt_fixup_clock("/plb", plb);
387 dt_fixup_clock("/plb/opb", opb);
388 dt_fixup_clock("/plb/opb/ebc", ebc);
389 dt_fixup_clock("/plb/opb/serial@40000200", uart0);
390 dt_fixup_clock("/plb/opb/serial@40000300", uart1);
393 #define SPRN_CCR1 0x378
395 static inline u32 __fix_zero(u32 v, u32 def)
397 return v ? v : def;
400 static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
401 unsigned int tmr_clk,
402 int per_clk_from_opb)
404 /* PLL config */
405 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
406 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
408 /* Dividers */
409 u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32);
410 u32 fwdva = __fix_zero((plld >> 16) & 0xf, 16);
411 u32 fwdvb = __fix_zero((plld >> 8) & 7, 8);
412 u32 lfbdv = __fix_zero(plld & 0x3f, 64);
413 u32 pradv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMAD) >> 24) & 7, 8);
414 u32 prbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMBD) >> 24) & 7, 8);
415 u32 opbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_OPBD) >> 24) & 3, 4);
416 u32 perdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PERD) >> 24) & 3, 4);
418 /* Input clocks for primary dividers */
419 u32 clk_a, clk_b;
421 /* Resulting clocks */
422 u32 cpu, plb, opb, ebc, vco;
424 /* Timebase */
425 u32 ccr1, tb = tmr_clk;
427 if (pllc & 0x40000000) {
428 u32 m;
430 /* Feedback path */
431 switch ((pllc >> 24) & 7) {
432 case 0:
433 /* PLLOUTx */
434 m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
435 break;
436 case 1:
437 /* CPU */
438 m = fwdva * pradv0;
439 break;
440 case 5:
441 /* PERClk */
442 m = fwdvb * prbdv0 * opbdv0 * perdv0;
443 break;
444 default:
445 printf("WARNING ! Invalid PLL feedback source !\n");
446 goto bypass;
448 m *= fbdv;
449 vco = sys_clk * m;
450 clk_a = vco / fwdva;
451 clk_b = vco / fwdvb;
452 } else {
453 bypass:
454 /* Bypass system PLL */
455 vco = 0;
456 clk_a = clk_b = sys_clk;
459 cpu = clk_a / pradv0;
460 plb = clk_b / prbdv0;
461 opb = plb / opbdv0;
462 ebc = (per_clk_from_opb ? opb : plb) / perdv0;
464 /* Figure out timebase. Either CPU or default TmrClk */
465 ccr1 = mfspr(SPRN_CCR1);
467 /* If passed a 0 tmr_clk, force CPU clock */
468 if (tb == 0) {
469 ccr1 &= ~0x80u;
470 mtspr(SPRN_CCR1, ccr1);
472 if ((ccr1 & 0x0080) == 0)
473 tb = cpu;
475 dt_fixup_cpu_clocks(cpu, tb, 0);
476 dt_fixup_clock("/plb", plb);
477 dt_fixup_clock("/plb/opb", opb);
478 dt_fixup_clock("/plb/opb/ebc", ebc);
480 return plb;
483 static void eplike_fixup_uart_clk(int index, const char *path,
484 unsigned int ser_clk,
485 unsigned int plb_clk)
487 unsigned int sdr;
488 unsigned int clock;
490 switch (index) {
491 case 0:
492 sdr = SDR0_READ(DCRN_SDR0_UART0);
493 break;
494 case 1:
495 sdr = SDR0_READ(DCRN_SDR0_UART1);
496 break;
497 case 2:
498 sdr = SDR0_READ(DCRN_SDR0_UART2);
499 break;
500 case 3:
501 sdr = SDR0_READ(DCRN_SDR0_UART3);
502 break;
503 default:
504 return;
507 if (sdr & 0x00800000u)
508 clock = ser_clk;
509 else
510 clock = plb_clk / __fix_zero(sdr & 0xff, 256);
512 dt_fixup_clock(path, clock);
515 void ibm440ep_fixup_clocks(unsigned int sys_clk,
516 unsigned int ser_clk,
517 unsigned int tmr_clk)
519 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
521 /* serial clocks need fixup based on int/ext */
522 eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
523 eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
524 eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
525 eplike_fixup_uart_clk(3, "/plb/opb/serial@ef600600", ser_clk, plb_clk);
528 void ibm440gx_fixup_clocks(unsigned int sys_clk,
529 unsigned int ser_clk,
530 unsigned int tmr_clk)
532 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
534 /* serial clocks need fixup based on int/ext */
535 eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
536 eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
539 void ibm440spe_fixup_clocks(unsigned int sys_clk,
540 unsigned int ser_clk,
541 unsigned int tmr_clk)
543 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
545 /* serial clocks need fixup based on int/ext */
546 eplike_fixup_uart_clk(0, "/plb/opb/serial@f0000200", ser_clk, plb_clk);
547 eplike_fixup_uart_clk(1, "/plb/opb/serial@f0000300", ser_clk, plb_clk);
548 eplike_fixup_uart_clk(2, "/plb/opb/serial@f0000600", ser_clk, plb_clk);
551 void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
553 u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
554 u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
555 u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
556 u32 psr = mfdcr(DCRN_405_CPC0_PSR);
557 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
558 u32 fwdv, fwdvb, fbdv, cbdv, opdv, epdv, ppdv, udiv;
560 fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
561 fbdv = (pllmr & 0x1e000000) >> 25;
562 if (fbdv == 0)
563 fbdv = 16;
564 cbdv = ((pllmr & 0x00060000) >> 17) + 1; /* CPU:PLB */
565 opdv = ((pllmr & 0x00018000) >> 15) + 1; /* PLB:OPB */
566 ppdv = ((pllmr & 0x00001800) >> 13) + 1; /* PLB:PCI */
567 epdv = ((pllmr & 0x00001800) >> 11) + 2; /* PLB:EBC */
568 udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
570 /* check for 405GPr */
571 if ((mfpvr() & 0xfffffff0) == (0x50910951 & 0xfffffff0)) {
572 fwdvb = 8 - (pllmr & 0x00000007);
573 if (!(psr & 0x00001000)) /* PCI async mode enable == 0 */
574 if (psr & 0x00000020) /* New mode enable */
575 m = fwdvb * 2 * ppdv;
576 else
577 m = fwdvb * cbdv * ppdv;
578 else if (psr & 0x00000020) /* New mode enable */
579 if (psr & 0x00000800) /* PerClk synch mode */
580 m = fwdvb * 2 * epdv;
581 else
582 m = fbdv * fwdv;
583 else if (epdv == fbdv)
584 m = fbdv * cbdv * epdv;
585 else
586 m = fbdv * fwdvb * cbdv;
588 cpu = sys_clk * m / fwdv;
589 plb = sys_clk * m / (fwdvb * cbdv);
590 } else {
591 m = fwdv * fbdv * cbdv;
592 cpu = sys_clk * m / fwdv;
593 plb = cpu / cbdv;
595 opb = plb / opdv;
596 ebc = plb / epdv;
598 if (cpc0_cr0 & 0x80)
599 /* uart0 uses the external clock */
600 uart0 = ser_clk;
601 else
602 uart0 = cpu / udiv;
604 if (cpc0_cr0 & 0x40)
605 /* uart1 uses the external clock */
606 uart1 = ser_clk;
607 else
608 uart1 = cpu / udiv;
610 /* setup the timebase clock to tick at the cpu frequency */
611 cpc0_cr1 = cpc0_cr1 & ~0x00800000;
612 mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
613 tb = cpu;
615 dt_fixup_cpu_clocks(cpu, tb, 0);
616 dt_fixup_clock("/plb", plb);
617 dt_fixup_clock("/plb/opb", opb);
618 dt_fixup_clock("/plb/ebc", ebc);
619 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
620 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
624 void ibm405ep_fixup_clocks(unsigned int sys_clk)
626 u32 pllmr0 = mfdcr(DCRN_CPC0_PLLMR0);
627 u32 pllmr1 = mfdcr(DCRN_CPC0_PLLMR1);
628 u32 cpc0_ucr = mfdcr(DCRN_CPC0_UCR);
629 u32 cpu, plb, opb, ebc, uart0, uart1;
630 u32 fwdva, fwdvb, fbdv, cbdv, opdv, epdv;
631 u32 pllmr0_ccdv, tb, m;
633 fwdva = 8 - ((pllmr1 & 0x00070000) >> 16);
634 fwdvb = 8 - ((pllmr1 & 0x00007000) >> 12);
635 fbdv = (pllmr1 & 0x00f00000) >> 20;
636 if (fbdv == 0)
637 fbdv = 16;
639 cbdv = ((pllmr0 & 0x00030000) >> 16) + 1; /* CPU:PLB */
640 epdv = ((pllmr0 & 0x00000300) >> 8) + 2; /* PLB:EBC */
641 opdv = ((pllmr0 & 0x00003000) >> 12) + 1; /* PLB:OPB */
643 m = fbdv * fwdvb;
645 pllmr0_ccdv = ((pllmr0 & 0x00300000) >> 20) + 1;
646 if (pllmr1 & 0x80000000)
647 cpu = sys_clk * m / (fwdva * pllmr0_ccdv);
648 else
649 cpu = sys_clk / pllmr0_ccdv;
651 plb = cpu / cbdv;
652 opb = plb / opdv;
653 ebc = plb / epdv;
654 tb = cpu;
655 uart0 = cpu / (cpc0_ucr & 0x0000007f);
656 uart1 = cpu / ((cpc0_ucr & 0x00007f00) >> 8);
658 dt_fixup_cpu_clocks(cpu, tb, 0);
659 dt_fixup_clock("/plb", plb);
660 dt_fixup_clock("/plb/opb", opb);
661 dt_fixup_clock("/plb/ebc", ebc);
662 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
663 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
666 static u8 ibm405ex_fwdv_multi_bits[] = {
667 /* values for: 1 - 16 */
668 0x01, 0x02, 0x0e, 0x09, 0x04, 0x0b, 0x10, 0x0d, 0x0c, 0x05,
669 0x06, 0x0f, 0x0a, 0x07, 0x08, 0x03
672 u32 ibm405ex_get_fwdva(unsigned long cpr_fwdv)
674 u32 index;
676 for (index = 0; index < ARRAY_SIZE(ibm405ex_fwdv_multi_bits); index++)
677 if (cpr_fwdv == (u32)ibm405ex_fwdv_multi_bits[index])
678 return index + 1;
680 return 0;
683 static u8 ibm405ex_fbdv_multi_bits[] = {
684 /* values for: 1 - 100 */
685 0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
686 0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
687 0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
688 0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
689 0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
690 0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
691 0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
692 0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
693 0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
694 0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
695 /* values for: 101 - 200 */
696 0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
697 0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
698 0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
699 0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
700 0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
701 0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
702 0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
703 0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
704 0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
705 0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
706 /* values for: 201 - 255 */
707 0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
708 0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
709 0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
710 0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
711 0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
712 0x03, 0x87, 0x0f, 0x9f, 0x3f /* END */
715 u32 ibm405ex_get_fbdv(unsigned long cpr_fbdv)
717 u32 index;
719 for (index = 0; index < ARRAY_SIZE(ibm405ex_fbdv_multi_bits); index++)
720 if (cpr_fbdv == (u32)ibm405ex_fbdv_multi_bits[index])
721 return index + 1;
723 return 0;
726 void ibm405ex_fixup_clocks(unsigned int sys_clk, unsigned int uart_clk)
728 /* PLL config */
729 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
730 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
731 u32 cpud = CPR0_READ(DCRN_CPR0_PRIMAD);
732 u32 plbd = CPR0_READ(DCRN_CPR0_PRIMBD);
733 u32 opbd = CPR0_READ(DCRN_CPR0_OPBD);
734 u32 perd = CPR0_READ(DCRN_CPR0_PERD);
736 /* Dividers */
737 u32 fbdv = ibm405ex_get_fbdv(__fix_zero((plld >> 24) & 0xff, 1));
739 u32 fwdva = ibm405ex_get_fwdva(__fix_zero((plld >> 16) & 0x0f, 1));
741 u32 cpudv0 = __fix_zero((cpud >> 24) & 7, 8);
743 /* PLBDV0 is hardwared to 010. */
744 u32 plbdv0 = 2;
745 u32 plb2xdv0 = __fix_zero((plbd >> 16) & 7, 8);
747 u32 opbdv0 = __fix_zero((opbd >> 24) & 3, 4);
749 u32 perdv0 = __fix_zero((perd >> 24) & 3, 4);
751 /* Resulting clocks */
752 u32 cpu, plb, opb, ebc, vco, tb, uart0, uart1;
754 /* PLL's VCO is the source for primary forward ? */
755 if (pllc & 0x40000000) {
756 u32 m;
758 /* Feedback path */
759 switch ((pllc >> 24) & 7) {
760 case 0:
761 /* PLLOUTx */
762 m = fbdv;
763 break;
764 case 1:
765 /* CPU */
766 m = fbdv * fwdva * cpudv0;
767 break;
768 case 5:
769 /* PERClk */
770 m = fbdv * fwdva * plb2xdv0 * plbdv0 * opbdv0 * perdv0;
771 break;
772 default:
773 printf("WARNING ! Invalid PLL feedback source !\n");
774 goto bypass;
777 vco = (unsigned int)(sys_clk * m);
778 } else {
779 bypass:
780 /* Bypass system PLL */
781 vco = 0;
784 /* CPU = VCO / ( FWDVA x CPUDV0) */
785 cpu = vco / (fwdva * cpudv0);
786 /* PLB = VCO / ( FWDVA x PLB2XDV0 x PLBDV0) */
787 plb = vco / (fwdva * plb2xdv0 * plbdv0);
788 /* OPB = PLB / OPBDV0 */
789 opb = plb / opbdv0;
790 /* EBC = OPB / PERDV0 */
791 ebc = opb / perdv0;
793 tb = cpu;
794 uart0 = uart1 = uart_clk;
796 dt_fixup_cpu_clocks(cpu, tb, 0);
797 dt_fixup_clock("/plb", plb);
798 dt_fixup_clock("/plb/opb", opb);
799 dt_fixup_clock("/plb/opb/ebc", ebc);
800 dt_fixup_clock("/plb/opb/serial@ef600200", uart0);
801 dt_fixup_clock("/plb/opb/serial@ef600300", uart1);