xref: /linux/arch/powerpc/boot/4xx.c (revision 08f3e0873ac203449465c2b8473d684e2f9f41d1)
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 
24 static 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. */
44 void 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 
66 static 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 
99 void 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  */
168 static 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 
187 read_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 
201 void 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 
260 void 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 
273 void 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
286 void 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 */
303 void 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 */
331 void 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 
392 static inline u32 __fix_zero(u32 v, u32 def)
393 {
394 	return v ? v : def;
395 }
396 
397 static 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 {
450 bypass:
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 
480 static 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 
512 void 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 
525 void 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 
536 void 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 
548 void 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 
621 void 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 
663 static 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 
669 u32 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 
680 static 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 
712 u32 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 
723 void 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 {
776 bypass:
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 }
800