xref: /openbmc/linux/arch/m68k/coldfire/m53xx.c (revision 9dbbc3b9)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /***************************************************************************/
3 
4 /*
5  *	m53xx.c -- platform support for ColdFire 53xx based boards
6  *
7  *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
8  *	Copyright (C) 2000, Lineo (www.lineo.com)
9  *	Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
10  *	Copyright Freescale Semiconductor, Inc 2006
11  *	Copyright (c) 2006, emlix, Sebastian Hess <shess@hessware.de>
12  */
13 
14 /***************************************************************************/
15 
16 #include <linux/clkdev.h>
17 #include <linux/kernel.h>
18 #include <linux/param.h>
19 #include <linux/init.h>
20 #include <linux/io.h>
21 #include <asm/machdep.h>
22 #include <asm/coldfire.h>
23 #include <asm/mcfsim.h>
24 #include <asm/mcfuart.h>
25 #include <asm/mcfdma.h>
26 #include <asm/mcfwdebug.h>
27 #include <asm/mcfclk.h>
28 
29 /***************************************************************************/
30 
31 DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
32 DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
33 DEFINE_CLK(0, "fec.0", 12, MCF_CLK);
34 DEFINE_CLK(0, "edma", 17, MCF_CLK);
35 DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
36 DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
37 DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
38 DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
39 DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
40 DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
41 DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
42 DEFINE_CLK(0, "mcfuart.2", 26, MCF_BUSCLK);
43 DEFINE_CLK(0, "mcftmr.0", 28, MCF_CLK);
44 DEFINE_CLK(0, "mcftmr.1", 29, MCF_CLK);
45 DEFINE_CLK(0, "mcftmr.2", 30, MCF_CLK);
46 DEFINE_CLK(0, "mcftmr.3", 31, MCF_CLK);
47 
48 DEFINE_CLK(0, "mcfpit.0", 32, MCF_CLK);
49 DEFINE_CLK(0, "mcfpit.1", 33, MCF_CLK);
50 DEFINE_CLK(0, "mcfpit.2", 34, MCF_CLK);
51 DEFINE_CLK(0, "mcfpit.3", 35, MCF_CLK);
52 DEFINE_CLK(0, "mcfpwm.0", 36, MCF_CLK);
53 DEFINE_CLK(0, "mcfeport.0", 37, MCF_CLK);
54 DEFINE_CLK(0, "mcfwdt.0", 38, MCF_CLK);
55 DEFINE_CLK(0, "sys.0", 40, MCF_BUSCLK);
56 DEFINE_CLK(0, "gpio.0", 41, MCF_BUSCLK);
57 DEFINE_CLK(0, "mcfrtc.0", 42, MCF_CLK);
58 DEFINE_CLK(0, "mcflcd.0", 43, MCF_CLK);
59 DEFINE_CLK(0, "mcfusb-otg.0", 44, MCF_CLK);
60 DEFINE_CLK(0, "mcfusb-host.0", 45, MCF_CLK);
61 DEFINE_CLK(0, "sdram.0", 46, MCF_CLK);
62 DEFINE_CLK(0, "ssi.0", 47, MCF_CLK);
63 DEFINE_CLK(0, "pll.0", 48, MCF_CLK);
64 
65 DEFINE_CLK(1, "mdha.0", 32, MCF_CLK);
66 DEFINE_CLK(1, "skha.0", 33, MCF_CLK);
67 DEFINE_CLK(1, "rng.0", 34, MCF_CLK);
68 
69 static struct clk_lookup m53xx_clk_lookup[] = {
70 	CLKDEV_INIT("flexbus", NULL, &__clk_0_2),
71 	CLKDEV_INIT("mcfcan.0", NULL, &__clk_0_8),
72 	CLKDEV_INIT("fec.0", NULL, &__clk_0_12),
73 	CLKDEV_INIT("edma", NULL, &__clk_0_17),
74 	CLKDEV_INIT("intc.0", NULL, &__clk_0_18),
75 	CLKDEV_INIT("intc.1", NULL, &__clk_0_19),
76 	CLKDEV_INIT("iack.0", NULL, &__clk_0_21),
77 	CLKDEV_INIT("imx1-i2c.0", NULL, &__clk_0_22),
78 	CLKDEV_INIT("mcfqspi.0", NULL, &__clk_0_23),
79 	CLKDEV_INIT("mcfuart.0", NULL, &__clk_0_24),
80 	CLKDEV_INIT("mcfuart.1", NULL, &__clk_0_25),
81 	CLKDEV_INIT("mcfuart.2", NULL, &__clk_0_26),
82 	CLKDEV_INIT("mcftmr.0", NULL, &__clk_0_28),
83 	CLKDEV_INIT("mcftmr.1", NULL, &__clk_0_29),
84 	CLKDEV_INIT("mcftmr.2", NULL, &__clk_0_30),
85 	CLKDEV_INIT("mcftmr.3", NULL, &__clk_0_31),
86 	CLKDEV_INIT("mcfpit.0", NULL, &__clk_0_32),
87 	CLKDEV_INIT("mcfpit.1", NULL, &__clk_0_33),
88 	CLKDEV_INIT("mcfpit.2", NULL, &__clk_0_34),
89 	CLKDEV_INIT("mcfpit.3", NULL, &__clk_0_35),
90 	CLKDEV_INIT("mcfpwm.0", NULL, &__clk_0_36),
91 	CLKDEV_INIT("mcfeport.0", NULL, &__clk_0_37),
92 	CLKDEV_INIT("mcfwdt.0", NULL, &__clk_0_38),
93 	CLKDEV_INIT(NULL, "sys.0", &__clk_0_40),
94 	CLKDEV_INIT("gpio.0", NULL, &__clk_0_41),
95 	CLKDEV_INIT("mcfrtc.0", NULL, &__clk_0_42),
96 	CLKDEV_INIT("mcflcd.0", NULL, &__clk_0_43),
97 	CLKDEV_INIT("mcfusb-otg.0", NULL, &__clk_0_44),
98 	CLKDEV_INIT("mcfusb-host.0", NULL, &__clk_0_45),
99 	CLKDEV_INIT("sdram.0", NULL, &__clk_0_46),
100 	CLKDEV_INIT("ssi.0", NULL, &__clk_0_47),
101 	CLKDEV_INIT(NULL, "pll.0", &__clk_0_48),
102 	CLKDEV_INIT("mdha.0", NULL, &__clk_1_32),
103 	CLKDEV_INIT("skha.0", NULL, &__clk_1_33),
104 	CLKDEV_INIT("rng.0", NULL, &__clk_1_34),
105 };
106 
107 static struct clk * const enable_clks[] __initconst = {
108 	&__clk_0_2,	/* flexbus */
109 	&__clk_0_18,	/* intc.0 */
110 	&__clk_0_19,	/* intc.1 */
111 	&__clk_0_21,	/* iack.0 */
112 	&__clk_0_24,	/* mcfuart.0 */
113 	&__clk_0_25,	/* mcfuart.1 */
114 	&__clk_0_26,	/* mcfuart.2 */
115 	&__clk_0_28,	/* mcftmr.0 */
116 	&__clk_0_29,	/* mcftmr.1 */
117 	&__clk_0_32,	/* mcfpit.0 */
118 	&__clk_0_33,	/* mcfpit.1 */
119 	&__clk_0_37,	/* mcfeport.0 */
120 	&__clk_0_40,	/* sys.0 */
121 	&__clk_0_41,	/* gpio.0 */
122 	&__clk_0_46,	/* sdram.0 */
123 	&__clk_0_48,	/* pll.0 */
124 };
125 
126 static struct clk * const disable_clks[] __initconst = {
127 	&__clk_0_8,	/* mcfcan.0 */
128 	&__clk_0_12,	/* fec.0 */
129 	&__clk_0_17,	/* edma */
130 	&__clk_0_22,	/* imx1-i2c.0 */
131 	&__clk_0_23,	/* mcfqspi.0 */
132 	&__clk_0_30,	/* mcftmr.2 */
133 	&__clk_0_31,	/* mcftmr.3 */
134 	&__clk_0_34,	/* mcfpit.2 */
135 	&__clk_0_35,	/* mcfpit.3 */
136 	&__clk_0_36,	/* mcfpwm.0 */
137 	&__clk_0_38,	/* mcfwdt.0 */
138 	&__clk_0_42,	/* mcfrtc.0 */
139 	&__clk_0_43,	/* mcflcd.0 */
140 	&__clk_0_44,	/* mcfusb-otg.0 */
141 	&__clk_0_45,	/* mcfusb-host.0 */
142 	&__clk_0_47,	/* ssi.0 */
143 	&__clk_1_32,	/* mdha.0 */
144 	&__clk_1_33,	/* skha.0 */
145 	&__clk_1_34,	/* rng.0 */
146 };
147 
148 
149 static void __init m53xx_clk_init(void)
150 {
151 	unsigned i;
152 
153 	/* make sure these clocks are enabled */
154 	for (i = 0; i < ARRAY_SIZE(enable_clks); ++i)
155 		__clk_init_enabled(enable_clks[i]);
156 	/* make sure these clocks are disabled */
157 	for (i = 0; i < ARRAY_SIZE(disable_clks); ++i)
158 		__clk_init_disabled(disable_clks[i]);
159 
160 	clkdev_add_table(m53xx_clk_lookup, ARRAY_SIZE(m53xx_clk_lookup));
161 }
162 
163 /***************************************************************************/
164 
165 static void __init m53xx_qspi_init(void)
166 {
167 #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
168 	/* setup QSPS pins for QSPI with gpio CS control */
169 	writew(0x01f0, MCFGPIO_PAR_QSPI);
170 #endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
171 }
172 
173 /***************************************************************************/
174 
175 static void __init m53xx_i2c_init(void)
176 {
177 #if IS_ENABLED(CONFIG_I2C_IMX)
178 	/* setup Port AS Pin Assignment Register for I2C */
179 	/*  set PASPA0 to SCL and PASPA1 to SDA */
180 	u8 r = readb(MCFGPIO_PAR_FECI2C);
181 	r |= 0x0f;
182 	writeb(r, MCFGPIO_PAR_FECI2C);
183 #endif /* IS_ENABLED(CONFIG_I2C_IMX) */
184 }
185 
186 /***************************************************************************/
187 
188 static void __init m53xx_uarts_init(void)
189 {
190 	/* UART GPIO initialization */
191 	writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART);
192 }
193 
194 /***************************************************************************/
195 
196 static void __init m53xx_fec_init(void)
197 {
198 	u8 v;
199 
200 	/* Set multi-function pins to ethernet mode for fec0 */
201 	v = readb(MCFGPIO_PAR_FECI2C);
202 	v |= MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
203 		MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO;
204 	writeb(v, MCFGPIO_PAR_FECI2C);
205 
206 	v = readb(MCFGPIO_PAR_FEC);
207 	v = MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC;
208 	writeb(v, MCFGPIO_PAR_FEC);
209 }
210 
211 /***************************************************************************/
212 
213 void __init config_BSP(char *commandp, int size)
214 {
215 #if !defined(CONFIG_BOOTPARAM)
216 	/* Copy command line from FLASH to local buffer... */
217 	memcpy(commandp, (char *) 0x4000, 4);
218 	if(strncmp(commandp, "kcl ", 4) == 0){
219 		memcpy(commandp, (char *) 0x4004, size);
220 		commandp[size-1] = 0;
221 	} else {
222 		memset(commandp, 0, size);
223 	}
224 #endif
225 	mach_sched_init = hw_timer_init;
226 	m53xx_clk_init();
227 	m53xx_uarts_init();
228 	m53xx_fec_init();
229 	m53xx_qspi_init();
230 	m53xx_i2c_init();
231 
232 #ifdef CONFIG_BDM_DISABLE
233 	/*
234 	 * Disable the BDM clocking.  This also turns off most of the rest of
235 	 * the BDM device.  This is good for EMC reasons. This option is not
236 	 * incompatible with the memory protection option.
237 	 */
238 	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
239 #endif
240 }
241 
242 /***************************************************************************/
243 /* Board initialization */
244 /***************************************************************************/
245 /*
246  * PLL min/max specifications
247  */
248 #define MAX_FVCO	500000	/* KHz */
249 #define MAX_FSYS	80000 	/* KHz */
250 #define MIN_FSYS	58333 	/* KHz */
251 #define FREF		16000   /* KHz */
252 
253 
254 #define MAX_MFD		135     /* Multiplier */
255 #define MIN_MFD		88      /* Multiplier */
256 #define BUSDIV		6       /* Divider */
257 
258 /*
259  * Low Power Divider specifications
260  */
261 #define MIN_LPD		(1 << 0)    /* Divider (not encoded) */
262 #define MAX_LPD		(1 << 15)   /* Divider (not encoded) */
263 #define DEFAULT_LPD	(1 << 1)	/* Divider (not encoded) */
264 
265 #define SYS_CLK_KHZ	80000
266 #define SYSTEM_PERIOD	12.5
267 /*
268  *  SDRAM Timing Parameters
269  */
270 #define SDRAM_BL	8	/* # of beats in a burst */
271 #define SDRAM_TWR	2	/* in clocks */
272 #define SDRAM_CASL	2.5	/* CASL in clocks */
273 #define SDRAM_TRCD	2	/* in clocks */
274 #define SDRAM_TRP	2	/* in clocks */
275 #define SDRAM_TRFC	7	/* in clocks */
276 #define SDRAM_TREFI	7800	/* in ns */
277 
278 #define EXT_SRAM_ADDRESS	(0xC0000000)
279 #define FLASH_ADDRESS		(0x00000000)
280 #define SDRAM_ADDRESS		(0x40000000)
281 
282 #define NAND_FLASH_ADDRESS	(0xD0000000)
283 
284 void wtm_init(void);
285 void scm_init(void);
286 void gpio_init(void);
287 void fbcs_init(void);
288 void sdramc_init(void);
289 int  clock_pll (int fsys, int flags);
290 int  clock_limp (int);
291 int  clock_exit_limp (void);
292 int  get_sys_clock (void);
293 
294 asmlinkage void __init sysinit(void)
295 {
296 	clock_pll(0, 0);
297 
298 	wtm_init();
299 	scm_init();
300 	gpio_init();
301 	fbcs_init();
302 	sdramc_init();
303 }
304 
305 void wtm_init(void)
306 {
307 	/* Disable watchdog timer */
308 	writew(0, MCF_WTM_WCR);
309 }
310 
311 #define MCF_SCM_BCR_GBW		(0x00000100)
312 #define MCF_SCM_BCR_GBR		(0x00000200)
313 
314 void scm_init(void)
315 {
316 	/* All masters are trusted */
317 	writel(0x77777777, MCF_SCM_MPR);
318 
319 	/* Allow supervisor/user, read/write, and trusted/untrusted
320 	   access to all slaves */
321 	writel(0, MCF_SCM_PACRA);
322 	writel(0, MCF_SCM_PACRB);
323 	writel(0, MCF_SCM_PACRC);
324 	writel(0, MCF_SCM_PACRD);
325 	writel(0, MCF_SCM_PACRE);
326 	writel(0, MCF_SCM_PACRF);
327 
328 	/* Enable bursts */
329 	writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR);
330 }
331 
332 
333 void fbcs_init(void)
334 {
335 	writeb(0x3E, MCFGPIO_PAR_CS);
336 
337 	/* Latch chip select */
338 	writel(0x10080000, MCF_FBCS1_CSAR);
339 
340 	writel(0x002A3780, MCF_FBCS1_CSCR);
341 	writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
342 
343 	/* Initialize latch to drive signals to inactive states */
344 	writew(0xffff, 0x10080000);
345 
346 	/* External SRAM */
347 	writel(EXT_SRAM_ADDRESS, MCF_FBCS1_CSAR);
348 	writel(MCF_FBCS_CSCR_PS_16 |
349 		MCF_FBCS_CSCR_AA |
350 		MCF_FBCS_CSCR_SBM |
351 		MCF_FBCS_CSCR_WS(1),
352 		MCF_FBCS1_CSCR);
353 	writel(MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
354 
355 	/* Boot Flash connected to FBCS0 */
356 	writel(FLASH_ADDRESS, MCF_FBCS0_CSAR);
357 	writel(MCF_FBCS_CSCR_PS_16 |
358 		MCF_FBCS_CSCR_BEM |
359 		MCF_FBCS_CSCR_AA |
360 		MCF_FBCS_CSCR_SBM |
361 		MCF_FBCS_CSCR_WS(7),
362 		MCF_FBCS0_CSCR);
363 	writel(MCF_FBCS_CSMR_BAM_32M | MCF_FBCS_CSMR_V, MCF_FBCS0_CSMR);
364 }
365 
366 void sdramc_init(void)
367 {
368 	/*
369 	 * Check to see if the SDRAM has already been initialized
370 	 * by a run control tool
371 	 */
372 	if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) {
373 		/* SDRAM chip select initialization */
374 
375 		/* Initialize SDRAM chip select */
376 		writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) |
377 			MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE),
378 			MCF_SDRAMC_SDCS0);
379 
380 	/*
381 	 * Basic configuration and initialization
382 	 */
383 	writel(MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5)) |
384 		MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) |
385 		MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL * 2) + 2)) |
386 		MCF_SDRAMC_SDCFG1_ACT2RW((int)(SDRAM_TRCD + 0.5)) |
387 		MCF_SDRAMC_SDCFG1_PRE2ACT((int)(SDRAM_TRP + 0.5)) |
388 		MCF_SDRAMC_SDCFG1_REF2ACT((int)(SDRAM_TRFC + 0.5)) |
389 		MCF_SDRAMC_SDCFG1_WTLAT(3),
390 		MCF_SDRAMC_SDCFG1);
391 	writel(MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL / 2 + 1) |
392 		MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL / 2 + SDRAM_TWR) |
393 		MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL + SDRAM_BL / 2 - 1.0) + 0.5)) |
394 		MCF_SDRAMC_SDCFG2_BL(SDRAM_BL - 1),
395 		MCF_SDRAMC_SDCFG2);
396 
397 
398 	/*
399 	 * Precharge and enable write to SDMR
400 	 */
401 	writel(MCF_SDRAMC_SDCR_MODE_EN |
402 		MCF_SDRAMC_SDCR_CKE |
403 		MCF_SDRAMC_SDCR_DDR |
404 		MCF_SDRAMC_SDCR_MUX(1) |
405 		MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI / (SYSTEM_PERIOD * 64)) - 1) + 0.5)) |
406 		MCF_SDRAMC_SDCR_PS_16 |
407 		MCF_SDRAMC_SDCR_IPALL,
408 		MCF_SDRAMC_SDCR);
409 
410 	/*
411 	 * Write extended mode register
412 	 */
413 	writel(MCF_SDRAMC_SDMR_BNKAD_LEMR |
414 		MCF_SDRAMC_SDMR_AD(0x0) |
415 		MCF_SDRAMC_SDMR_CMD,
416 		MCF_SDRAMC_SDMR);
417 
418 	/*
419 	 * Write mode register and reset DLL
420 	 */
421 	writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
422 		MCF_SDRAMC_SDMR_AD(0x163) |
423 		MCF_SDRAMC_SDMR_CMD,
424 		MCF_SDRAMC_SDMR);
425 
426 	/*
427 	 * Execute a PALL command
428 	 */
429 	writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR);
430 
431 	/*
432 	 * Perform two REF cycles
433 	 */
434 	writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
435 	writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
436 
437 	/*
438 	 * Write mode register and clear reset DLL
439 	 */
440 	writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
441 		MCF_SDRAMC_SDMR_AD(0x063) |
442 		MCF_SDRAMC_SDMR_CMD,
443 		MCF_SDRAMC_SDMR);
444 
445 	/*
446 	 * Enable auto refresh and lock SDMR
447 	 */
448 	writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_MODE_EN,
449 		MCF_SDRAMC_SDCR);
450 	writel(MCF_SDRAMC_SDCR_REF | MCF_SDRAMC_SDCR_DQS_OE(0xC),
451 		MCF_SDRAMC_SDCR);
452 	}
453 }
454 
455 void gpio_init(void)
456 {
457 	/* Enable UART0 pins */
458 	writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0,
459 		MCFGPIO_PAR_UART);
460 
461 	/*
462 	 * Initialize TIN3 as a GPIO output to enable the write
463 	 * half of the latch.
464 	 */
465 	writeb(0x00, MCFGPIO_PAR_TIMER);
466 	writeb(0x08, MCFGPIO_PDDR_TIMER);
467 	writeb(0x00, MCFGPIO_PCLRR_TIMER);
468 }
469 
470 int clock_pll(int fsys, int flags)
471 {
472 	int fref, temp, fout, mfd;
473 	u32 i;
474 
475 	fref = FREF;
476 
477 	if (fsys == 0) {
478 		/* Return current PLL output */
479 		mfd = readb(MCF_PLL_PFDR);
480 
481 		return (fref * mfd / (BUSDIV * 4));
482 	}
483 
484 	/* Check bounds of requested system clock */
485 	if (fsys > MAX_FSYS)
486 		fsys = MAX_FSYS;
487 	if (fsys < MIN_FSYS)
488 		fsys = MIN_FSYS;
489 
490 	/* Multiplying by 100 when calculating the temp value,
491 	   and then dividing by 100 to calculate the mfd allows
492 	   for exact values without needing to include floating
493 	   point libraries. */
494 	temp = 100 * fsys / fref;
495 	mfd = 4 * BUSDIV * temp / 100;
496 
497 	/* Determine the output frequency for selected values */
498 	fout = (fref * mfd / (BUSDIV * 4));
499 
500 	/*
501 	 * Check to see if the SDRAM has already been initialized.
502 	 * If it has then the SDRAM needs to be put into self refresh
503 	 * mode before reprogramming the PLL.
504 	 */
505 	if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
506 		/* Put SDRAM into self refresh mode */
507 		writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE,
508 			MCF_SDRAMC_SDCR);
509 
510 	/*
511 	 * Initialize the PLL to generate the new system clock frequency.
512 	 * The device must be put into LIMP mode to reprogram the PLL.
513 	 */
514 
515 	/* Enter LIMP mode */
516 	clock_limp(DEFAULT_LPD);
517 
518 	/* Reprogram PLL for desired fsys */
519 	writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV),
520 		MCF_PLL_PODR);
521 
522 	writeb(mfd, MCF_PLL_PFDR);
523 
524 	/* Exit LIMP mode */
525 	clock_exit_limp();
526 
527 	/*
528 	 * Return the SDRAM to normal operation if it is in use.
529 	 */
530 	if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
531 		/* Exit self refresh mode */
532 		writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE,
533 			MCF_SDRAMC_SDCR);
534 
535 	/* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
536 	writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX);
537 
538 	/* wait for DQS logic to relock */
539 	for (i = 0; i < 0x200; i++)
540 		;
541 
542 	return fout;
543 }
544 
545 int clock_limp(int div)
546 {
547 	u32 temp;
548 
549 	/* Check bounds of divider */
550 	if (div < MIN_LPD)
551 		div = MIN_LPD;
552 	if (div > MAX_LPD)
553 		div = MAX_LPD;
554 
555 	/* Save of the current value of the SSIDIV so we don't
556 	   overwrite the value*/
557 	temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF);
558 
559 	/* Apply the divider to the system clock */
560 	writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR);
561 
562 	writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
563 
564 	return (FREF/(3*(1 << div)));
565 }
566 
567 int clock_exit_limp(void)
568 {
569 	int fout;
570 
571 	/* Exit LIMP mode */
572 	writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
573 
574 	/* Wait for PLL to lock */
575 	while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK))
576 		;
577 
578 	fout = get_sys_clock();
579 
580 	return fout;
581 }
582 
583 int get_sys_clock(void)
584 {
585 	int divider;
586 
587 	/* Test to see if device is in LIMP mode */
588 	if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) {
589 		divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF);
590 		return (FREF/(2 << divider));
591 	}
592 	else
593 		return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4);
594 }
595