blob: 0adeef17fd4122ad950b5164fa4b22f0022428e6 [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 */
Greg Ungerere4c2b9b2012-09-17 15:26:25 +1000175 writew(0x01f0, MCFGPIO_PAR_QSPI);
Steven King91d60412010-01-22 12:43:03 -0800176}
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 */
Greg Ungerere4c2b9b2012-09-17 15:26:25 +1000185 writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART);
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 Ungerere4c2b9b2012-09-17 15:26:25 +1000192 u8 v;
193
Greg Ungererffba3f42009-02-26 22:40:38 -0800194 /* Set multi-function pins to ethernet mode for fec0 */
Greg Ungerere4c2b9b2012-09-17 15:26:25 +1000195 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);
Greg Ungererffba3f42009-02-26 22:40:38 -0800203}
Greg Ungerer3196cf82006-06-26 10:33:10 +1000204
205/***************************************************************************/
206
Greg Ungererb2e18102008-02-01 17:34:58 +1000207void __init config_BSP(char *commandp, int size)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000208{
Greg Ungererbc724502007-07-25 22:07:20 +1000209#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000210 /* 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
Greg Ungerer35aefb22012-01-23 15:34:58 +1000219 mach_sched_init = hw_timer_init;
Steven King12ce4c12012-06-17 00:41:39 -0700220 m532x_clk_init();
Greg Ungererc05793c2011-12-24 13:06:33 +1000221 m532x_uarts_init();
222 m532x_fec_init();
Steven King83ca6002012-05-06 12:22:53 -0700223#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
Greg Ungererc05793c2011-12-24 13:06:33 +1000224 m532x_qspi_init();
225#endif
Greg Ungerer35aefb22012-01-23 15:34:58 +1000226
Greg Ungererb2e18102008-02-01 17:34:58 +1000227#ifdef CONFIG_BDM_DISABLE
Greg Ungerer3196cf82006-06-26 10:33:10 +1000228 /*
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/***************************************************************************/
Greg Ungererb2e18102008-02-01 17:34:58 +1000238/* Board initialization */
239/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000240/*
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 MCF_WTM_WCR = 0;
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 MCF_SCM_MPR = 0x77777777;
317
318 /* Allow supervisor/user, read/write, and trusted/untrusted
319 access to all slaves */
320 MCF_SCM_PACRA = 0;
321 MCF_SCM_PACRB = 0;
322 MCF_SCM_PACRC = 0;
323 MCF_SCM_PACRD = 0;
324 MCF_SCM_PACRE = 0;
325 MCF_SCM_PACRF = 0;
326
327 /* Enable bursts */
328 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
329}
330
331
332void fbcs_init(void)
333{
Greg Ungerere4c2b9b2012-09-17 15:26:25 +1000334 writeb(0x3E, MCFGPIO_PAR_CS);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000335
336 /* Latch chip select */
337 MCF_FBCS1_CSAR = 0x10080000;
338
339 MCF_FBCS1_CSCR = 0x002A3780;
340 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
341
342 /* Initialize latch to drive signals to inactive states */
343 *((u16 *)(0x10080000)) = 0xFFFF;
344
345 /* External SRAM */
346 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
347 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
348 | MCF_FBCS_CSCR_AA
349 | MCF_FBCS_CSCR_SBM
350 | MCF_FBCS_CSCR_WS(1));
351 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
352 | MCF_FBCS_CSMR_V);
353
354 /* Boot Flash connected to FBCS0 */
355 MCF_FBCS0_CSAR = FLASH_ADDRESS;
356 MCF_FBCS0_CSCR = (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_CSMR = (MCF_FBCS_CSMR_BAM_32M
362 | MCF_FBCS_CSMR_V);
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 (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
372 /* SDRAM chip select initialization */
373
374 /* Initialize SDRAM chip select */
375 MCF_SDRAMC_SDCS0 = (0
376 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
377 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
378
379 /*
380 * Basic configuration and initialization
381 */
382 MCF_SDRAMC_SDCFG1 = (0
383 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
384 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
385 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
386 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
387 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
388 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
389 | MCF_SDRAMC_SDCFG1_WTLAT(3));
390 MCF_SDRAMC_SDCFG2 = (0
391 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
392 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
393 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
394 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
395
396
397 /*
398 * Precharge and enable write to SDMR
399 */
400 MCF_SDRAMC_SDCR = (0
401 | MCF_SDRAMC_SDCR_MODE_EN
402 | MCF_SDRAMC_SDCR_CKE
403 | MCF_SDRAMC_SDCR_DDR
404 | MCF_SDRAMC_SDCR_MUX(1)
405 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
406 | MCF_SDRAMC_SDCR_PS_16
407 | MCF_SDRAMC_SDCR_IPALL);
408
409 /*
410 * Write extended mode register
411 */
412 MCF_SDRAMC_SDMR = (0
413 | MCF_SDRAMC_SDMR_BNKAD_LEMR
414 | MCF_SDRAMC_SDMR_AD(0x0)
415 | MCF_SDRAMC_SDMR_CMD);
416
417 /*
418 * Write mode register and reset DLL
419 */
420 MCF_SDRAMC_SDMR = (0
421 | MCF_SDRAMC_SDMR_BNKAD_LMR
422 | MCF_SDRAMC_SDMR_AD(0x163)
423 | MCF_SDRAMC_SDMR_CMD);
424
425 /*
426 * Execute a PALL command
427 */
428 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
429
430 /*
431 * Perform two REF cycles
432 */
433 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
434 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
435
436 /*
437 * Write mode register and clear reset DLL
438 */
439 MCF_SDRAMC_SDMR = (0
440 | MCF_SDRAMC_SDMR_BNKAD_LMR
441 | MCF_SDRAMC_SDMR_AD(0x063)
442 | MCF_SDRAMC_SDMR_CMD);
443
444 /*
445 * Enable auto refresh and lock SDMR
446 */
447 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
448 MCF_SDRAMC_SDCR |= (0
449 | MCF_SDRAMC_SDCR_REF
450 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
451 }
452}
453
454void gpio_init(void)
455{
456 /* Enable UART0 pins */
Greg Ungerere4c2b9b2012-09-17 15:26:25 +1000457 writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0,
458 MCFGPIO_PAR_UART);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000459
Greg Ungerere4c2b9b2012-09-17 15:26:25 +1000460 /*
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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000467}
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 = 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 (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
505 /* Put SDRAM into self refresh mode */
506 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
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 MCF_PLL_PODR = (0
518 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
519 | MCF_PLL_PODR_BUSDIV(BUSDIV));
520
521 MCF_PLL_PFDR = mfd;
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 (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
530 /* Exit self refresh mode */
531 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
532
533 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
534 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
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 = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
556
557 /* Apply the divider to the system clock */
558 MCF_CCM_CDR = ( 0
559 | MCF_CCM_CDR_LPDIV(div)
560 | MCF_CCM_CDR_SSIDIV(temp));
561
562 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
563
564 return (FREF/(3*(1 << div)));
565}
566
567int clock_exit_limp(void)
568{
569 int fout;
570
571 /* Exit LIMP mode */
572 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
573
574 /* Wait for PLL to lock */
575 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
576 ;
577
578 fout = get_sys_clock();
579
580 return fout;
581}
582
583int get_sys_clock(void)
584{
585 int divider;
586
587 /* Test to see if device is in LIMP mode */
588 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
589 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
590 return (FREF/(2 << divider));
591 }
592 else
593 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
594}