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}
800