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