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.c476
1 files changed, 393 insertions, 83 deletions
diff --git a/arch/powerpc/boot/4xx.c b/arch/powerpc/boot/4xx.c
index ebf9e217612d..758edf1c5815 100644
--- a/arch/powerpc/boot/4xx.c
+++ b/arch/powerpc/boot/4xx.c
@@ -22,16 +22,14 @@
22#include "dcr.h" 22#include "dcr.h"
23 23
24/* Read the 4xx SDRAM controller to get size of system memory. */ 24/* Read the 4xx SDRAM controller to get size of system memory. */
25void ibm4xx_fixup_memsize(void) 25void ibm4xx_sdram_fixup_memsize(void)
26{ 26{
27 int i; 27 int i;
28 unsigned long memsize, bank_config; 28 unsigned long memsize, bank_config;
29 29
30 memsize = 0; 30 memsize = 0;
31 for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) { 31 for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
32 mtdcr(DCRN_SDRAM0_CFGADDR, sdram_bxcr[i]); 32 bank_config = SDRAM0_READ(sdram_bxcr[i]);
33 bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
34
35 if (bank_config & SDRAM_CONFIG_BANK_ENABLE) 33 if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
36 memsize += SDRAM_CONFIG_BANK_SIZE(bank_config); 34 memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
37 } 35 }
@@ -39,6 +37,69 @@ void ibm4xx_fixup_memsize(void)
39 dt_fixup_memory(0, memsize); 37 dt_fixup_memory(0, memsize);
40} 38}
41 39
40/* Read the 440SPe MQ controller to get size of system memory. */
41#define DCRN_MQ0_B0BAS 0x40
42#define DCRN_MQ0_B1BAS 0x41
43#define DCRN_MQ0_B2BAS 0x42
44#define DCRN_MQ0_B3BAS 0x43
45
46static u64 ibm440spe_decode_bas(u32 bas)
47{
48 u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
49
50 /* open coded because I'm paranoid about invalid values */
51 switch ((bas >> 4) & 0xFFF) {
52 case 0:
53 return 0;
54 case 0xffc:
55 return base + 0x000800000ull;
56 case 0xff8:
57 return base + 0x001000000ull;
58 case 0xff0:
59 return base + 0x002000000ull;
60 case 0xfe0:
61 return base + 0x004000000ull;
62 case 0xfc0:
63 return base + 0x008000000ull;
64 case 0xf80:
65 return base + 0x010000000ull;
66 case 0xf00:
67 return base + 0x020000000ull;
68 case 0xe00:
69 return base + 0x040000000ull;
70 case 0xc00:
71 return base + 0x080000000ull;
72 case 0x800:
73 return base + 0x100000000ull;
74 }
75 printf("Memory BAS value 0x%08x unsupported !\n", bas);
76 return 0;
77}
78
79void ibm440spe_fixup_memsize(void)
80{
81 u64 banktop, memsize = 0;
82
83 /* Ultimately, we should directly construct the memory node
84 * so we are able to handle holes in the memory address space
85 */
86 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
87 if (banktop > memsize)
88 memsize = banktop;
89 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
90 if (banktop > memsize)
91 memsize = banktop;
92 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
93 if (banktop > memsize)
94 memsize = banktop;
95 banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
96 if (banktop > memsize)
97 memsize = banktop;
98
99 dt_fixup_memory(0, memsize);
100}
101
102
42/* 4xx DDR1/2 Denali memory controller support */ 103/* 4xx DDR1/2 Denali memory controller support */
43/* DDR0 registers */ 104/* DDR0 registers */
44#define DDR0_02 2 105#define DDR0_02 2
@@ -77,19 +138,13 @@ void ibm4xx_fixup_memsize(void)
77 138
78#define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask)) 139#define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
79 140
80static inline u32 mfdcr_sdram0(u32 reg)
81{
82 mtdcr(DCRN_SDRAM0_CFGADDR, reg);
83 return mfdcr(DCRN_SDRAM0_CFGDATA);
84}
85
86void ibm4xx_denali_fixup_memsize(void) 141void ibm4xx_denali_fixup_memsize(void)
87{ 142{
88 u32 val, max_cs, max_col, max_row; 143 u32 val, max_cs, max_col, max_row;
89 u32 cs, col, row, bank, dpath; 144 u32 cs, col, row, bank, dpath;
90 unsigned long memsize; 145 unsigned long memsize;
91 146
92 val = mfdcr_sdram0(DDR0_02); 147 val = SDRAM0_READ(DDR0_02);
93 if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT)) 148 if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
94 fatal("DDR controller is not initialized\n"); 149 fatal("DDR controller is not initialized\n");
95 150
@@ -99,12 +154,12 @@ void ibm4xx_denali_fixup_memsize(void)
99 max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT); 154 max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
100 155
101 /* get CS value */ 156 /* get CS value */
102 val = mfdcr_sdram0(DDR0_10); 157 val = SDRAM0_READ(DDR0_10);
103 158
104 val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT); 159 val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
105 cs = 0; 160 cs = 0;
106 while (val) { 161 while (val) {
107 if (val && 0x1) 162 if (val & 0x1)
108 cs++; 163 cs++;
109 val = val >> 1; 164 val = val >> 1;
110 } 165 }
@@ -115,15 +170,15 @@ void ibm4xx_denali_fixup_memsize(void)
115 fatal("DDR wrong CS configuration\n"); 170 fatal("DDR wrong CS configuration\n");
116 171
117 /* get data path bytes */ 172 /* get data path bytes */
118 val = mfdcr_sdram0(DDR0_14); 173 val = SDRAM0_READ(DDR0_14);
119 174
120 if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT)) 175 if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
121 dpath = 8; /* 64 bits */ 176 dpath = 8; /* 64 bits */
122 else 177 else
123 dpath = 4; /* 32 bits */ 178 dpath = 4; /* 32 bits */
124 179
125 /* get adress pins (rows) */ 180 /* get address pins (rows) */
126 val = mfdcr_sdram0(DDR0_42); 181 val = SDRAM0_READ(DDR0_42);
127 182
128 row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT); 183 row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
129 if (row > max_row) 184 if (row > max_row)
@@ -131,7 +186,7 @@ void ibm4xx_denali_fixup_memsize(void)
131 row = max_row - row; 186 row = max_row - row;
132 187
133 /* get collomn size and banks */ 188 /* get collomn size and banks */
134 val = mfdcr_sdram0(DDR0_43); 189 val = SDRAM0_READ(DDR0_43);
135 190
136 col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT); 191 col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
137 if (col > max_col) 192 if (col > max_col)
@@ -179,13 +234,17 @@ void ibm40x_dbcr_reset(void)
179#define EMAC_RESET 0x20000000 234#define EMAC_RESET 0x20000000
180void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1) 235void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
181{ 236{
182 /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't do this for us */ 237 /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
238 * do this for us
239 */
183 if (emac0) 240 if (emac0)
184 *emac0 = EMAC_RESET; 241 *emac0 = EMAC_RESET;
185 if (emac1) 242 if (emac1)
186 *emac1 = EMAC_RESET; 243 *emac1 = EMAC_RESET;
187 244
188 mtdcr(DCRN_MAL0_CFG, MAL_RESET); 245 mtdcr(DCRN_MAL0_CFG, MAL_RESET);
246 while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
247 ; /* loop until reset takes effect */
189} 248}
190 249
191/* Read 4xx EBC bus bridge registers to get mappings of the peripheral 250/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
@@ -217,84 +276,335 @@ void ibm4xx_fixup_ebc_ranges(const char *ebc)
217 setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32)); 276 setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
218} 277}
219 278
220#define SPRN_CCR1 0x378 279/* Calculate 440GP clocks */
221void ibm440ep_fixup_clocks(unsigned int sysclk, unsigned int ser_clk) 280void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
222{ 281{
223 u32 cpu, plb, opb, ebc, tb, uart0, m, vco; 282 u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
224 u32 reg; 283 u32 cr0 = mfdcr(DCRN_CPC0_CR0);
225 u32 fwdva, fwdvb, fbdv, lfbdv, opbdv0, perdv0, spcid0, prbdv0, tmp; 284 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
226 285 u32 opdv = CPC0_SYS0_OPDV(sys0);
227 mtdcr(DCRN_CPR0_ADDR, CPR0_PLLD0); 286 u32 epdv = CPC0_SYS0_EPDV(sys0);
228 reg = mfdcr(DCRN_CPR0_DATA); 287
229 tmp = (reg & 0x000F0000) >> 16; 288 if (sys0 & CPC0_SYS0_BYPASS) {
230 fwdva = tmp ? tmp : 16; 289 /* Bypass system PLL */
231 tmp = (reg & 0x00000700) >> 8; 290 cpu = plb = sys_clk;
232 fwdvb = tmp ? tmp : 8; 291 } else {
233 tmp = (reg & 0x1F000000) >> 24; 292 if (sys0 & CPC0_SYS0_EXTSL)
234 fbdv = tmp ? tmp : 32; 293 /* PerClk */
235 lfbdv = (reg & 0x0000007F); 294 m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
236
237 mtdcr(DCRN_CPR0_ADDR, CPR0_OPBD0);
238 reg = mfdcr(DCRN_CPR0_DATA);
239 tmp = (reg & 0x03000000) >> 24;
240 opbdv0 = tmp ? tmp : 4;
241
242 mtdcr(DCRN_CPR0_ADDR, CPR0_PERD0);
243 reg = mfdcr(DCRN_CPR0_DATA);
244 tmp = (reg & 0x07000000) >> 24;
245 perdv0 = tmp ? tmp : 8;
246
247 mtdcr(DCRN_CPR0_ADDR, CPR0_PRIMBD0);
248 reg = mfdcr(DCRN_CPR0_DATA);
249 tmp = (reg & 0x07000000) >> 24;
250 prbdv0 = tmp ? tmp : 8;
251
252 mtdcr(DCRN_CPR0_ADDR, CPR0_SCPID);
253 reg = mfdcr(DCRN_CPR0_DATA);
254 tmp = (reg & 0x03000000) >> 24;
255 spcid0 = tmp ? tmp : 4;
256
257 /* Calculate M */
258 mtdcr(DCRN_CPR0_ADDR, CPR0_PLLC0);
259 reg = mfdcr(DCRN_CPR0_DATA);
260 tmp = (reg & 0x03000000) >> 24;
261 if (tmp == 0) { /* PLL output */
262 tmp = (reg & 0x20000000) >> 29;
263 if (!tmp) /* PLLOUTA */
264 m = fbdv * lfbdv * fwdva;
265 else 295 else
266 m = fbdv * lfbdv * fwdvb; 296 /* CPU clock */
297 m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
298 cpu = sys_clk * m / CPC0_SYS0_FWDVA(sys0);
299 plb = sys_clk * m / CPC0_SYS0_FWDVB(sys0);
267 } 300 }
268 else if (tmp == 1) /* CPU output */ 301
269 m = fbdv * fwdva; 302 opb = plb / opdv;
303 ebc = opb / epdv;
304
305 /* FIXME: Check if this is for all 440GP, or just Ebony */
306 if ((mfpvr() & 0xf0000fff) == 0x40000440)
307 /* Rev. B 440GP, use external system clock */
308 tb = sys_clk;
270 else 309 else
271 m = perdv0 * opbdv0 * fwdvb; 310 /* Rev. C 440GP, errata force us to use internal clock */
311 tb = cpu;
272 312
273 vco = (m * sysclk) + (m >> 1); 313 if (cr0 & CPC0_CR0_U0EC)
274 cpu = vco / fwdva; 314 /* External UART clock */
275 plb = vco / fwdvb / prbdv0; 315 uart0 = ser_clk;
276 opb = plb / opbdv0; 316 else
277 ebc = plb / perdv0; 317 /* Internal UART clock */
318 uart0 = plb / CPC0_CR0_UDIV(cr0);
319
320 if (cr0 & CPC0_CR0_U1EC)
321 /* External UART clock */
322 uart1 = ser_clk;
323 else
324 /* Internal UART clock */
325 uart1 = plb / CPC0_CR0_UDIV(cr0);
278 326
279 /* FIXME */ 327 printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
280 uart0 = ser_clk; 328 (sys_clk + 500000) / 1000000, sys_clk);
329
330 dt_fixup_cpu_clocks(cpu, tb, 0);
331
332 dt_fixup_clock("/plb", plb);
333 dt_fixup_clock("/plb/opb", opb);
334 dt_fixup_clock("/plb/opb/ebc", ebc);
335 dt_fixup_clock("/plb/opb/serial@40000200", uart0);
336 dt_fixup_clock("/plb/opb/serial@40000300", uart1);
337}
338
339#define SPRN_CCR1 0x378
340
341static inline u32 __fix_zero(u32 v, u32 def)
342{
343 return v ? v : def;
344}
345
346static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
347 unsigned int tmr_clk,
348 int per_clk_from_opb)
349{
350 /* PLL config */
351 u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
352 u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
353
354 /* Dividers */
355 u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32);
356 u32 fwdva = __fix_zero((plld >> 16) & 0xf, 16);
357 u32 fwdvb = __fix_zero((plld >> 8) & 7, 8);
358 u32 lfbdv = __fix_zero(plld & 0x3f, 64);
359 u32 pradv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMAD) >> 24) & 7, 8);
360 u32 prbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMBD) >> 24) & 7, 8);
361 u32 opbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_OPBD) >> 24) & 3, 4);
362 u32 perdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PERD) >> 24) & 3, 4);
363
364 /* Input clocks for primary dividers */
365 u32 clk_a, clk_b;
366
367 /* Resulting clocks */
368 u32 cpu, plb, opb, ebc, vco;
369
370 /* Timebase */
371 u32 ccr1, tb = tmr_clk;
372
373 if (pllc & 0x40000000) {
374 u32 m;
375
376 /* Feedback path */
377 switch ((pllc >> 24) & 7) {
378 case 0:
379 /* PLLOUTx */
380 m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
381 break;
382 case 1:
383 /* CPU */
384 m = fwdva * pradv0;
385 break;
386 case 5:
387 /* PERClk */
388 m = fwdvb * prbdv0 * opbdv0 * perdv0;
389 break;
390 default:
391 printf("WARNING ! Invalid PLL feedback source !\n");
392 goto bypass;
393 }
394 m *= fbdv;
395 vco = sys_clk * m;
396 clk_a = vco / fwdva;
397 clk_b = vco / fwdvb;
398 } else {
399bypass:
400 /* Bypass system PLL */
401 vco = 0;
402 clk_a = clk_b = sys_clk;
403 }
404
405 cpu = clk_a / pradv0;
406 plb = clk_b / prbdv0;
407 opb = plb / opbdv0;
408 ebc = (per_clk_from_opb ? opb : plb) / perdv0;
281 409
282 /* Figure out timebase. Either CPU or default TmrClk */ 410 /* Figure out timebase. Either CPU or default TmrClk */
283 asm volatile ( 411 ccr1 = mfspr(SPRN_CCR1);
284 "mfspr %0,%1\n" 412
285 : 413 /* If passed a 0 tmr_clk, force CPU clock */
286 "=&r"(reg) : "i"(SPRN_CCR1)); 414 if (tb == 0) {
287 if (reg & 0x0080) 415 ccr1 &= ~0x80u;
288 tb = 25000000; /* TmrClk is 25MHz */ 416 mtspr(SPRN_CCR1, ccr1);
289 else 417 }
418 if ((ccr1 & 0x0080) == 0)
290 tb = cpu; 419 tb = cpu;
291 420
292 dt_fixup_cpu_clocks(cpu, tb, 0); 421 dt_fixup_cpu_clocks(cpu, tb, 0);
293 dt_fixup_clock("/plb", plb); 422 dt_fixup_clock("/plb", plb);
294 dt_fixup_clock("/plb/opb", opb); 423 dt_fixup_clock("/plb/opb", opb);
295 dt_fixup_clock("/plb/opb/ebc", ebc); 424 dt_fixup_clock("/plb/opb/ebc", ebc);
425
426 return plb;
427}
428
429static void eplike_fixup_uart_clk(int index, const char *path,
430 unsigned int ser_clk,
431 unsigned int plb_clk)
432{
433 unsigned int sdr;
434 unsigned int clock;
435
436 switch (index) {
437 case 0:
438 sdr = SDR0_READ(DCRN_SDR0_UART0);
439 break;
440 case 1:
441 sdr = SDR0_READ(DCRN_SDR0_UART1);
442 break;
443 case 2:
444 sdr = SDR0_READ(DCRN_SDR0_UART2);
445 break;
446 case 3:
447 sdr = SDR0_READ(DCRN_SDR0_UART3);
448 break;
449 default:
450 return;
451 }
452
453 if (sdr & 0x00800000u)
454 clock = ser_clk;
455 else
456 clock = plb_clk / __fix_zero(sdr & 0xff, 256);
457
458 dt_fixup_clock(path, clock);
459}
460
461void ibm440ep_fixup_clocks(unsigned int sys_clk,
462 unsigned int ser_clk,
463 unsigned int tmr_clk)
464{
465 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
466
467 /* serial clocks beed fixup based on int/ext */
468 eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
469 eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
470 eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
471 eplike_fixup_uart_clk(3, "/plb/opb/serial@ef600600", ser_clk, plb_clk);
472}
473
474void ibm440gx_fixup_clocks(unsigned int sys_clk,
475 unsigned int ser_clk,
476 unsigned int tmr_clk)
477{
478 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
479
480 /* serial clocks beed fixup based on int/ext */
481 eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
482 eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
483}
484
485void ibm440spe_fixup_clocks(unsigned int sys_clk,
486 unsigned int ser_clk,
487 unsigned int tmr_clk)
488{
489 unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
490
491 /* serial clocks beed fixup based on int/ext */
492 eplike_fixup_uart_clk(0, "/plb/opb/serial@10000200", ser_clk, plb_clk);
493 eplike_fixup_uart_clk(1, "/plb/opb/serial@10000300", ser_clk, plb_clk);
494 eplike_fixup_uart_clk(2, "/plb/opb/serial@10000600", ser_clk, plb_clk);
495}
496
497void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
498{
499 u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
500 u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
501 u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
502 u32 psr = mfdcr(DCRN_405_CPC0_PSR);
503 u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
504 u32 fwdv, fwdvb, fbdv, cbdv, opdv, epdv, ppdv, udiv;
505
506 fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
507 fbdv = (pllmr & 0x1e000000) >> 25;
508 if (fbdv == 0)
509 fbdv = 16;
510 cbdv = ((pllmr & 0x00060000) >> 17) + 1; /* CPU:PLB */
511 opdv = ((pllmr & 0x00018000) >> 15) + 1; /* PLB:OPB */
512 ppdv = ((pllmr & 0x00001800) >> 13) + 1; /* PLB:PCI */
513 epdv = ((pllmr & 0x00001800) >> 11) + 2; /* PLB:EBC */
514 udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
515
516 /* check for 405GPr */
517 if ((mfpvr() & 0xfffffff0) == (0x50910951 & 0xfffffff0)) {
518 fwdvb = 8 - (pllmr & 0x00000007);
519 if (!(psr & 0x00001000)) /* PCI async mode enable == 0 */
520 if (psr & 0x00000020) /* New mode enable */
521 m = fwdvb * 2 * ppdv;
522 else
523 m = fwdvb * cbdv * ppdv;
524 else if (psr & 0x00000020) /* New mode enable */
525 if (psr & 0x00000800) /* PerClk synch mode */
526 m = fwdvb * 2 * epdv;
527 else
528 m = fbdv * fwdv;
529 else if (epdv == fbdv)
530 m = fbdv * cbdv * epdv;
531 else
532 m = fbdv * fwdvb * cbdv;
533
534 cpu = sys_clk * m / fwdv;
535 plb = sys_clk * m / (fwdvb * cbdv);
536 } else {
537 m = fwdv * fbdv * cbdv;
538 cpu = sys_clk * m / fwdv;
539 plb = cpu / cbdv;
540 }
541 opb = plb / opdv;
542 ebc = plb / epdv;
543
544 if (cpc0_cr0 & 0x80)
545 /* uart0 uses the external clock */
546 uart0 = ser_clk;
547 else
548 uart0 = cpu / udiv;
549
550 if (cpc0_cr0 & 0x40)
551 /* uart1 uses the external clock */
552 uart1 = ser_clk;
553 else
554 uart1 = cpu / udiv;
555
556 /* setup the timebase clock to tick at the cpu frequency */
557 cpc0_cr1 = cpc0_cr1 & ~0x00800000;
558 mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
559 tb = cpu;
560
561 dt_fixup_cpu_clocks(cpu, tb, 0);
562 dt_fixup_clock("/plb", plb);
563 dt_fixup_clock("/plb/opb", opb);
564 dt_fixup_clock("/plb/ebc", ebc);
565 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
566 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
567}
568
569
570void ibm405ep_fixup_clocks(unsigned int sys_clk)
571{
572 u32 pllmr0 = mfdcr(DCRN_CPC0_PLLMR0);
573 u32 pllmr1 = mfdcr(DCRN_CPC0_PLLMR1);
574 u32 cpc0_ucr = mfdcr(DCRN_CPC0_UCR);
575 u32 cpu, plb, opb, ebc, uart0, uart1;
576 u32 fwdva, fwdvb, fbdv, cbdv, opdv, epdv;
577 u32 pllmr0_ccdv, tb, m;
578
579 fwdva = 8 - ((pllmr1 & 0x00070000) >> 16);
580 fwdvb = 8 - ((pllmr1 & 0x00007000) >> 12);
581 fbdv = (pllmr1 & 0x00f00000) >> 20;
582 if (fbdv == 0)
583 fbdv = 16;
584
585 cbdv = ((pllmr0 & 0x00030000) >> 16) + 1; /* CPU:PLB */
586 epdv = ((pllmr0 & 0x00000300) >> 8) + 2; /* PLB:EBC */
587 opdv = ((pllmr0 & 0x00003000) >> 12) + 1; /* PLB:OPB */
588
589 m = fbdv * fwdvb;
590
591 pllmr0_ccdv = ((pllmr0 & 0x00300000) >> 20) + 1;
592 if (pllmr1 & 0x80000000)
593 cpu = sys_clk * m / (fwdva * pllmr0_ccdv);
594 else
595 cpu = sys_clk / pllmr0_ccdv;
596
597 plb = cpu / cbdv;
598 opb = plb / opdv;
599 ebc = plb / epdv;
600 tb = cpu;
601 uart0 = cpu / (cpc0_ucr & 0x0000007f);
602 uart1 = cpu / ((cpc0_ucr & 0x00007f00) >> 8);
603
604 dt_fixup_cpu_clocks(cpu, tb, 0);
605 dt_fixup_clock("/plb", plb);
606 dt_fixup_clock("/plb/opb", opb);
607 dt_fixup_clock("/plb/ebc", ebc);
296 dt_fixup_clock("/plb/opb/serial@ef600300", uart0); 608 dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
297 dt_fixup_clock("/plb/opb/serial@ef600400", uart0); 609 dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
298 dt_fixup_clock("/plb/opb/serial@ef600500", uart0);
299 dt_fixup_clock("/plb/opb/serial@ef600600", uart0);
300} 610}