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