blob: 5b106839f9b673086e1acbefd9c878f8db559080 [file] [log] [blame]
Greg Ungerer3196cf82006-06-26 10:33:10 +10001/***************************************************************************/
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
Greg Ungerer3196cf82006-06-26 10:33:10 +100020#include <linux/kernel.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100021#include <linux/param.h>
22#include <linux/init.h>
Greg Ungererb2e18102008-02-01 17:34:58 +100023#include <linux/io.h>
Steven King91d60412010-01-22 12:43:03 -080024#include <linux/spi/spi.h>
25#include <linux/gpio.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100026#include <asm/machdep.h>
27#include <asm/coldfire.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100028#include <asm/mcfsim.h>
Greg Ungererb2e18102008-02-01 17:34:58 +100029#include <asm/mcfuart.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100030#include <asm/mcfdma.h>
31#include <asm/mcfwdebug.h>
Steven King91d60412010-01-22 12:43:03 -080032#include <asm/mcfqspi.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100033
34/***************************************************************************/
35
Greg Ungererb2e18102008-02-01 17:34:58 +100036static struct mcf_platform_uart m532x_uart_platform[] = {
37 {
Greg Ungerer35b7cf22011-12-24 00:41:07 +100038 .mapbase = MCFUART_BASE0,
39 .irq = MCF_IRQ_UART0,
40 },
41 {
42 .mapbase = MCFUART_BASE1,
43 .irq = MCF_IRQ_UART1,
Greg Ungererb2e18102008-02-01 17:34:58 +100044 },
45 {
Matt Waddeladd82402008-12-20 07:16:38 -070046 .mapbase = MCFUART_BASE2,
Greg Ungerer35b7cf22011-12-24 00:41:07 +100047 .irq = MCF_IRQ_UART2,
Greg Ungererb2e18102008-02-01 17:34:58 +100048 },
49 { },
50};
51
52static struct platform_device m532x_uart = {
53 .name = "mcfuart",
54 .id = 0,
55 .dev.platform_data = m532x_uart_platform,
56};
57
Greg Ungererffba3f42009-02-26 22:40:38 -080058static 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
81static 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};
Greg Ungererf6a66272009-05-19 15:00:01 +100087
Steven King91d60412010-01-22 12:43:03 -080088#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
89static 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
106static 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
145fail3:
146 gpio_free(MCFQSPI_CS2);
147fail2:
148 gpio_free(MCFQSPI_CS1);
149fail1:
150 gpio_free(MCFQSPI_CS0);
151fail0:
152 return status;
153}
154
155static 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
162static 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
168static 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
174static 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
181static struct mcfqspi_platform_data m532x_qspi_data = {
182 .bus_num = 0,
183 .num_chipselect = 3,
184 .cs_control = &m532x_cs_control,
185};
186
187static 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
195static 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
Greg Ungererb2e18102008-02-01 17:34:58 +1000203static struct platform_device *m532x_devices[] __initdata = {
204 &m532x_uart,
Greg Ungererffba3f42009-02-26 22:40:38 -0800205 &m532x_fec,
Steven King91d60412010-01-22 12:43:03 -0800206#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
207 &m532x_qspi,
208#endif
Greg Ungererb2e18102008-02-01 17:34:58 +1000209};
210
211/***************************************************************************/
212
Greg Ungererb2e18102008-02-01 17:34:58 +1000213static void __init m532x_uarts_init(void)
214{
Greg Ungerera75bc612011-12-24 01:04:22 +1000215 /* UART GPIO initialization */
216 MCF_GPIO_PAR_UART |= 0x0FFF;
Greg Ungererb2e18102008-02-01 17:34:58 +1000217}
Greg Ungerera75bc612011-12-24 01:04:22 +1000218
Greg Ungererffba3f42009-02-26 22:40:38 -0800219/***************************************************************************/
220
221static void __init m532x_fec_init(void)
222{
Greg Ungererffba3f42009-02-26 22:40:38 -0800223 /* Set multi-function pins to ethernet mode for fec0 */
224 MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
225 MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
226 MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
227 MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
228}
Greg Ungerer3196cf82006-06-26 10:33:10 +1000229
230/***************************************************************************/
231
Greg Ungerer384feb92009-04-30 22:03:43 +1000232static void m532x_cpu_reset(void)
233{
234 local_irq_disable();
235 __raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
236}
237
238/***************************************************************************/
239
Greg Ungererb2e18102008-02-01 17:34:58 +1000240void __init config_BSP(char *commandp, int size)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000241{
Greg Ungererbc724502007-07-25 22:07:20 +1000242#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000243 /* Copy command line from FLASH to local buffer... */
244 memcpy(commandp, (char *) 0x4000, 4);
245 if(strncmp(commandp, "kcl ", 4) == 0){
246 memcpy(commandp, (char *) 0x4004, size);
247 commandp[size-1] = 0;
248 } else {
249 memset(commandp, 0, size);
250 }
251#endif
252
Greg Ungerer35aefb22012-01-23 15:34:58 +1000253 mach_sched_init = hw_timer_init;
254
Greg Ungererb2e18102008-02-01 17:34:58 +1000255#ifdef CONFIG_BDM_DISABLE
Greg Ungerer3196cf82006-06-26 10:33:10 +1000256 /*
257 * Disable the BDM clocking. This also turns off most of the rest of
258 * the BDM device. This is good for EMC reasons. This option is not
259 * incompatible with the memory protection option.
260 */
261 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
262#endif
263}
264
265/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000266
Greg Ungererb2e18102008-02-01 17:34:58 +1000267static int __init init_BSP(void)
268{
269 m532x_uarts_init();
Greg Ungererffba3f42009-02-26 22:40:38 -0800270 m532x_fec_init();
Steven King91d60412010-01-22 12:43:03 -0800271#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
272 m532x_qspi_init();
273#endif
Greg Ungererb2e18102008-02-01 17:34:58 +1000274 platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
275 return 0;
276}
277
278arch_initcall(init_BSP);
279
280/***************************************************************************/
281/* Board initialization */
282/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000283/*
284 * PLL min/max specifications
285 */
286#define MAX_FVCO 500000 /* KHz */
287#define MAX_FSYS 80000 /* KHz */
288#define MIN_FSYS 58333 /* KHz */
289#define FREF 16000 /* KHz */
290
291
292#define MAX_MFD 135 /* Multiplier */
293#define MIN_MFD 88 /* Multiplier */
294#define BUSDIV 6 /* Divider */
295
296/*
297 * Low Power Divider specifications
298 */
299#define MIN_LPD (1 << 0) /* Divider (not encoded) */
300#define MAX_LPD (1 << 15) /* Divider (not encoded) */
301#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
302
303#define SYS_CLK_KHZ 80000
304#define SYSTEM_PERIOD 12.5
305/*
306 * SDRAM Timing Parameters
307 */
308#define SDRAM_BL 8 /* # of beats in a burst */
309#define SDRAM_TWR 2 /* in clocks */
310#define SDRAM_CASL 2.5 /* CASL in clocks */
311#define SDRAM_TRCD 2 /* in clocks */
312#define SDRAM_TRP 2 /* in clocks */
313#define SDRAM_TRFC 7 /* in clocks */
314#define SDRAM_TREFI 7800 /* in ns */
315
316#define EXT_SRAM_ADDRESS (0xC0000000)
317#define FLASH_ADDRESS (0x00000000)
318#define SDRAM_ADDRESS (0x40000000)
319
320#define NAND_FLASH_ADDRESS (0xD0000000)
321
322int sys_clk_khz = 0;
323int sys_clk_mhz = 0;
324
325void wtm_init(void);
326void scm_init(void);
327void gpio_init(void);
328void fbcs_init(void);
329void sdramc_init(void);
330int clock_pll (int fsys, int flags);
331int clock_limp (int);
332int clock_exit_limp (void);
333int get_sys_clock (void);
334
335asmlinkage void __init sysinit(void)
336{
337 sys_clk_khz = clock_pll(0, 0);
338 sys_clk_mhz = sys_clk_khz/1000;
339
340 wtm_init();
341 scm_init();
342 gpio_init();
343 fbcs_init();
344 sdramc_init();
345}
346
347void wtm_init(void)
348{
349 /* Disable watchdog timer */
350 MCF_WTM_WCR = 0;
351}
352
353#define MCF_SCM_BCR_GBW (0x00000100)
354#define MCF_SCM_BCR_GBR (0x00000200)
355
356void scm_init(void)
357{
358 /* All masters are trusted */
359 MCF_SCM_MPR = 0x77777777;
360
361 /* Allow supervisor/user, read/write, and trusted/untrusted
362 access to all slaves */
363 MCF_SCM_PACRA = 0;
364 MCF_SCM_PACRB = 0;
365 MCF_SCM_PACRC = 0;
366 MCF_SCM_PACRD = 0;
367 MCF_SCM_PACRE = 0;
368 MCF_SCM_PACRF = 0;
369
370 /* Enable bursts */
371 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
372}
373
374
375void fbcs_init(void)
376{
377 MCF_GPIO_PAR_CS = 0x0000003E;
378
379 /* Latch chip select */
380 MCF_FBCS1_CSAR = 0x10080000;
381
382 MCF_FBCS1_CSCR = 0x002A3780;
383 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
384
385 /* Initialize latch to drive signals to inactive states */
386 *((u16 *)(0x10080000)) = 0xFFFF;
387
388 /* External SRAM */
389 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
390 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
391 | MCF_FBCS_CSCR_AA
392 | MCF_FBCS_CSCR_SBM
393 | MCF_FBCS_CSCR_WS(1));
394 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
395 | MCF_FBCS_CSMR_V);
396
397 /* Boot Flash connected to FBCS0 */
398 MCF_FBCS0_CSAR = FLASH_ADDRESS;
399 MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
400 | MCF_FBCS_CSCR_BEM
401 | MCF_FBCS_CSCR_AA
402 | MCF_FBCS_CSCR_SBM
403 | MCF_FBCS_CSCR_WS(7));
404 MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
405 | MCF_FBCS_CSMR_V);
406}
407
408void sdramc_init(void)
409{
410 /*
411 * Check to see if the SDRAM has already been initialized
412 * by a run control tool
413 */
414 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
415 /* SDRAM chip select initialization */
416
417 /* Initialize SDRAM chip select */
418 MCF_SDRAMC_SDCS0 = (0
419 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
420 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
421
422 /*
423 * Basic configuration and initialization
424 */
425 MCF_SDRAMC_SDCFG1 = (0
426 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
427 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
428 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
429 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
430 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
431 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
432 | MCF_SDRAMC_SDCFG1_WTLAT(3));
433 MCF_SDRAMC_SDCFG2 = (0
434 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
435 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
436 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
437 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
438
439
440 /*
441 * Precharge and enable write to SDMR
442 */
443 MCF_SDRAMC_SDCR = (0
444 | MCF_SDRAMC_SDCR_MODE_EN
445 | MCF_SDRAMC_SDCR_CKE
446 | MCF_SDRAMC_SDCR_DDR
447 | MCF_SDRAMC_SDCR_MUX(1)
448 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
449 | MCF_SDRAMC_SDCR_PS_16
450 | MCF_SDRAMC_SDCR_IPALL);
451
452 /*
453 * Write extended mode register
454 */
455 MCF_SDRAMC_SDMR = (0
456 | MCF_SDRAMC_SDMR_BNKAD_LEMR
457 | MCF_SDRAMC_SDMR_AD(0x0)
458 | MCF_SDRAMC_SDMR_CMD);
459
460 /*
461 * Write mode register and reset DLL
462 */
463 MCF_SDRAMC_SDMR = (0
464 | MCF_SDRAMC_SDMR_BNKAD_LMR
465 | MCF_SDRAMC_SDMR_AD(0x163)
466 | MCF_SDRAMC_SDMR_CMD);
467
468 /*
469 * Execute a PALL command
470 */
471 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
472
473 /*
474 * Perform two REF cycles
475 */
476 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
477 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
478
479 /*
480 * Write mode register and clear reset DLL
481 */
482 MCF_SDRAMC_SDMR = (0
483 | MCF_SDRAMC_SDMR_BNKAD_LMR
484 | MCF_SDRAMC_SDMR_AD(0x063)
485 | MCF_SDRAMC_SDMR_CMD);
486
487 /*
488 * Enable auto refresh and lock SDMR
489 */
490 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
491 MCF_SDRAMC_SDCR |= (0
492 | MCF_SDRAMC_SDCR_REF
493 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
494 }
495}
496
497void gpio_init(void)
498{
499 /* Enable UART0 pins */
500 MCF_GPIO_PAR_UART = ( 0
501 | MCF_GPIO_PAR_UART_PAR_URXD0
502 | MCF_GPIO_PAR_UART_PAR_UTXD0);
503
504 /* Initialize TIN3 as a GPIO output to enable the write
505 half of the latch */
506 MCF_GPIO_PAR_TIMER = 0x00;
sfking@fdwdc.com7846fe82009-06-19 18:11:10 -0700507 __raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
508 __raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000509
510}
511
512int clock_pll(int fsys, int flags)
513{
514 int fref, temp, fout, mfd;
515 u32 i;
516
517 fref = FREF;
518
519 if (fsys == 0) {
520 /* Return current PLL output */
521 mfd = MCF_PLL_PFDR;
522
523 return (fref * mfd / (BUSDIV * 4));
524 }
525
526 /* Check bounds of requested system clock */
527 if (fsys > MAX_FSYS)
528 fsys = MAX_FSYS;
529 if (fsys < MIN_FSYS)
530 fsys = MIN_FSYS;
531
532 /* Multiplying by 100 when calculating the temp value,
533 and then dividing by 100 to calculate the mfd allows
534 for exact values without needing to include floating
535 point libraries. */
536 temp = 100 * fsys / fref;
537 mfd = 4 * BUSDIV * temp / 100;
538
539 /* Determine the output frequency for selected values */
540 fout = (fref * mfd / (BUSDIV * 4));
541
542 /*
543 * Check to see if the SDRAM has already been initialized.
544 * If it has then the SDRAM needs to be put into self refresh
545 * mode before reprogramming the PLL.
546 */
547 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
548 /* Put SDRAM into self refresh mode */
549 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
550
551 /*
552 * Initialize the PLL to generate the new system clock frequency.
553 * The device must be put into LIMP mode to reprogram the PLL.
554 */
555
556 /* Enter LIMP mode */
557 clock_limp(DEFAULT_LPD);
558
559 /* Reprogram PLL for desired fsys */
560 MCF_PLL_PODR = (0
561 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
562 | MCF_PLL_PODR_BUSDIV(BUSDIV));
563
564 MCF_PLL_PFDR = mfd;
565
566 /* Exit LIMP mode */
567 clock_exit_limp();
568
569 /*
570 * Return the SDRAM to normal operation if it is in use.
571 */
572 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
573 /* Exit self refresh mode */
574 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
575
576 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
577 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
578
579 /* wait for DQS logic to relock */
580 for (i = 0; i < 0x200; i++)
581 ;
582
583 return fout;
584}
585
586int clock_limp(int div)
587{
588 u32 temp;
589
590 /* Check bounds of divider */
591 if (div < MIN_LPD)
592 div = MIN_LPD;
593 if (div > MAX_LPD)
594 div = MAX_LPD;
595
596 /* Save of the current value of the SSIDIV so we don't
597 overwrite the value*/
598 temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
599
600 /* Apply the divider to the system clock */
601 MCF_CCM_CDR = ( 0
602 | MCF_CCM_CDR_LPDIV(div)
603 | MCF_CCM_CDR_SSIDIV(temp));
604
605 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
606
607 return (FREF/(3*(1 << div)));
608}
609
610int clock_exit_limp(void)
611{
612 int fout;
613
614 /* Exit LIMP mode */
615 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
616
617 /* Wait for PLL to lock */
618 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
619 ;
620
621 fout = get_sys_clock();
622
623 return fout;
624}
625
626int get_sys_clock(void)
627{
628 int divider;
629
630 /* Test to see if device is in LIMP mode */
631 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
632 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
633 return (FREF/(2 << divider));
634 }
635 else
636 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
637}