aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/platform/coldfire/m53xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/platform/coldfire/m53xx.c')
-rw-r--r--arch/m68k/platform/coldfire/m53xx.c592
1 files changed, 592 insertions, 0 deletions
diff --git a/arch/m68k/platform/coldfire/m53xx.c b/arch/m68k/platform/coldfire/m53xx.c
new file mode 100644
index 000000000000..5286f98fbed0
--- /dev/null
+++ b/arch/m68k/platform/coldfire/m53xx.c
@@ -0,0 +1,592 @@
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
34DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
35DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
36DEFINE_CLK(0, "fec.0", 12, MCF_CLK);
37DEFINE_CLK(0, "edma", 17, MCF_CLK);
38DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
39DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
40DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
41DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
42DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
43DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
44DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
45DEFINE_CLK(0, "mcfuart.2", 26, MCF_BUSCLK);
46DEFINE_CLK(0, "mcftmr.0", 28, MCF_CLK);
47DEFINE_CLK(0, "mcftmr.1", 29, MCF_CLK);
48DEFINE_CLK(0, "mcftmr.2", 30, MCF_CLK);
49DEFINE_CLK(0, "mcftmr.3", 31, MCF_CLK);
50
51DEFINE_CLK(0, "mcfpit.0", 32, MCF_CLK);
52DEFINE_CLK(0, "mcfpit.1", 33, MCF_CLK);
53DEFINE_CLK(0, "mcfpit.2", 34, MCF_CLK);
54DEFINE_CLK(0, "mcfpit.3", 35, MCF_CLK);
55DEFINE_CLK(0, "mcfpwm.0", 36, MCF_CLK);
56DEFINE_CLK(0, "mcfeport.0", 37, MCF_CLK);
57DEFINE_CLK(0, "mcfwdt.0", 38, MCF_CLK);
58DEFINE_CLK(0, "sys.0", 40, MCF_BUSCLK);
59DEFINE_CLK(0, "gpio.0", 41, MCF_BUSCLK);
60DEFINE_CLK(0, "mcfrtc.0", 42, MCF_CLK);
61DEFINE_CLK(0, "mcflcd.0", 43, MCF_CLK);
62DEFINE_CLK(0, "mcfusb-otg.0", 44, MCF_CLK);
63DEFINE_CLK(0, "mcfusb-host.0", 45, MCF_CLK);
64DEFINE_CLK(0, "sdram.0", 46, MCF_CLK);
65DEFINE_CLK(0, "ssi.0", 47, MCF_CLK);
66DEFINE_CLK(0, "pll.0", 48, MCF_CLK);
67
68DEFINE_CLK(1, "mdha.0", 32, MCF_CLK);
69DEFINE_CLK(1, "skha.0", 33, MCF_CLK);
70DEFINE_CLK(1, "rng.0", 34, MCF_CLK);
71
72struct 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
113static 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
132static 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
155static 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#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
170
171static void __init m53xx_qspi_init(void)
172{
173 /* setup QSPS pins for QSPI with gpio CS control */
174 writew(0x01f0, MCFGPIO_PAR_QSPI);
175}
176
177#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
178
179/***************************************************************************/
180
181static void __init m53xx_uarts_init(void)
182{
183 /* UART GPIO initialization */
184 writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART);
185}
186
187/***************************************************************************/
188
189static void __init m53xx_fec_init(void)
190{
191 u8 v;
192
193 /* Set multi-function pins to ethernet mode for fec0 */
194 v = readb(MCFGPIO_PAR_FECI2C);
195 v |= MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
196 MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO;
197 writeb(v, MCFGPIO_PAR_FECI2C);
198
199 v = readb(MCFGPIO_PAR_FEC);
200 v = MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC;
201 writeb(v, MCFGPIO_PAR_FEC);
202}
203
204/***************************************************************************/
205
206void __init config_BSP(char *commandp, int size)
207{
208#if !defined(CONFIG_BOOTPARAM)
209 /* Copy command line from FLASH to local buffer... */
210 memcpy(commandp, (char *) 0x4000, 4);
211 if(strncmp(commandp, "kcl ", 4) == 0){
212 memcpy(commandp, (char *) 0x4004, size);
213 commandp[size-1] = 0;
214 } else {
215 memset(commandp, 0, size);
216 }
217#endif
218 mach_sched_init = hw_timer_init;
219 m53xx_clk_init();
220 m53xx_uarts_init();
221 m53xx_fec_init();
222#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
223 m53xx_qspi_init();
224#endif
225
226#ifdef CONFIG_BDM_DISABLE
227 /*
228 * Disable the BDM clocking. This also turns off most of the rest of
229 * the BDM device. This is good for EMC reasons. This option is not
230 * incompatible with the memory protection option.
231 */
232 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
233#endif
234}
235
236/***************************************************************************/
237/* Board initialization */
238/***************************************************************************/
239/*
240 * PLL min/max specifications
241 */
242#define MAX_FVCO 500000 /* KHz */
243#define MAX_FSYS 80000 /* KHz */
244#define MIN_FSYS 58333 /* KHz */
245#define FREF 16000 /* KHz */
246
247
248#define MAX_MFD 135 /* Multiplier */
249#define MIN_MFD 88 /* Multiplier */
250#define BUSDIV 6 /* Divider */
251
252/*
253 * Low Power Divider specifications
254 */
255#define MIN_LPD (1 << 0) /* Divider (not encoded) */
256#define MAX_LPD (1 << 15) /* Divider (not encoded) */
257#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
258
259#define SYS_CLK_KHZ 80000
260#define SYSTEM_PERIOD 12.5
261/*
262 * SDRAM Timing Parameters
263 */
264#define SDRAM_BL 8 /* # of beats in a burst */
265#define SDRAM_TWR 2 /* in clocks */
266#define SDRAM_CASL 2.5 /* CASL in clocks */
267#define SDRAM_TRCD 2 /* in clocks */
268#define SDRAM_TRP 2 /* in clocks */
269#define SDRAM_TRFC 7 /* in clocks */
270#define SDRAM_TREFI 7800 /* in ns */
271
272#define EXT_SRAM_ADDRESS (0xC0000000)
273#define FLASH_ADDRESS (0x00000000)
274#define SDRAM_ADDRESS (0x40000000)
275
276#define NAND_FLASH_ADDRESS (0xD0000000)
277
278int sys_clk_khz = 0;
279int sys_clk_mhz = 0;
280
281void wtm_init(void);
282void scm_init(void);
283void gpio_init(void);
284void fbcs_init(void);
285void sdramc_init(void);
286int clock_pll (int fsys, int flags);
287int clock_limp (int);
288int clock_exit_limp (void);
289int get_sys_clock (void);
290
291asmlinkage void __init sysinit(void)
292{
293 sys_clk_khz = clock_pll(0, 0);
294 sys_clk_mhz = sys_clk_khz/1000;
295
296 wtm_init();
297 scm_init();
298 gpio_init();
299 fbcs_init();
300 sdramc_init();
301}
302
303void wtm_init(void)
304{
305 /* Disable watchdog timer */
306 writew(0, MCF_WTM_WCR);
307}
308
309#define MCF_SCM_BCR_GBW (0x00000100)
310#define MCF_SCM_BCR_GBR (0x00000200)
311
312void scm_init(void)
313{
314 /* All masters are trusted */
315 writel(0x77777777, MCF_SCM_MPR);
316
317 /* Allow supervisor/user, read/write, and trusted/untrusted
318 access to all slaves */
319 writel(0, MCF_SCM_PACRA);
320 writel(0, MCF_SCM_PACRB);
321 writel(0, MCF_SCM_PACRC);
322 writel(0, MCF_SCM_PACRD);
323 writel(0, MCF_SCM_PACRE);
324 writel(0, MCF_SCM_PACRF);
325
326 /* Enable bursts */
327 writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR);
328}
329
330
331void fbcs_init(void)
332{
333 writeb(0x3E, MCFGPIO_PAR_CS);
334
335 /* Latch chip select */
336 writel(0x10080000, MCF_FBCS1_CSAR);
337
338 writel(0x002A3780, MCF_FBCS1_CSCR);
339 writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
340
341 /* Initialize latch to drive signals to inactive states */
342 writew(0xffff, 0x10080000);
343
344 /* External SRAM */
345 writel(EXT_SRAM_ADDRESS, MCF_FBCS1_CSAR);
346 writel(MCF_FBCS_CSCR_PS_16 |
347 MCF_FBCS_CSCR_AA |
348 MCF_FBCS_CSCR_SBM |
349 MCF_FBCS_CSCR_WS(1),
350 MCF_FBCS1_CSCR);
351 writel(MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
352
353 /* Boot Flash connected to FBCS0 */
354 writel(FLASH_ADDRESS, MCF_FBCS0_CSAR);
355 writel(MCF_FBCS_CSCR_PS_16 |
356 MCF_FBCS_CSCR_BEM |
357 MCF_FBCS_CSCR_AA |
358 MCF_FBCS_CSCR_SBM |
359 MCF_FBCS_CSCR_WS(7),
360 MCF_FBCS0_CSCR);
361 writel(MCF_FBCS_CSMR_BAM_32M | MCF_FBCS_CSMR_V, MCF_FBCS0_CSMR);
362}
363
364void sdramc_init(void)
365{
366 /*
367 * Check to see if the SDRAM has already been initialized
368 * by a run control tool
369 */
370 if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) {
371 /* SDRAM chip select initialization */
372
373 /* Initialize SDRAM chip select */
374 writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) |
375 MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE),
376 MCF_SDRAMC_SDCS0);
377
378 /*
379 * Basic configuration and initialization
380 */
381 writel(MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5)) |
382 MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) |
383 MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL * 2) + 2)) |
384 MCF_SDRAMC_SDCFG1_ACT2RW((int)(SDRAM_TRCD + 0.5)) |
385 MCF_SDRAMC_SDCFG1_PRE2ACT((int)(SDRAM_TRP + 0.5)) |
386 MCF_SDRAMC_SDCFG1_REF2ACT((int)(SDRAM_TRFC + 0.5)) |
387 MCF_SDRAMC_SDCFG1_WTLAT(3),
388 MCF_SDRAMC_SDCFG1);
389 writel(MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL / 2 + 1) |
390 MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL / 2 + SDRAM_TWR) |
391 MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL + SDRAM_BL / 2 - 1.0) + 0.5)) |
392 MCF_SDRAMC_SDCFG2_BL(SDRAM_BL - 1),
393 MCF_SDRAMC_SDCFG2);
394
395
396 /*
397 * Precharge and enable write to SDMR
398 */
399 writel(MCF_SDRAMC_SDCR_MODE_EN |
400 MCF_SDRAMC_SDCR_CKE |
401 MCF_SDRAMC_SDCR_DDR |
402 MCF_SDRAMC_SDCR_MUX(1) |
403 MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI / (SYSTEM_PERIOD * 64)) - 1) + 0.5)) |
404 MCF_SDRAMC_SDCR_PS_16 |
405 MCF_SDRAMC_SDCR_IPALL,
406 MCF_SDRAMC_SDCR);
407
408 /*
409 * Write extended mode register
410 */
411 writel(MCF_SDRAMC_SDMR_BNKAD_LEMR |
412 MCF_SDRAMC_SDMR_AD(0x0) |
413 MCF_SDRAMC_SDMR_CMD,
414 MCF_SDRAMC_SDMR);
415
416 /*
417 * Write mode register and reset DLL
418 */
419 writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
420 MCF_SDRAMC_SDMR_AD(0x163) |
421 MCF_SDRAMC_SDMR_CMD,
422 MCF_SDRAMC_SDMR);
423
424 /*
425 * Execute a PALL command
426 */
427 writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR);
428
429 /*
430 * Perform two REF cycles
431 */
432 writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
433 writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
434
435 /*
436 * Write mode register and clear reset DLL
437 */
438 writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
439 MCF_SDRAMC_SDMR_AD(0x063) |
440 MCF_SDRAMC_SDMR_CMD,
441 MCF_SDRAMC_SDMR);
442
443 /*
444 * Enable auto refresh and lock SDMR
445 */
446 writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_MODE_EN,
447 MCF_SDRAMC_SDCR);
448 writel(MCF_SDRAMC_SDCR_REF | MCF_SDRAMC_SDCR_DQS_OE(0xC),
449 MCF_SDRAMC_SDCR);
450 }
451}
452
453void gpio_init(void)
454{
455 /* Enable UART0 pins */
456 writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0,
457 MCFGPIO_PAR_UART);
458
459 /*
460 * Initialize TIN3 as a GPIO output to enable the write
461 * half of the latch.
462 */
463 writeb(0x00, MCFGPIO_PAR_TIMER);
464 writeb(0x08, MCFGPIO_PDDR_TIMER);
465 writeb(0x00, MCFGPIO_PCLRR_TIMER);
466}
467
468int clock_pll(int fsys, int flags)
469{
470 int fref, temp, fout, mfd;
471 u32 i;
472
473 fref = FREF;
474
475 if (fsys == 0) {
476 /* Return current PLL output */
477 mfd = readb(MCF_PLL_PFDR);
478
479 return (fref * mfd / (BUSDIV * 4));
480 }
481
482 /* Check bounds of requested system clock */
483 if (fsys > MAX_FSYS)
484 fsys = MAX_FSYS;
485 if (fsys < MIN_FSYS)
486 fsys = MIN_FSYS;
487
488 /* Multiplying by 100 when calculating the temp value,
489 and then dividing by 100 to calculate the mfd allows
490 for exact values without needing to include floating
491 point libraries. */
492 temp = 100 * fsys / fref;
493 mfd = 4 * BUSDIV * temp / 100;
494
495 /* Determine the output frequency for selected values */
496 fout = (fref * mfd / (BUSDIV * 4));
497
498 /*
499 * Check to see if the SDRAM has already been initialized.
500 * If it has then the SDRAM needs to be put into self refresh
501 * mode before reprogramming the PLL.
502 */
503 if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
504 /* Put SDRAM into self refresh mode */
505 writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE,
506 MCF_SDRAMC_SDCR);
507
508 /*
509 * Initialize the PLL to generate the new system clock frequency.
510 * The device must be put into LIMP mode to reprogram the PLL.
511 */
512
513 /* Enter LIMP mode */
514 clock_limp(DEFAULT_LPD);
515
516 /* Reprogram PLL for desired fsys */
517 writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV),
518 MCF_PLL_PODR);
519
520 writeb(mfd, MCF_PLL_PFDR);
521
522 /* Exit LIMP mode */
523 clock_exit_limp();
524
525 /*
526 * Return the SDRAM to normal operation if it is in use.
527 */
528 if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
529 /* Exit self refresh mode */
530 writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE,
531 MCF_SDRAMC_SDCR);
532
533 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
534 writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX);
535
536 /* wait for DQS logic to relock */
537 for (i = 0; i < 0x200; i++)
538 ;
539
540 return fout;
541}
542
543int clock_limp(int div)
544{
545 u32 temp;
546
547 /* Check bounds of divider */
548 if (div < MIN_LPD)
549 div = MIN_LPD;
550 if (div > MAX_LPD)
551 div = MAX_LPD;
552
553 /* Save of the current value of the SSIDIV so we don't
554 overwrite the value*/
555 temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF);
556
557 /* Apply the divider to the system clock */
558 writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR);
559
560 writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
561
562 return (FREF/(3*(1 << div)));
563}
564
565int clock_exit_limp(void)
566{
567 int fout;
568
569 /* Exit LIMP mode */
570 writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
571
572 /* Wait for PLL to lock */
573 while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK))
574 ;
575
576 fout = get_sys_clock();
577
578 return fout;
579}
580
581int get_sys_clock(void)
582{
583 int divider;
584
585 /* Test to see if device is in LIMP mode */
586 if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) {
587 divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF);
588 return (FREF/(2 << divider));
589 }
590 else
591 return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4);
592}