Linux Audio

Check our new training course

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