blob: 4819a44991edcbf5172dd0f9d361ae15e442a6c2 [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
Linus Torvaldse8650a02012-05-22 19:22:50 -070010 * Copyright (c) 2006, emlix, Sebastian Hess <shess@hessware.de>
Greg Ungerer3196cf82006-06-26 10:33:10 +100011 *
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>
Greg Ungerer3196cf82006-06-26 10:33:10 +100024#include <asm/machdep.h>
25#include <asm/coldfire.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100026#include <asm/mcfsim.h>
Greg Ungererb2e18102008-02-01 17:34:58 +100027#include <asm/mcfuart.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100028#include <asm/mcfdma.h>
29#include <asm/mcfwdebug.h>
Steven King12ce4c12012-06-17 00:41:39 -070030#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 m532x_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}
Greg Ungerer3196cf82006-06-26 10:33:10 +1000167
168/***************************************************************************/
169
Steven King83ca6002012-05-06 12:22:53 -0700170#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
Steven King91d60412010-01-22 12:43:03 -0800171
172static void __init m532x_qspi_init(void)
173{
174 /* setup QSPS pins for QSPI with gpio CS control */
175 writew(0x01f0, MCF_GPIO_PAR_QSPI);
176}
Steven King91d60412010-01-22 12:43:03 -0800177
Steven King83ca6002012-05-06 12:22:53 -0700178#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
Greg Ungererb2e18102008-02-01 17:34:58 +1000179
180/***************************************************************************/
181
Greg Ungererb2e18102008-02-01 17:34:58 +1000182static void __init m532x_uarts_init(void)
183{
Greg Ungerera75bc612011-12-24 01:04:22 +1000184 /* UART GPIO initialization */
185 MCF_GPIO_PAR_UART |= 0x0FFF;
Greg Ungererb2e18102008-02-01 17:34:58 +1000186}
Greg Ungerera75bc612011-12-24 01:04:22 +1000187
Greg Ungererffba3f42009-02-26 22:40:38 -0800188/***************************************************************************/
189
190static void __init m532x_fec_init(void)
191{
Greg Ungererffba3f42009-02-26 22:40:38 -0800192 /* Set multi-function pins to ethernet mode for fec0 */
193 MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
194 MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
195 MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
196 MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
197}
Greg Ungerer3196cf82006-06-26 10:33:10 +1000198
199/***************************************************************************/
200
Greg Ungererb2e18102008-02-01 17:34:58 +1000201void __init config_BSP(char *commandp, int size)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000202{
Greg Ungererbc724502007-07-25 22:07:20 +1000203#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000204 /* Copy command line from FLASH to local buffer... */
205 memcpy(commandp, (char *) 0x4000, 4);
206 if(strncmp(commandp, "kcl ", 4) == 0){
207 memcpy(commandp, (char *) 0x4004, size);
208 commandp[size-1] = 0;
209 } else {
210 memset(commandp, 0, size);
211 }
212#endif
Greg Ungerer35aefb22012-01-23 15:34:58 +1000213 mach_sched_init = hw_timer_init;
Steven King12ce4c12012-06-17 00:41:39 -0700214 m532x_clk_init();
Greg Ungererc05793c2011-12-24 13:06:33 +1000215 m532x_uarts_init();
216 m532x_fec_init();
Steven King83ca6002012-05-06 12:22:53 -0700217#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
Greg Ungererc05793c2011-12-24 13:06:33 +1000218 m532x_qspi_init();
219#endif
Greg Ungerer35aefb22012-01-23 15:34:58 +1000220
Greg Ungererb2e18102008-02-01 17:34:58 +1000221#ifdef CONFIG_BDM_DISABLE
Greg Ungerer3196cf82006-06-26 10:33:10 +1000222 /*
223 * Disable the BDM clocking. This also turns off most of the rest of
224 * the BDM device. This is good for EMC reasons. This option is not
225 * incompatible with the memory protection option.
226 */
227 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
228#endif
229}
230
231/***************************************************************************/
Greg Ungererb2e18102008-02-01 17:34:58 +1000232/* Board initialization */
233/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000234/*
235 * PLL min/max specifications
236 */
237#define MAX_FVCO 500000 /* KHz */
238#define MAX_FSYS 80000 /* KHz */
239#define MIN_FSYS 58333 /* KHz */
240#define FREF 16000 /* KHz */
241
242
243#define MAX_MFD 135 /* Multiplier */
244#define MIN_MFD 88 /* Multiplier */
245#define BUSDIV 6 /* Divider */
246
247/*
248 * Low Power Divider specifications
249 */
250#define MIN_LPD (1 << 0) /* Divider (not encoded) */
251#define MAX_LPD (1 << 15) /* Divider (not encoded) */
252#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
253
254#define SYS_CLK_KHZ 80000
255#define SYSTEM_PERIOD 12.5
256/*
257 * SDRAM Timing Parameters
258 */
259#define SDRAM_BL 8 /* # of beats in a burst */
260#define SDRAM_TWR 2 /* in clocks */
261#define SDRAM_CASL 2.5 /* CASL in clocks */
262#define SDRAM_TRCD 2 /* in clocks */
263#define SDRAM_TRP 2 /* in clocks */
264#define SDRAM_TRFC 7 /* in clocks */
265#define SDRAM_TREFI 7800 /* in ns */
266
267#define EXT_SRAM_ADDRESS (0xC0000000)
268#define FLASH_ADDRESS (0x00000000)
269#define SDRAM_ADDRESS (0x40000000)
270
271#define NAND_FLASH_ADDRESS (0xD0000000)
272
273int sys_clk_khz = 0;
274int sys_clk_mhz = 0;
275
276void wtm_init(void);
277void scm_init(void);
278void gpio_init(void);
279void fbcs_init(void);
280void sdramc_init(void);
281int clock_pll (int fsys, int flags);
282int clock_limp (int);
283int clock_exit_limp (void);
284int get_sys_clock (void);
285
286asmlinkage void __init sysinit(void)
287{
288 sys_clk_khz = clock_pll(0, 0);
289 sys_clk_mhz = sys_clk_khz/1000;
290
291 wtm_init();
292 scm_init();
293 gpio_init();
294 fbcs_init();
295 sdramc_init();
296}
297
298void wtm_init(void)
299{
300 /* Disable watchdog timer */
301 MCF_WTM_WCR = 0;
302}
303
304#define MCF_SCM_BCR_GBW (0x00000100)
305#define MCF_SCM_BCR_GBR (0x00000200)
306
307void scm_init(void)
308{
309 /* All masters are trusted */
310 MCF_SCM_MPR = 0x77777777;
311
312 /* Allow supervisor/user, read/write, and trusted/untrusted
313 access to all slaves */
314 MCF_SCM_PACRA = 0;
315 MCF_SCM_PACRB = 0;
316 MCF_SCM_PACRC = 0;
317 MCF_SCM_PACRD = 0;
318 MCF_SCM_PACRE = 0;
319 MCF_SCM_PACRF = 0;
320
321 /* Enable bursts */
322 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
323}
324
325
326void fbcs_init(void)
327{
328 MCF_GPIO_PAR_CS = 0x0000003E;
329
330 /* Latch chip select */
331 MCF_FBCS1_CSAR = 0x10080000;
332
333 MCF_FBCS1_CSCR = 0x002A3780;
334 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
335
336 /* Initialize latch to drive signals to inactive states */
337 *((u16 *)(0x10080000)) = 0xFFFF;
338
339 /* External SRAM */
340 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
341 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
342 | MCF_FBCS_CSCR_AA
343 | MCF_FBCS_CSCR_SBM
344 | MCF_FBCS_CSCR_WS(1));
345 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
346 | MCF_FBCS_CSMR_V);
347
348 /* Boot Flash connected to FBCS0 */
349 MCF_FBCS0_CSAR = FLASH_ADDRESS;
350 MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
351 | MCF_FBCS_CSCR_BEM
352 | MCF_FBCS_CSCR_AA
353 | MCF_FBCS_CSCR_SBM
354 | MCF_FBCS_CSCR_WS(7));
355 MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
356 | MCF_FBCS_CSMR_V);
357}
358
359void sdramc_init(void)
360{
361 /*
362 * Check to see if the SDRAM has already been initialized
363 * by a run control tool
364 */
365 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
366 /* SDRAM chip select initialization */
367
368 /* Initialize SDRAM chip select */
369 MCF_SDRAMC_SDCS0 = (0
370 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
371 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
372
373 /*
374 * Basic configuration and initialization
375 */
376 MCF_SDRAMC_SDCFG1 = (0
377 | 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_SDCFG2 = (0
385 | 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
390
391 /*
392 * Precharge and enable write to SDMR
393 */
394 MCF_SDRAMC_SDCR = (0
395 | 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
403 /*
404 * Write extended mode register
405 */
406 MCF_SDRAMC_SDMR = (0
407 | MCF_SDRAMC_SDMR_BNKAD_LEMR
408 | MCF_SDRAMC_SDMR_AD(0x0)
409 | MCF_SDRAMC_SDMR_CMD);
410
411 /*
412 * Write mode register and reset DLL
413 */
414 MCF_SDRAMC_SDMR = (0
415 | MCF_SDRAMC_SDMR_BNKAD_LMR
416 | MCF_SDRAMC_SDMR_AD(0x163)
417 | MCF_SDRAMC_SDMR_CMD);
418
419 /*
420 * Execute a PALL command
421 */
422 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
423
424 /*
425 * Perform two REF cycles
426 */
427 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
428 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
429
430 /*
431 * Write mode register and clear reset DLL
432 */
433 MCF_SDRAMC_SDMR = (0
434 | MCF_SDRAMC_SDMR_BNKAD_LMR
435 | MCF_SDRAMC_SDMR_AD(0x063)
436 | MCF_SDRAMC_SDMR_CMD);
437
438 /*
439 * Enable auto refresh and lock SDMR
440 */
441 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
442 MCF_SDRAMC_SDCR |= (0
443 | MCF_SDRAMC_SDCR_REF
444 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
445 }
446}
447
448void gpio_init(void)
449{
450 /* Enable UART0 pins */
451 MCF_GPIO_PAR_UART = ( 0
452 | MCF_GPIO_PAR_UART_PAR_URXD0
453 | MCF_GPIO_PAR_UART_PAR_UTXD0);
454
455 /* Initialize TIN3 as a GPIO output to enable the write
456 half of the latch */
457 MCF_GPIO_PAR_TIMER = 0x00;
sfking@fdwdc.com7846fe82009-06-19 18:11:10 -0700458 __raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
459 __raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000460
461}
462
463int clock_pll(int fsys, int flags)
464{
465 int fref, temp, fout, mfd;
466 u32 i;
467
468 fref = FREF;
469
470 if (fsys == 0) {
471 /* Return current PLL output */
472 mfd = MCF_PLL_PFDR;
473
474 return (fref * mfd / (BUSDIV * 4));
475 }
476
477 /* Check bounds of requested system clock */
478 if (fsys > MAX_FSYS)
479 fsys = MAX_FSYS;
480 if (fsys < MIN_FSYS)
481 fsys = MIN_FSYS;
482
483 /* Multiplying by 100 when calculating the temp value,
484 and then dividing by 100 to calculate the mfd allows
485 for exact values without needing to include floating
486 point libraries. */
487 temp = 100 * fsys / fref;
488 mfd = 4 * BUSDIV * temp / 100;
489
490 /* Determine the output frequency for selected values */
491 fout = (fref * mfd / (BUSDIV * 4));
492
493 /*
494 * Check to see if the SDRAM has already been initialized.
495 * If it has then the SDRAM needs to be put into self refresh
496 * mode before reprogramming the PLL.
497 */
498 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
499 /* Put SDRAM into self refresh mode */
500 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
501
502 /*
503 * Initialize the PLL to generate the new system clock frequency.
504 * The device must be put into LIMP mode to reprogram the PLL.
505 */
506
507 /* Enter LIMP mode */
508 clock_limp(DEFAULT_LPD);
509
510 /* Reprogram PLL for desired fsys */
511 MCF_PLL_PODR = (0
512 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
513 | MCF_PLL_PODR_BUSDIV(BUSDIV));
514
515 MCF_PLL_PFDR = mfd;
516
517 /* Exit LIMP mode */
518 clock_exit_limp();
519
520 /*
521 * Return the SDRAM to normal operation if it is in use.
522 */
523 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
524 /* Exit self refresh mode */
525 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
526
527 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
528 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
529
530 /* wait for DQS logic to relock */
531 for (i = 0; i < 0x200; i++)
532 ;
533
534 return fout;
535}
536
537int clock_limp(int div)
538{
539 u32 temp;
540
541 /* Check bounds of divider */
542 if (div < MIN_LPD)
543 div = MIN_LPD;
544 if (div > MAX_LPD)
545 div = MAX_LPD;
546
547 /* Save of the current value of the SSIDIV so we don't
548 overwrite the value*/
549 temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
550
551 /* Apply the divider to the system clock */
552 MCF_CCM_CDR = ( 0
553 | MCF_CCM_CDR_LPDIV(div)
554 | MCF_CCM_CDR_SSIDIV(temp));
555
556 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
557
558 return (FREF/(3*(1 << div)));
559}
560
561int clock_exit_limp(void)
562{
563 int fout;
564
565 /* Exit LIMP mode */
566 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
567
568 /* Wait for PLL to lock */
569 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
570 ;
571
572 fout = get_sys_clock();
573
574 return fout;
575}
576
577int get_sys_clock(void)
578{
579 int divider;
580
581 /* Test to see if device is in LIMP mode */
582 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
583 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
584 return (FREF/(2 << divider));
585 }
586 else
587 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
588}