xref: /linux/arch/powerpc/boot/4xx.c (revision 15a1fbdcfb519c2bd291ed01c6c94e0b89537a77)
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