1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /***************************************************************************/ |
3 | |
4 | /* |
5 | * m53xx.c -- platform support for ColdFire 53xx based boards |
6 | * |
7 | * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) |
8 | * Copyright (C) 2000, Lineo (www.lineo.com) |
9 | * Yaroslav Vinogradov yaroslav.vinogradov@freescale.com |
10 | * Copyright Freescale Semiconductor, Inc 2006 |
11 | * Copyright (c) 2006, emlix, Sebastian Hess <shess@hessware.de> |
12 | */ |
13 | |
14 | /***************************************************************************/ |
15 | |
16 | #include <linux/clkdev.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/param.h> |
19 | #include <linux/init.h> |
20 | #include <linux/io.h> |
21 | #include <asm/machdep.h> |
22 | #include <asm/coldfire.h> |
23 | #include <asm/mcfsim.h> |
24 | #include <asm/mcfuart.h> |
25 | #include <asm/mcfdma.h> |
26 | #include <asm/mcfwdebug.h> |
27 | #include <asm/mcfclk.h> |
28 | |
29 | /***************************************************************************/ |
30 | |
31 | DEFINE_CLK(0, "flexbus" , 2, MCF_CLK); |
32 | DEFINE_CLK(0, "mcfcan.0" , 8, MCF_CLK); |
33 | DEFINE_CLK(0, "fec.0" , 12, MCF_CLK); |
34 | DEFINE_CLK(0, "edma" , 17, MCF_CLK); |
35 | DEFINE_CLK(0, "intc.0" , 18, MCF_CLK); |
36 | DEFINE_CLK(0, "intc.1" , 19, MCF_CLK); |
37 | DEFINE_CLK(0, "iack.0" , 21, MCF_CLK); |
38 | DEFINE_CLK(0, "imx1-i2c.0" , 22, MCF_CLK); |
39 | DEFINE_CLK(0, "mcfqspi.0" , 23, MCF_CLK); |
40 | DEFINE_CLK(0, "mcfuart.0" , 24, MCF_BUSCLK); |
41 | DEFINE_CLK(0, "mcfuart.1" , 25, MCF_BUSCLK); |
42 | DEFINE_CLK(0, "mcfuart.2" , 26, MCF_BUSCLK); |
43 | DEFINE_CLK(0, "mcftmr.0" , 28, MCF_CLK); |
44 | DEFINE_CLK(0, "mcftmr.1" , 29, MCF_CLK); |
45 | DEFINE_CLK(0, "mcftmr.2" , 30, MCF_CLK); |
46 | DEFINE_CLK(0, "mcftmr.3" , 31, MCF_CLK); |
47 | |
48 | DEFINE_CLK(0, "mcfpit.0" , 32, MCF_CLK); |
49 | DEFINE_CLK(0, "mcfpit.1" , 33, MCF_CLK); |
50 | DEFINE_CLK(0, "mcfpit.2" , 34, MCF_CLK); |
51 | DEFINE_CLK(0, "mcfpit.3" , 35, MCF_CLK); |
52 | DEFINE_CLK(0, "mcfpwm.0" , 36, MCF_CLK); |
53 | DEFINE_CLK(0, "mcfeport.0" , 37, MCF_CLK); |
54 | DEFINE_CLK(0, "mcfwdt.0" , 38, MCF_CLK); |
55 | DEFINE_CLK(0, "sys.0" , 40, MCF_BUSCLK); |
56 | DEFINE_CLK(0, "gpio.0" , 41, MCF_BUSCLK); |
57 | DEFINE_CLK(0, "mcfrtc.0" , 42, MCF_CLK); |
58 | DEFINE_CLK(0, "mcflcd.0" , 43, MCF_CLK); |
59 | DEFINE_CLK(0, "mcfusb-otg.0" , 44, MCF_CLK); |
60 | DEFINE_CLK(0, "mcfusb-host.0" , 45, MCF_CLK); |
61 | DEFINE_CLK(0, "sdram.0" , 46, MCF_CLK); |
62 | DEFINE_CLK(0, "ssi.0" , 47, MCF_CLK); |
63 | DEFINE_CLK(0, "pll.0" , 48, MCF_CLK); |
64 | |
65 | DEFINE_CLK(1, "mdha.0" , 32, MCF_CLK); |
66 | DEFINE_CLK(1, "skha.0" , 33, MCF_CLK); |
67 | DEFINE_CLK(1, "rng.0" , 34, MCF_CLK); |
68 | |
69 | static struct clk_lookup m53xx_clk_lookup[] = { |
70 | CLKDEV_INIT("flexbus" , NULL, &__clk_0_2), |
71 | CLKDEV_INIT("mcfcan.0" , NULL, &__clk_0_8), |
72 | CLKDEV_INIT("fec.0" , NULL, &__clk_0_12), |
73 | CLKDEV_INIT("edma" , NULL, &__clk_0_17), |
74 | CLKDEV_INIT("intc.0" , NULL, &__clk_0_18), |
75 | CLKDEV_INIT("intc.1" , NULL, &__clk_0_19), |
76 | CLKDEV_INIT("iack.0" , NULL, &__clk_0_21), |
77 | CLKDEV_INIT("imx1-i2c.0" , NULL, &__clk_0_22), |
78 | CLKDEV_INIT("mcfqspi.0" , NULL, &__clk_0_23), |
79 | CLKDEV_INIT("mcfuart.0" , NULL, &__clk_0_24), |
80 | CLKDEV_INIT("mcfuart.1" , NULL, &__clk_0_25), |
81 | CLKDEV_INIT("mcfuart.2" , NULL, &__clk_0_26), |
82 | CLKDEV_INIT("mcftmr.0" , NULL, &__clk_0_28), |
83 | CLKDEV_INIT("mcftmr.1" , NULL, &__clk_0_29), |
84 | CLKDEV_INIT("mcftmr.2" , NULL, &__clk_0_30), |
85 | CLKDEV_INIT("mcftmr.3" , NULL, &__clk_0_31), |
86 | CLKDEV_INIT("mcfpit.0" , NULL, &__clk_0_32), |
87 | CLKDEV_INIT("mcfpit.1" , NULL, &__clk_0_33), |
88 | CLKDEV_INIT("mcfpit.2" , NULL, &__clk_0_34), |
89 | CLKDEV_INIT("mcfpit.3" , NULL, &__clk_0_35), |
90 | CLKDEV_INIT("mcfpwm.0" , NULL, &__clk_0_36), |
91 | CLKDEV_INIT("mcfeport.0" , NULL, &__clk_0_37), |
92 | CLKDEV_INIT("mcfwdt.0" , NULL, &__clk_0_38), |
93 | CLKDEV_INIT(NULL, "sys.0" , &__clk_0_40), |
94 | CLKDEV_INIT("gpio.0" , NULL, &__clk_0_41), |
95 | CLKDEV_INIT("mcfrtc.0" , NULL, &__clk_0_42), |
96 | CLKDEV_INIT("mcflcd.0" , NULL, &__clk_0_43), |
97 | CLKDEV_INIT("mcfusb-otg.0" , NULL, &__clk_0_44), |
98 | CLKDEV_INIT("mcfusb-host.0" , NULL, &__clk_0_45), |
99 | CLKDEV_INIT("sdram.0" , NULL, &__clk_0_46), |
100 | CLKDEV_INIT("ssi.0" , NULL, &__clk_0_47), |
101 | CLKDEV_INIT(NULL, "pll.0" , &__clk_0_48), |
102 | CLKDEV_INIT("mdha.0" , NULL, &__clk_1_32), |
103 | CLKDEV_INIT("skha.0" , NULL, &__clk_1_33), |
104 | CLKDEV_INIT("rng.0" , NULL, &__clk_1_34), |
105 | }; |
106 | |
107 | static struct clk * const enable_clks[] __initconst = { |
108 | &__clk_0_2, /* flexbus */ |
109 | &__clk_0_18, /* intc.0 */ |
110 | &__clk_0_19, /* intc.1 */ |
111 | &__clk_0_21, /* iack.0 */ |
112 | &__clk_0_24, /* mcfuart.0 */ |
113 | &__clk_0_25, /* mcfuart.1 */ |
114 | &__clk_0_26, /* mcfuart.2 */ |
115 | &__clk_0_28, /* mcftmr.0 */ |
116 | &__clk_0_29, /* mcftmr.1 */ |
117 | &__clk_0_32, /* mcfpit.0 */ |
118 | &__clk_0_33, /* mcfpit.1 */ |
119 | &__clk_0_37, /* mcfeport.0 */ |
120 | &__clk_0_40, /* sys.0 */ |
121 | &__clk_0_41, /* gpio.0 */ |
122 | &__clk_0_46, /* sdram.0 */ |
123 | &__clk_0_48, /* pll.0 */ |
124 | }; |
125 | |
126 | static struct clk * const disable_clks[] __initconst = { |
127 | &__clk_0_8, /* mcfcan.0 */ |
128 | &__clk_0_12, /* fec.0 */ |
129 | &__clk_0_17, /* edma */ |
130 | &__clk_0_22, /* imx1-i2c.0 */ |
131 | &__clk_0_23, /* mcfqspi.0 */ |
132 | &__clk_0_30, /* mcftmr.2 */ |
133 | &__clk_0_31, /* mcftmr.3 */ |
134 | &__clk_0_34, /* mcfpit.2 */ |
135 | &__clk_0_35, /* mcfpit.3 */ |
136 | &__clk_0_36, /* mcfpwm.0 */ |
137 | &__clk_0_38, /* mcfwdt.0 */ |
138 | &__clk_0_42, /* mcfrtc.0 */ |
139 | &__clk_0_43, /* mcflcd.0 */ |
140 | &__clk_0_44, /* mcfusb-otg.0 */ |
141 | &__clk_0_45, /* mcfusb-host.0 */ |
142 | &__clk_0_47, /* ssi.0 */ |
143 | &__clk_1_32, /* mdha.0 */ |
144 | &__clk_1_33, /* skha.0 */ |
145 | &__clk_1_34, /* rng.0 */ |
146 | }; |
147 | |
148 | |
149 | static void __init m53xx_clk_init(void) |
150 | { |
151 | unsigned i; |
152 | |
153 | /* make sure these clocks are enabled */ |
154 | for (i = 0; i < ARRAY_SIZE(enable_clks); ++i) |
155 | __clk_init_enabled(enable_clks[i]); |
156 | /* make sure these clocks are disabled */ |
157 | for (i = 0; i < ARRAY_SIZE(disable_clks); ++i) |
158 | __clk_init_disabled(disable_clks[i]); |
159 | |
160 | clkdev_add_table(m53xx_clk_lookup, ARRAY_SIZE(m53xx_clk_lookup)); |
161 | } |
162 | |
163 | /***************************************************************************/ |
164 | |
165 | static void __init m53xx_qspi_init(void) |
166 | { |
167 | #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) |
168 | /* setup QSPS pins for QSPI with gpio CS control */ |
169 | writew(0x01f0, MCFGPIO_PAR_QSPI); |
170 | #endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */ |
171 | } |
172 | |
173 | /***************************************************************************/ |
174 | |
175 | static void __init m53xx_i2c_init(void) |
176 | { |
177 | #if IS_ENABLED(CONFIG_I2C_IMX) |
178 | /* setup Port AS Pin Assignment Register for I2C */ |
179 | /* set PASPA0 to SCL and PASPA1 to SDA */ |
180 | u8 r = readb(MCFGPIO_PAR_FECI2C); |
181 | r |= 0x0f; |
182 | writeb(r, MCFGPIO_PAR_FECI2C); |
183 | #endif /* IS_ENABLED(CONFIG_I2C_IMX) */ |
184 | } |
185 | |
186 | /***************************************************************************/ |
187 | |
188 | static void __init m53xx_uarts_init(void) |
189 | { |
190 | /* UART GPIO initialization */ |
191 | writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART); |
192 | } |
193 | |
194 | /***************************************************************************/ |
195 | |
196 | static void __init m53xx_fec_init(void) |
197 | { |
198 | u8 v; |
199 | |
200 | /* Set multi-function pins to ethernet mode for fec0 */ |
201 | v = readb(MCFGPIO_PAR_FECI2C); |
202 | v |= MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC | |
203 | MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO; |
204 | writeb(v, MCFGPIO_PAR_FECI2C); |
205 | |
206 | v = readb(MCFGPIO_PAR_FEC); |
207 | v = MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC; |
208 | writeb(v, MCFGPIO_PAR_FEC); |
209 | } |
210 | |
211 | /***************************************************************************/ |
212 | |
213 | void __init config_BSP(char *commandp, int size) |
214 | { |
215 | #if !defined(CONFIG_BOOTPARAM) |
216 | /* Copy command line from FLASH to local buffer... */ |
217 | memcpy(commandp, (char *) 0x4000, 4); |
218 | if(strncmp(commandp, "kcl " , 4) == 0){ |
219 | memcpy(commandp, (char *) 0x4004, size); |
220 | commandp[size-1] = 0; |
221 | } else { |
222 | memset(commandp, 0, size); |
223 | } |
224 | #endif |
225 | mach_sched_init = hw_timer_init; |
226 | m53xx_clk_init(); |
227 | m53xx_uarts_init(); |
228 | m53xx_fec_init(); |
229 | m53xx_qspi_init(); |
230 | m53xx_i2c_init(); |
231 | |
232 | #ifdef CONFIG_BDM_DISABLE |
233 | /* |
234 | * Disable the BDM clocking. This also turns off most of the rest of |
235 | * the BDM device. This is good for EMC reasons. This option is not |
236 | * incompatible with the memory protection option. |
237 | */ |
238 | wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); |
239 | #endif |
240 | } |
241 | |
242 | /***************************************************************************/ |
243 | /* Board initialization */ |
244 | /***************************************************************************/ |
245 | /* |
246 | * PLL min/max specifications |
247 | */ |
248 | #define MAX_FVCO 500000 /* KHz */ |
249 | #define MAX_FSYS 80000 /* KHz */ |
250 | #define MIN_FSYS 58333 /* KHz */ |
251 | #define FREF 16000 /* KHz */ |
252 | |
253 | |
254 | #define MAX_MFD 135 /* Multiplier */ |
255 | #define MIN_MFD 88 /* Multiplier */ |
256 | #define BUSDIV 6 /* Divider */ |
257 | |
258 | /* |
259 | * Low Power Divider specifications |
260 | */ |
261 | #define MIN_LPD (1 << 0) /* Divider (not encoded) */ |
262 | #define MAX_LPD (1 << 15) /* Divider (not encoded) */ |
263 | #define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */ |
264 | |
265 | #define SYS_CLK_KHZ 80000 |
266 | #define SYSTEM_PERIOD 12.5 |
267 | /* |
268 | * SDRAM Timing Parameters |
269 | */ |
270 | #define SDRAM_BL 8 /* # of beats in a burst */ |
271 | #define SDRAM_TWR 2 /* in clocks */ |
272 | #define SDRAM_CASL 2.5 /* CASL in clocks */ |
273 | #define SDRAM_TRCD 2 /* in clocks */ |
274 | #define SDRAM_TRP 2 /* in clocks */ |
275 | #define SDRAM_TRFC 7 /* in clocks */ |
276 | #define SDRAM_TREFI 7800 /* in ns */ |
277 | |
278 | #define EXT_SRAM_ADDRESS (0xC0000000) |
279 | #define FLASH_ADDRESS (0x00000000) |
280 | #define SDRAM_ADDRESS (0x40000000) |
281 | |
282 | #define NAND_FLASH_ADDRESS (0xD0000000) |
283 | |
284 | void wtm_init(void); |
285 | void scm_init(void); |
286 | void gpio_init(void); |
287 | void fbcs_init(void); |
288 | void sdramc_init(void); |
289 | int clock_pll (int fsys, int flags); |
290 | int clock_limp (int); |
291 | int clock_exit_limp (void); |
292 | int get_sys_clock (void); |
293 | |
294 | asmlinkage void __init sysinit(void) |
295 | { |
296 | clock_pll(fsys: 0, flags: 0); |
297 | |
298 | wtm_init(); |
299 | scm_init(); |
300 | gpio_init(); |
301 | fbcs_init(); |
302 | sdramc_init(); |
303 | } |
304 | |
305 | void wtm_init(void) |
306 | { |
307 | /* Disable watchdog timer */ |
308 | writew(0, MCF_WTM_WCR); |
309 | } |
310 | |
311 | #define MCF_SCM_BCR_GBW (0x00000100) |
312 | #define MCF_SCM_BCR_GBR (0x00000200) |
313 | |
314 | void scm_init(void) |
315 | { |
316 | /* All masters are trusted */ |
317 | writel(0x77777777, MCF_SCM_MPR); |
318 | |
319 | /* Allow supervisor/user, read/write, and trusted/untrusted |
320 | access to all slaves */ |
321 | writel(0, MCF_SCM_PACRA); |
322 | writel(0, MCF_SCM_PACRB); |
323 | writel(0, MCF_SCM_PACRC); |
324 | writel(0, MCF_SCM_PACRD); |
325 | writel(0, MCF_SCM_PACRE); |
326 | writel(0, MCF_SCM_PACRF); |
327 | |
328 | /* Enable bursts */ |
329 | writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR); |
330 | } |
331 | |
332 | |
333 | void fbcs_init(void) |
334 | { |
335 | writeb(0x3E, MCFGPIO_PAR_CS); |
336 | |
337 | /* Latch chip select */ |
338 | writel(0x10080000, MCF_FBCS1_CSAR); |
339 | |
340 | writel(0x002A3780, MCF_FBCS1_CSCR); |
341 | writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR); |
342 | |
343 | /* Initialize latch to drive signals to inactive states */ |
344 | writew(val: 0xffff, addr: 0x10080000); |
345 | |
346 | /* External SRAM */ |
347 | writel(EXT_SRAM_ADDRESS, MCF_FBCS1_CSAR); |
348 | writel(MCF_FBCS_CSCR_PS_16 | |
349 | MCF_FBCS_CSCR_AA | |
350 | MCF_FBCS_CSCR_SBM | |
351 | MCF_FBCS_CSCR_WS(1), |
352 | MCF_FBCS1_CSCR); |
353 | writel(MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR); |
354 | |
355 | /* Boot Flash connected to FBCS0 */ |
356 | writel(FLASH_ADDRESS, MCF_FBCS0_CSAR); |
357 | writel(MCF_FBCS_CSCR_PS_16 | |
358 | MCF_FBCS_CSCR_BEM | |
359 | MCF_FBCS_CSCR_AA | |
360 | MCF_FBCS_CSCR_SBM | |
361 | MCF_FBCS_CSCR_WS(7), |
362 | MCF_FBCS0_CSCR); |
363 | writel(MCF_FBCS_CSMR_BAM_32M | MCF_FBCS_CSMR_V, MCF_FBCS0_CSMR); |
364 | } |
365 | |
366 | void sdramc_init(void) |
367 | { |
368 | /* |
369 | * Check to see if the SDRAM has already been initialized |
370 | * by a run control tool |
371 | */ |
372 | if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) { |
373 | /* SDRAM chip select initialization */ |
374 | |
375 | /* Initialize SDRAM chip select */ |
376 | writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) | |
377 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE), |
378 | MCF_SDRAMC_SDCS0); |
379 | |
380 | /* |
381 | * Basic configuration and initialization |
382 | */ |
383 | writel(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_SDCFG1); |
391 | writel(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 | MCF_SDRAMC_SDCFG2); |
396 | |
397 | |
398 | /* |
399 | * Precharge and enable write to SDMR |
400 | */ |
401 | writel(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 | MCF_SDRAMC_SDCR); |
409 | |
410 | /* |
411 | * Write extended mode register |
412 | */ |
413 | writel(MCF_SDRAMC_SDMR_BNKAD_LEMR | |
414 | MCF_SDRAMC_SDMR_AD(0x0) | |
415 | MCF_SDRAMC_SDMR_CMD, |
416 | MCF_SDRAMC_SDMR); |
417 | |
418 | /* |
419 | * Write mode register and reset DLL |
420 | */ |
421 | writel(MCF_SDRAMC_SDMR_BNKAD_LMR | |
422 | MCF_SDRAMC_SDMR_AD(0x163) | |
423 | MCF_SDRAMC_SDMR_CMD, |
424 | MCF_SDRAMC_SDMR); |
425 | |
426 | /* |
427 | * Execute a PALL command |
428 | */ |
429 | writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR); |
430 | |
431 | /* |
432 | * Perform two REF cycles |
433 | */ |
434 | writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR); |
435 | writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR); |
436 | |
437 | /* |
438 | * Write mode register and clear reset DLL |
439 | */ |
440 | writel(MCF_SDRAMC_SDMR_BNKAD_LMR | |
441 | MCF_SDRAMC_SDMR_AD(0x063) | |
442 | MCF_SDRAMC_SDMR_CMD, |
443 | MCF_SDRAMC_SDMR); |
444 | |
445 | /* |
446 | * Enable auto refresh and lock SDMR |
447 | */ |
448 | writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_MODE_EN, |
449 | MCF_SDRAMC_SDCR); |
450 | writel(MCF_SDRAMC_SDCR_REF | MCF_SDRAMC_SDCR_DQS_OE(0xC), |
451 | MCF_SDRAMC_SDCR); |
452 | } |
453 | } |
454 | |
455 | void gpio_init(void) |
456 | { |
457 | /* Enable UART0 pins */ |
458 | writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0, |
459 | MCFGPIO_PAR_UART); |
460 | |
461 | /* |
462 | * Initialize TIN3 as a GPIO output to enable the write |
463 | * half of the latch. |
464 | */ |
465 | writeb(0x00, MCFGPIO_PAR_TIMER); |
466 | writeb(0x08, MCFGPIO_PDDR_TIMER); |
467 | writeb(0x00, MCFGPIO_PCLRR_TIMER); |
468 | } |
469 | |
470 | int clock_pll(int fsys, int flags) |
471 | { |
472 | int fref, temp, fout, mfd; |
473 | u32 i; |
474 | |
475 | fref = FREF; |
476 | |
477 | if (fsys == 0) { |
478 | /* Return current PLL output */ |
479 | mfd = readb(MCF_PLL_PFDR); |
480 | |
481 | return (fref * mfd / (BUSDIV * 4)); |
482 | } |
483 | |
484 | /* Check bounds of requested system clock */ |
485 | if (fsys > MAX_FSYS) |
486 | fsys = MAX_FSYS; |
487 | if (fsys < MIN_FSYS) |
488 | fsys = MIN_FSYS; |
489 | |
490 | /* Multiplying by 100 when calculating the temp value, |
491 | and then dividing by 100 to calculate the mfd allows |
492 | for exact values without needing to include floating |
493 | point libraries. */ |
494 | temp = 100 * fsys / fref; |
495 | mfd = 4 * BUSDIV * temp / 100; |
496 | |
497 | /* Determine the output frequency for selected values */ |
498 | fout = (fref * mfd / (BUSDIV * 4)); |
499 | |
500 | /* |
501 | * Check to see if the SDRAM has already been initialized. |
502 | * If it has then the SDRAM needs to be put into self refresh |
503 | * mode before reprogramming the PLL. |
504 | */ |
505 | if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF) |
506 | /* Put SDRAM into self refresh mode */ |
507 | writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE, |
508 | MCF_SDRAMC_SDCR); |
509 | |
510 | /* |
511 | * Initialize the PLL to generate the new system clock frequency. |
512 | * The device must be put into LIMP mode to reprogram the PLL. |
513 | */ |
514 | |
515 | /* Enter LIMP mode */ |
516 | clock_limp(DEFAULT_LPD); |
517 | |
518 | /* Reprogram PLL for desired fsys */ |
519 | writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV), |
520 | MCF_PLL_PODR); |
521 | |
522 | writeb(mfd, MCF_PLL_PFDR); |
523 | |
524 | /* Exit LIMP mode */ |
525 | clock_exit_limp(); |
526 | |
527 | /* |
528 | * Return the SDRAM to normal operation if it is in use. |
529 | */ |
530 | if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF) |
531 | /* Exit self refresh mode */ |
532 | writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE, |
533 | MCF_SDRAMC_SDCR); |
534 | |
535 | /* Errata - workaround for SDRAM operation after exiting LIMP mode */ |
536 | writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX); |
537 | |
538 | /* wait for DQS logic to relock */ |
539 | for (i = 0; i < 0x200; i++) |
540 | ; |
541 | |
542 | return fout; |
543 | } |
544 | |
545 | int clock_limp(int div) |
546 | { |
547 | u32 temp; |
548 | |
549 | /* Check bounds of divider */ |
550 | if (div < MIN_LPD) |
551 | div = MIN_LPD; |
552 | if (div > MAX_LPD) |
553 | div = MAX_LPD; |
554 | |
555 | /* Save of the current value of the SSIDIV so we don't |
556 | overwrite the value*/ |
557 | temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF); |
558 | |
559 | /* Apply the divider to the system clock */ |
560 | writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR); |
561 | |
562 | writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR); |
563 | |
564 | return (FREF/(3*(1 << div))); |
565 | } |
566 | |
567 | int clock_exit_limp(void) |
568 | { |
569 | int fout; |
570 | |
571 | /* Exit LIMP mode */ |
572 | writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR); |
573 | |
574 | /* Wait for PLL to lock */ |
575 | while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK)) |
576 | ; |
577 | |
578 | fout = get_sys_clock(); |
579 | |
580 | return fout; |
581 | } |
582 | |
583 | int get_sys_clock(void) |
584 | { |
585 | int divider; |
586 | |
587 | /* Test to see if device is in LIMP mode */ |
588 | if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) { |
589 | divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF); |
590 | return (FREF/(2 << divider)); |
591 | } |
592 | else |
593 | return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4); |
594 | } |
595 | |