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