1 /***************************************************************************/
2 
3 /*
4  *	linux/arch/m68knommu/platform/532x/config.c
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 <sh@emlix.com>
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 <linux/spi/spi.h>
25 #include <linux/gpio.h>
26 #include <asm/machdep.h>
27 #include <asm/coldfire.h>
28 #include <asm/mcfsim.h>
29 #include <asm/mcfuart.h>
30 #include <asm/mcfdma.h>
31 #include <asm/mcfwdebug.h>
32 #include <asm/mcfqspi.h>
33 
34 /***************************************************************************/
35 
36 static struct mcf_platform_uart m532x_uart_platform[] = {
37 	{
38 		.mapbase	= MCFUART_BASE1,
39 		.irq		= MCFINT_VECBASE + MCFINT_UART0,
40 	},
41 	{
42 		.mapbase 	= MCFUART_BASE2,
43 		.irq		= MCFINT_VECBASE + MCFINT_UART1,
44 	},
45 	{
46 		.mapbase 	= MCFUART_BASE3,
47 		.irq		= MCFINT_VECBASE + MCFINT_UART2,
48 	},
49 	{ },
50 };
51 
52 static struct platform_device m532x_uart = {
53 	.name			= "mcfuart",
54 	.id			= 0,
55 	.dev.platform_data	= m532x_uart_platform,
56 };
57 
58 static struct resource m532x_fec_resources[] = {
59 	{
60 		.start		= 0xfc030000,
61 		.end		= 0xfc0307ff,
62 		.flags		= IORESOURCE_MEM,
63 	},
64 	{
65 		.start		= 64 + 36,
66 		.end		= 64 + 36,
67 		.flags		= IORESOURCE_IRQ,
68 	},
69 	{
70 		.start		= 64 + 40,
71 		.end		= 64 + 40,
72 		.flags		= IORESOURCE_IRQ,
73 	},
74 	{
75 		.start		= 64 + 42,
76 		.end		= 64 + 42,
77 		.flags		= IORESOURCE_IRQ,
78 	},
79 };
80 
81 static struct platform_device m532x_fec = {
82 	.name			= "fec",
83 	.id			= 0,
84 	.num_resources		= ARRAY_SIZE(m532x_fec_resources),
85 	.resource		= m532x_fec_resources,
86 };
87 
88 #if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
89 static struct resource m532x_qspi_resources[] = {
90 	{
91 		.start		= MCFQSPI_IOBASE,
92 		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
93 		.flags		= IORESOURCE_MEM,
94 	},
95 	{
96 		.start		= MCFINT_VECBASE + MCFINT_QSPI,
97 		.end		= MCFINT_VECBASE + MCFINT_QSPI,
98 		.flags		= IORESOURCE_IRQ,
99 	},
100 };
101 
102 #define MCFQSPI_CS0    84
103 #define MCFQSPI_CS1    85
104 #define MCFQSPI_CS2    86
105 
m532x_cs_setup(struct mcfqspi_cs_control * cs_control)106 static int m532x_cs_setup(struct mcfqspi_cs_control *cs_control)
107 {
108 	int status;
109 
110 	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
111 	if (status) {
112 		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
113 		goto fail0;
114 	}
115 	status = gpio_direction_output(MCFQSPI_CS0, 1);
116 	if (status) {
117 		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
118 		goto fail1;
119 	}
120 
121 	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
122 	if (status) {
123 		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
124 		goto fail1;
125 	}
126 	status = gpio_direction_output(MCFQSPI_CS1, 1);
127 	if (status) {
128 		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
129 		goto fail2;
130 	}
131 
132 	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
133 	if (status) {
134 		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
135 		goto fail2;
136 	}
137 	status = gpio_direction_output(MCFQSPI_CS2, 1);
138 	if (status) {
139 		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
140 		goto fail3;
141 	}
142 
143 	return 0;
144 
145 fail3:
146 	gpio_free(MCFQSPI_CS2);
147 fail2:
148 	gpio_free(MCFQSPI_CS1);
149 fail1:
150 	gpio_free(MCFQSPI_CS0);
151 fail0:
152 	return status;
153 }
154 
m532x_cs_teardown(struct mcfqspi_cs_control * cs_control)155 static void m532x_cs_teardown(struct mcfqspi_cs_control *cs_control)
156 {
157 	gpio_free(MCFQSPI_CS2);
158 	gpio_free(MCFQSPI_CS1);
159 	gpio_free(MCFQSPI_CS0);
160 }
161 
m532x_cs_select(struct mcfqspi_cs_control * cs_control,u8 chip_select,bool cs_high)162 static void m532x_cs_select(struct mcfqspi_cs_control *cs_control,
163 			    u8 chip_select, bool cs_high)
164 {
165 	gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
166 }
167 
m532x_cs_deselect(struct mcfqspi_cs_control * cs_control,u8 chip_select,bool cs_high)168 static void m532x_cs_deselect(struct mcfqspi_cs_control *cs_control,
169 			      u8 chip_select, bool cs_high)
170 {
171 	gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
172 }
173 
174 static struct mcfqspi_cs_control m532x_cs_control = {
175 	.setup                  = m532x_cs_setup,
176 	.teardown               = m532x_cs_teardown,
177 	.select                 = m532x_cs_select,
178 	.deselect               = m532x_cs_deselect,
179 };
180 
181 static struct mcfqspi_platform_data m532x_qspi_data = {
182 	.bus_num		= 0,
183 	.num_chipselect		= 3,
184 	.cs_control		= &m532x_cs_control,
185 };
186 
187 static struct platform_device m532x_qspi = {
188 	.name			= "mcfqspi",
189 	.id			= 0,
190 	.num_resources		= ARRAY_SIZE(m532x_qspi_resources),
191 	.resource		= m532x_qspi_resources,
192 	.dev.platform_data	= &m532x_qspi_data,
193 };
194 
m532x_qspi_init(void)195 static void __init m532x_qspi_init(void)
196 {
197 	/* setup QSPS pins for QSPI with gpio CS control */
198 	writew(0x01f0, MCF_GPIO_PAR_QSPI);
199 }
200 #endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
201 
202 
203 static struct platform_device *m532x_devices[] __initdata = {
204 	&m532x_uart,
205 	&m532x_fec,
206 #if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
207 	&m532x_qspi,
208 #endif
209 };
210 
211 /***************************************************************************/
212 
m532x_uart_init_line(int line,int irq)213 static void __init m532x_uart_init_line(int line, int irq)
214 {
215 	if (line == 0) {
216 		/* GPIO initialization */
217 		MCF_GPIO_PAR_UART |= 0x000F;
218 	} else if (line == 1) {
219 		/* GPIO initialization */
220 		MCF_GPIO_PAR_UART |= 0x0FF0;
221 	}
222 }
223 
m532x_uarts_init(void)224 static void __init m532x_uarts_init(void)
225 {
226 	const int nrlines = ARRAY_SIZE(m532x_uart_platform);
227 	int line;
228 
229 	for (line = 0; (line < nrlines); line++)
230 		m532x_uart_init_line(line, m532x_uart_platform[line].irq);
231 }
232 /***************************************************************************/
233 
m532x_fec_init(void)234 static void __init m532x_fec_init(void)
235 {
236 	/* Set multi-function pins to ethernet mode for fec0 */
237 	MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
238 		MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
239 	MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
240 		MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
241 }
242 
243 /***************************************************************************/
244 
m532x_cpu_reset(void)245 static void m532x_cpu_reset(void)
246 {
247 	local_irq_disable();
248 	__raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
249 }
250 
251 /***************************************************************************/
252 
config_BSP(char * commandp,int size)253 void __init config_BSP(char *commandp, int size)
254 {
255 #if !defined(CONFIG_BOOTPARAM)
256 	/* Copy command line from FLASH to local buffer... */
257 	memcpy(commandp, (char *) 0x4000, 4);
258 	if(strncmp(commandp, "kcl ", 4) == 0){
259 		memcpy(commandp, (char *) 0x4004, size);
260 		commandp[size-1] = 0;
261 	} else {
262 		memset(commandp, 0, size);
263 	}
264 #endif
265 
266 #ifdef CONFIG_BDM_DISABLE
267 	/*
268 	 * Disable the BDM clocking.  This also turns off most of the rest of
269 	 * the BDM device.  This is good for EMC reasons. This option is not
270 	 * incompatible with the memory protection option.
271 	 */
272 	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
273 #endif
274 }
275 
276 /***************************************************************************/
277 
init_BSP(void)278 static int __init init_BSP(void)
279 {
280 	m532x_uarts_init();
281 	m532x_fec_init();
282 #if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
283 	m532x_qspi_init();
284 #endif
285 	platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
286 	return 0;
287 }
288 
289 arch_initcall(init_BSP);
290 
291 /***************************************************************************/
292 /* Board initialization */
293 /***************************************************************************/
294 /*
295  * PLL min/max specifications
296  */
297 #define MAX_FVCO	500000	/* KHz */
298 #define MAX_FSYS	80000 	/* KHz */
299 #define MIN_FSYS	58333 	/* KHz */
300 #define FREF		16000   /* KHz */
301 
302 
303 #define MAX_MFD		135     /* Multiplier */
304 #define MIN_MFD		88      /* Multiplier */
305 #define BUSDIV		6       /* Divider */
306 
307 /*
308  * Low Power Divider specifications
309  */
310 #define MIN_LPD		(1 << 0)    /* Divider (not encoded) */
311 #define MAX_LPD		(1 << 15)   /* Divider (not encoded) */
312 #define DEFAULT_LPD	(1 << 1)	/* Divider (not encoded) */
313 
314 #define SYS_CLK_KHZ	80000
315 #define SYSTEM_PERIOD	12.5
316 /*
317  *  SDRAM Timing Parameters
318  */
319 #define SDRAM_BL	8	/* # of beats in a burst */
320 #define SDRAM_TWR	2	/* in clocks */
321 #define SDRAM_CASL	2.5	/* CASL in clocks */
322 #define SDRAM_TRCD	2	/* in clocks */
323 #define SDRAM_TRP	2	/* in clocks */
324 #define SDRAM_TRFC	7	/* in clocks */
325 #define SDRAM_TREFI	7800	/* in ns */
326 
327 #define EXT_SRAM_ADDRESS	(0xC0000000)
328 #define FLASH_ADDRESS		(0x00000000)
329 #define SDRAM_ADDRESS		(0x40000000)
330 
331 #define NAND_FLASH_ADDRESS	(0xD0000000)
332 
333 int sys_clk_khz = 0;
334 int sys_clk_mhz = 0;
335 
336 void wtm_init(void);
337 void scm_init(void);
338 void gpio_init(void);
339 void fbcs_init(void);
340 void sdramc_init(void);
341 int  clock_pll (int fsys, int flags);
342 int  clock_limp (int);
343 int  clock_exit_limp (void);
344 int  get_sys_clock (void);
345 
sysinit(void)346 asmlinkage void __init sysinit(void)
347 {
348 	sys_clk_khz = clock_pll(0, 0);
349 	sys_clk_mhz = sys_clk_khz/1000;
350 
351 	wtm_init();
352 	scm_init();
353 	gpio_init();
354 	fbcs_init();
355 	sdramc_init();
356 }
357 
wtm_init(void)358 void wtm_init(void)
359 {
360 	/* Disable watchdog timer */
361 	MCF_WTM_WCR = 0;
362 }
363 
364 #define MCF_SCM_BCR_GBW		(0x00000100)
365 #define MCF_SCM_BCR_GBR		(0x00000200)
366 
scm_init(void)367 void scm_init(void)
368 {
369 	/* All masters are trusted */
370 	MCF_SCM_MPR = 0x77777777;
371 
372 	/* Allow supervisor/user, read/write, and trusted/untrusted
373 	   access to all slaves */
374 	MCF_SCM_PACRA = 0;
375 	MCF_SCM_PACRB = 0;
376 	MCF_SCM_PACRC = 0;
377 	MCF_SCM_PACRD = 0;
378 	MCF_SCM_PACRE = 0;
379 	MCF_SCM_PACRF = 0;
380 
381 	/* Enable bursts */
382 	MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
383 }
384 
385 
fbcs_init(void)386 void fbcs_init(void)
387 {
388 	MCF_GPIO_PAR_CS = 0x0000003E;
389 
390 	/* Latch chip select */
391 	MCF_FBCS1_CSAR = 0x10080000;
392 
393 	MCF_FBCS1_CSCR = 0x002A3780;
394 	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
395 
396 	/* Initialize latch to drive signals to inactive states */
397 	*((u16 *)(0x10080000)) = 0xFFFF;
398 
399 	/* External SRAM */
400 	MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
401 	MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
402 			| MCF_FBCS_CSCR_AA
403 			| MCF_FBCS_CSCR_SBM
404 			| MCF_FBCS_CSCR_WS(1));
405 	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
406 			| MCF_FBCS_CSMR_V);
407 
408 	/* Boot Flash connected to FBCS0 */
409 	MCF_FBCS0_CSAR = FLASH_ADDRESS;
410 	MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
411 			| MCF_FBCS_CSCR_BEM
412 			| MCF_FBCS_CSCR_AA
413 			| MCF_FBCS_CSCR_SBM
414 			| MCF_FBCS_CSCR_WS(7));
415 	MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
416 			| MCF_FBCS_CSMR_V);
417 }
418 
sdramc_init(void)419 void sdramc_init(void)
420 {
421 	/*
422 	 * Check to see if the SDRAM has already been initialized
423 	 * by a run control tool
424 	 */
425 	if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
426 		/* SDRAM chip select initialization */
427 
428 		/* Initialize SDRAM chip select */
429 		MCF_SDRAMC_SDCS0 = (0
430 			| MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
431 			| MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
432 
433 	/*
434 	 * Basic configuration and initialization
435 	 */
436 	MCF_SDRAMC_SDCFG1 = (0
437 		| MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
438 		| MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
439 		| MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
440 		| MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
441 		| MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
442 		| MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
443 		| MCF_SDRAMC_SDCFG1_WTLAT(3));
444 	MCF_SDRAMC_SDCFG2 = (0
445 		| MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
446 		| MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
447 		| MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
448 		| MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
449 
450 
451 	/*
452 	 * Precharge and enable write to SDMR
453 	 */
454         MCF_SDRAMC_SDCR = (0
455 		| MCF_SDRAMC_SDCR_MODE_EN
456 		| MCF_SDRAMC_SDCR_CKE
457 		| MCF_SDRAMC_SDCR_DDR
458 		| MCF_SDRAMC_SDCR_MUX(1)
459 		| MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
460 		| MCF_SDRAMC_SDCR_PS_16
461 		| MCF_SDRAMC_SDCR_IPALL);
462 
463 	/*
464 	 * Write extended mode register
465 	 */
466 	MCF_SDRAMC_SDMR = (0
467 		| MCF_SDRAMC_SDMR_BNKAD_LEMR
468 		| MCF_SDRAMC_SDMR_AD(0x0)
469 		| MCF_SDRAMC_SDMR_CMD);
470 
471 	/*
472 	 * Write mode register and reset DLL
473 	 */
474 	MCF_SDRAMC_SDMR = (0
475 		| MCF_SDRAMC_SDMR_BNKAD_LMR
476 		| MCF_SDRAMC_SDMR_AD(0x163)
477 		| MCF_SDRAMC_SDMR_CMD);
478 
479 	/*
480 	 * Execute a PALL command
481 	 */
482 	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
483 
484 	/*
485 	 * Perform two REF cycles
486 	 */
487 	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
488 	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
489 
490 	/*
491 	 * Write mode register and clear reset DLL
492 	 */
493 	MCF_SDRAMC_SDMR = (0
494 		| MCF_SDRAMC_SDMR_BNKAD_LMR
495 		| MCF_SDRAMC_SDMR_AD(0x063)
496 		| MCF_SDRAMC_SDMR_CMD);
497 
498 	/*
499 	 * Enable auto refresh and lock SDMR
500 	 */
501 	MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
502 	MCF_SDRAMC_SDCR |= (0
503 		| MCF_SDRAMC_SDCR_REF
504 		| MCF_SDRAMC_SDCR_DQS_OE(0xC));
505 	}
506 }
507 
gpio_init(void)508 void gpio_init(void)
509 {
510 	/* Enable UART0 pins */
511 	MCF_GPIO_PAR_UART = ( 0
512 		| MCF_GPIO_PAR_UART_PAR_URXD0
513 		| MCF_GPIO_PAR_UART_PAR_UTXD0);
514 
515 	/* Initialize TIN3 as a GPIO output to enable the write
516 	   half of the latch */
517 	MCF_GPIO_PAR_TIMER = 0x00;
518 	__raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
519 	__raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
520 
521 }
522 
clock_pll(int fsys,int flags)523 int clock_pll(int fsys, int flags)
524 {
525 	int fref, temp, fout, mfd;
526 	u32 i;
527 
528 	fref = FREF;
529 
530 	if (fsys == 0) {
531 		/* Return current PLL output */
532 		mfd = MCF_PLL_PFDR;
533 
534 		return (fref * mfd / (BUSDIV * 4));
535 	}
536 
537 	/* Check bounds of requested system clock */
538 	if (fsys > MAX_FSYS)
539 		fsys = MAX_FSYS;
540 	if (fsys < MIN_FSYS)
541 		fsys = MIN_FSYS;
542 
543 	/* Multiplying by 100 when calculating the temp value,
544 	   and then dividing by 100 to calculate the mfd allows
545 	   for exact values without needing to include floating
546 	   point libraries. */
547 	temp = 100 * fsys / fref;
548 	mfd = 4 * BUSDIV * temp / 100;
549 
550 	/* Determine the output frequency for selected values */
551 	fout = (fref * mfd / (BUSDIV * 4));
552 
553 	/*
554 	 * Check to see if the SDRAM has already been initialized.
555 	 * If it has then the SDRAM needs to be put into self refresh
556 	 * mode before reprogramming the PLL.
557 	 */
558 	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
559 		/* Put SDRAM into self refresh mode */
560 		MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
561 
562 	/*
563 	 * Initialize the PLL to generate the new system clock frequency.
564 	 * The device must be put into LIMP mode to reprogram the PLL.
565 	 */
566 
567 	/* Enter LIMP mode */
568 	clock_limp(DEFAULT_LPD);
569 
570 	/* Reprogram PLL for desired fsys */
571 	MCF_PLL_PODR = (0
572 		| MCF_PLL_PODR_CPUDIV(BUSDIV/3)
573 		| MCF_PLL_PODR_BUSDIV(BUSDIV));
574 
575 	MCF_PLL_PFDR = mfd;
576 
577 	/* Exit LIMP mode */
578 	clock_exit_limp();
579 
580 	/*
581 	 * Return the SDRAM to normal operation if it is in use.
582 	 */
583 	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
584 		/* Exit self refresh mode */
585 		MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
586 
587 	/* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
588 	MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
589 
590 	/* wait for DQS logic to relock */
591 	for (i = 0; i < 0x200; i++)
592 		;
593 
594 	return fout;
595 }
596 
clock_limp(int div)597 int clock_limp(int div)
598 {
599 	u32 temp;
600 
601 	/* Check bounds of divider */
602 	if (div < MIN_LPD)
603 		div = MIN_LPD;
604 	if (div > MAX_LPD)
605 		div = MAX_LPD;
606 
607 	/* Save of the current value of the SSIDIV so we don't
608 	   overwrite the value*/
609 	temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
610 
611 	/* Apply the divider to the system clock */
612 	MCF_CCM_CDR = ( 0
613 		| MCF_CCM_CDR_LPDIV(div)
614 		| MCF_CCM_CDR_SSIDIV(temp));
615 
616 	MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
617 
618 	return (FREF/(3*(1 << div)));
619 }
620 
clock_exit_limp(void)621 int clock_exit_limp(void)
622 {
623 	int fout;
624 
625 	/* Exit LIMP mode */
626 	MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
627 
628 	/* Wait for PLL to lock */
629 	while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
630 		;
631 
632 	fout = get_sys_clock();
633 
634 	return fout;
635 }
636 
get_sys_clock(void)637 int get_sys_clock(void)
638 {
639 	int divider;
640 
641 	/* Test to see if device is in LIMP mode */
642 	if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
643 		divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
644 		return (FREF/(2 << divider));
645 	}
646 	else
647 		return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
648 }
649