blob: ca51323f957b4ec86bf7e5be18080475d089677b [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 {
Matt Waddeladd82402008-12-20 07:16:38 -070038 .mapbase = MCFUART_BASE1,
Greg Ungererb2e18102008-02-01 17:34:58 +100039 .irq = MCFINT_VECBASE + MCFINT_UART0,
40 },
41 {
Matt Waddeladd82402008-12-20 07:16:38 -070042 .mapbase = MCFUART_BASE2,
Greg Ungererb2e18102008-02-01 17:34:58 +100043 .irq = MCFINT_VECBASE + MCFINT_UART1,
44 },
45 {
Matt Waddeladd82402008-12-20 07:16:38 -070046 .mapbase = MCFUART_BASE3,
Greg Ungererb2e18102008-02-01 17:34:58 +100047 .irq = MCFINT_VECBASE + MCFINT_UART2,
48 },
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
213static void __init m532x_uart_init_line(int line, int irq)
214{
215 if (line == 0) {
Greg Ungererb2e18102008-02-01 17:34:58 +1000216 /* GPIO initialization */
217 MCF_GPIO_PAR_UART |= 0x000F;
218 } else if (line == 1) {
Greg Ungererb2e18102008-02-01 17:34:58 +1000219 /* GPIO initialization */
220 MCF_GPIO_PAR_UART |= 0x0FF0;
Greg Ungererb2e18102008-02-01 17:34:58 +1000221 }
222}
223
224static 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}
Greg Ungererffba3f42009-02-26 22:40:38 -0800232/***************************************************************************/
233
234static void __init m532x_fec_init(void)
235{
Greg Ungererffba3f42009-02-26 22:40:38 -0800236 /* 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}
Greg Ungerer3196cf82006-06-26 10:33:10 +1000242
243/***************************************************************************/
244
Greg Ungerer384feb92009-04-30 22:03:43 +1000245static void m532x_cpu_reset(void)
246{
247 local_irq_disable();
248 __raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
249}
250
251/***************************************************************************/
252
Greg Ungererb2e18102008-02-01 17:34:58 +1000253void __init config_BSP(char *commandp, int size)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000254{
Greg Ungererbc724502007-07-25 22:07:20 +1000255#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000256 /* 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
Greg Ungererb2e18102008-02-01 17:34:58 +1000266#ifdef CONFIG_BDM_DISABLE
Greg Ungerer3196cf82006-06-26 10:33:10 +1000267 /*
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/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000277
Greg Ungererb2e18102008-02-01 17:34:58 +1000278static int __init init_BSP(void)
279{
280 m532x_uarts_init();
Greg Ungererffba3f42009-02-26 22:40:38 -0800281 m532x_fec_init();
Steven King91d60412010-01-22 12:43:03 -0800282#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
283 m532x_qspi_init();
284#endif
Greg Ungererb2e18102008-02-01 17:34:58 +1000285 platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
286 return 0;
287}
288
289arch_initcall(init_BSP);
290
291/***************************************************************************/
292/* Board initialization */
293/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000294/*
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
333int sys_clk_khz = 0;
334int sys_clk_mhz = 0;
335
336void wtm_init(void);
337void scm_init(void);
338void gpio_init(void);
339void fbcs_init(void);
340void sdramc_init(void);
341int clock_pll (int fsys, int flags);
342int clock_limp (int);
343int clock_exit_limp (void);
344int get_sys_clock (void);
345
346asmlinkage 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
358void 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
367void 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
386void 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
419void 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
508void 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;
sfking@fdwdc.com7846fe82009-06-19 18:11:10 -0700518 __raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
519 __raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000520
521}
522
523int 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
597int 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
621int 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
637int 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}