blob: 7951d1d43357a16ac953b584f71c5c7efd6bd526 [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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000307 writew(0, MCF_WTM_WCR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000308}
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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000316 writel(0x77777777, MCF_SCM_MPR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000317
318 /* Allow supervisor/user, read/write, and trusted/untrusted
319 access to all slaves */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000320 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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000326
327 /* Enable bursts */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000328 writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000329}
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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000337 writel(0x10080000, MCF_FBCS1_CSAR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000338
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000339 writel(0x002A3780, MCF_FBCS1_CSCR);
340 writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000341
342 /* Initialize latch to drive signals to inactive states */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000343 writew(0xffff, 0x10080000);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000344
345 /* External SRAM */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000346 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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000353
354 /* Boot Flash connected to FBCS0 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000355 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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000363}
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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000371 if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) {
Greg Ungerer3196cf82006-06-26 10:33:10 +1000372 /* SDRAM chip select initialization */
373
374 /* Initialize SDRAM chip select */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000375 writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) |
376 MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE),
377 MCF_SDRAMC_SDCS0);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000378
379 /*
380 * Basic configuration and initialization
381 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000382 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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000395
396
397 /*
398 * Precharge and enable write to SDMR
399 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000400 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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000408
409 /*
410 * Write extended mode register
411 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000412 writel(MCF_SDRAMC_SDMR_BNKAD_LEMR |
413 MCF_SDRAMC_SDMR_AD(0x0) |
414 MCF_SDRAMC_SDMR_CMD,
415 MCF_SDRAMC_SDMR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000416
417 /*
418 * Write mode register and reset DLL
419 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000420 writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
421 MCF_SDRAMC_SDMR_AD(0x163) |
422 MCF_SDRAMC_SDMR_CMD,
423 MCF_SDRAMC_SDMR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000424
425 /*
426 * Execute a PALL command
427 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000428 writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000429
430 /*
431 * Perform two REF cycles
432 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000433 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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000435
436 /*
437 * Write mode register and clear reset DLL
438 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000439 writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
440 MCF_SDRAMC_SDMR_AD(0x063) |
441 MCF_SDRAMC_SDMR_CMD,
442 MCF_SDRAMC_SDMR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000443
444 /*
445 * Enable auto refresh and lock SDMR
446 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000447 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);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000451 }
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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000478 mfd = readb(MCF_PLL_PFDR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000479
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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000504 if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000505 /* Put SDRAM into self refresh mode */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000506 writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE,
507 MCF_SDRAMC_SDCR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000508
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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000518 writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV),
519 MCF_PLL_PODR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000520
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000521 writeb(mfd, MCF_PLL_PFDR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000522
523 /* Exit LIMP mode */
524 clock_exit_limp();
525
526 /*
527 * Return the SDRAM to normal operation if it is in use.
528 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000529 if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000530 /* Exit self refresh mode */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000531 writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE,
532 MCF_SDRAMC_SDCR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000533
534 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000535 writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000536
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*/
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000556 temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000557
558 /* Apply the divider to the system clock */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000559 writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000560
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000561 writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000562
563 return (FREF/(3*(1 << div)));
564}
565
566int clock_exit_limp(void)
567{
568 int fout;
569
570 /* Exit LIMP mode */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000571 writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000572
573 /* Wait for PLL to lock */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000574 while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK))
Greg Ungerer3196cf82006-06-26 10:33:10 +1000575 ;
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 */
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000587 if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) {
588 divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000589 return (FREF/(2 << divider));
590 }
591 else
Greg Ungerer6d8a1392012-09-17 16:16:19 +1000592 return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000593}