xref: /openbmc/linux/arch/powerpc/boot/4xx.c (revision 5a244f48)
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 
28 static 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. */
48 void 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 
70 static 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 
103 void 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  */
172 static 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 
191 read_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 
205 void 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 
264 void 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 
277 void 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
290 void 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 */
307 void 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 */
335 void 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 
396 static inline u32 __fix_zero(u32 v, u32 def)
397 {
398 	return v ? v : def;
399 }
400 
401 static 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 {
454 bypass:
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 
484 static 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 
516 void 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 
529 void 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 
540 void 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 
552 void 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 & 0x00006000) >> 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 
625 void 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 
667 static 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 
673 u32 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 
684 static 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 
716 u32 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 
727 void 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 {
780 bypass:
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 }
804