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