ext3: Flush disk caches on fsync when needed
[deliverable/linux.git] / arch / m68knommu / platform / 532x / config.c
1 /***************************************************************************/
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
10 * Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.com>
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/interrupt.h>
24 #include <linux/io.h>
25 #include <asm/machdep.h>
26 #include <asm/coldfire.h>
27 #include <asm/mcfsim.h>
28 #include <asm/mcfuart.h>
29 #include <asm/mcfdma.h>
30 #include <asm/mcfwdebug.h>
31
32 /***************************************************************************/
33
34 extern unsigned int mcf_timervector;
35 extern unsigned int mcf_profilevector;
36 extern unsigned int mcf_timerlevel;
37
38 /***************************************************************************/
39
40 static struct mcf_platform_uart m532x_uart_platform[] = {
41 {
42 .mapbase = MCFUART_BASE1,
43 .irq = MCFINT_VECBASE + MCFINT_UART0,
44 },
45 {
46 .mapbase = MCFUART_BASE2,
47 .irq = MCFINT_VECBASE + MCFINT_UART1,
48 },
49 {
50 .mapbase = MCFUART_BASE3,
51 .irq = MCFINT_VECBASE + MCFINT_UART2,
52 },
53 { },
54 };
55
56 static struct platform_device m532x_uart = {
57 .name = "mcfuart",
58 .id = 0,
59 .dev.platform_data = m532x_uart_platform,
60 };
61
62 static struct resource m532x_fec_resources[] = {
63 {
64 .start = 0xfc030000,
65 .end = 0xfc0307ff,
66 .flags = IORESOURCE_MEM,
67 },
68 {
69 .start = 64 + 36,
70 .end = 64 + 36,
71 .flags = IORESOURCE_IRQ,
72 },
73 {
74 .start = 64 + 40,
75 .end = 64 + 40,
76 .flags = IORESOURCE_IRQ,
77 },
78 {
79 .start = 64 + 42,
80 .end = 64 + 42,
81 .flags = IORESOURCE_IRQ,
82 },
83 };
84
85 static struct platform_device m532x_fec = {
86 .name = "fec",
87 .id = 0,
88 .num_resources = ARRAY_SIZE(m532x_fec_resources),
89 .resource = m532x_fec_resources,
90 };
91 static struct platform_device *m532x_devices[] __initdata = {
92 &m532x_uart,
93 &m532x_fec,
94 };
95
96 /***************************************************************************/
97
98 static void __init m532x_uart_init_line(int line, int irq)
99 {
100 if (line == 0) {
101 MCF_INTC0_ICR26 = 0x3;
102 MCF_INTC0_CIMR = 26;
103 /* GPIO initialization */
104 MCF_GPIO_PAR_UART |= 0x000F;
105 } else if (line == 1) {
106 MCF_INTC0_ICR27 = 0x3;
107 MCF_INTC0_CIMR = 27;
108 /* GPIO initialization */
109 MCF_GPIO_PAR_UART |= 0x0FF0;
110 } else if (line == 2) {
111 MCF_INTC0_ICR28 = 0x3;
112 MCF_INTC0_CIMR = 28;
113 }
114 }
115
116 static void __init m532x_uarts_init(void)
117 {
118 const int nrlines = ARRAY_SIZE(m532x_uart_platform);
119 int line;
120
121 for (line = 0; (line < nrlines); line++)
122 m532x_uart_init_line(line, m532x_uart_platform[line].irq);
123 }
124 /***************************************************************************/
125
126 static void __init m532x_fec_init(void)
127 {
128 /* Unmask FEC interrupts at ColdFire interrupt controller */
129 MCF_INTC0_ICR36 = 0x2;
130 MCF_INTC0_ICR40 = 0x2;
131 MCF_INTC0_ICR42 = 0x2;
132
133 MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK36 |
134 MCF_INTC_IMRH_INT_MASK40 | MCF_INTC_IMRH_INT_MASK42);
135
136 /* Set multi-function pins to ethernet mode for fec0 */
137 MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
138 MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
139 MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
140 MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
141 }
142
143 /***************************************************************************/
144
145 void mcf_settimericr(unsigned int timer, unsigned int level)
146 {
147 volatile unsigned char *icrp;
148 unsigned int icr;
149 unsigned char irq;
150
151 if (timer <= 2) {
152 switch (timer) {
153 case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break;
154 default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
155 }
156
157 icrp = (volatile unsigned char *) (icr);
158 *icrp = level;
159 mcf_enable_irq0(irq);
160 }
161 }
162
163 /***************************************************************************/
164
165 static void m532x_cpu_reset(void)
166 {
167 local_irq_disable();
168 __raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
169 }
170
171 /***************************************************************************/
172
173 void __init config_BSP(char *commandp, int size)
174 {
175 mcf_setimr(MCFSIM_IMR_MASKALL);
176
177 #if !defined(CONFIG_BOOTPARAM)
178 /* Copy command line from FLASH to local buffer... */
179 memcpy(commandp, (char *) 0x4000, 4);
180 if(strncmp(commandp, "kcl ", 4) == 0){
181 memcpy(commandp, (char *) 0x4004, size);
182 commandp[size-1] = 0;
183 } else {
184 memset(commandp, 0, size);
185 }
186 #endif
187
188 mcf_timervector = 64+32;
189 mcf_profilevector = 64+33;
190 mach_reset = m532x_cpu_reset;
191
192 #ifdef CONFIG_BDM_DISABLE
193 /*
194 * Disable the BDM clocking. This also turns off most of the rest of
195 * the BDM device. This is good for EMC reasons. This option is not
196 * incompatible with the memory protection option.
197 */
198 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
199 #endif
200 }
201
202 /***************************************************************************/
203
204 static int __init init_BSP(void)
205 {
206 m532x_uarts_init();
207 m532x_fec_init();
208 platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
209 return 0;
210 }
211
212 arch_initcall(init_BSP);
213
214 /***************************************************************************/
215 /* Board initialization */
216 /***************************************************************************/
217 /*
218 * PLL min/max specifications
219 */
220 #define MAX_FVCO 500000 /* KHz */
221 #define MAX_FSYS 80000 /* KHz */
222 #define MIN_FSYS 58333 /* KHz */
223 #define FREF 16000 /* KHz */
224
225
226 #define MAX_MFD 135 /* Multiplier */
227 #define MIN_MFD 88 /* Multiplier */
228 #define BUSDIV 6 /* Divider */
229
230 /*
231 * Low Power Divider specifications
232 */
233 #define MIN_LPD (1 << 0) /* Divider (not encoded) */
234 #define MAX_LPD (1 << 15) /* Divider (not encoded) */
235 #define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
236
237 #define SYS_CLK_KHZ 80000
238 #define SYSTEM_PERIOD 12.5
239 /*
240 * SDRAM Timing Parameters
241 */
242 #define SDRAM_BL 8 /* # of beats in a burst */
243 #define SDRAM_TWR 2 /* in clocks */
244 #define SDRAM_CASL 2.5 /* CASL in clocks */
245 #define SDRAM_TRCD 2 /* in clocks */
246 #define SDRAM_TRP 2 /* in clocks */
247 #define SDRAM_TRFC 7 /* in clocks */
248 #define SDRAM_TREFI 7800 /* in ns */
249
250 #define EXT_SRAM_ADDRESS (0xC0000000)
251 #define FLASH_ADDRESS (0x00000000)
252 #define SDRAM_ADDRESS (0x40000000)
253
254 #define NAND_FLASH_ADDRESS (0xD0000000)
255
256 int sys_clk_khz = 0;
257 int sys_clk_mhz = 0;
258
259 void wtm_init(void);
260 void scm_init(void);
261 void gpio_init(void);
262 void fbcs_init(void);
263 void sdramc_init(void);
264 int clock_pll (int fsys, int flags);
265 int clock_limp (int);
266 int clock_exit_limp (void);
267 int get_sys_clock (void);
268
269 asmlinkage void __init sysinit(void)
270 {
271 sys_clk_khz = clock_pll(0, 0);
272 sys_clk_mhz = sys_clk_khz/1000;
273
274 wtm_init();
275 scm_init();
276 gpio_init();
277 fbcs_init();
278 sdramc_init();
279 }
280
281 void wtm_init(void)
282 {
283 /* Disable watchdog timer */
284 MCF_WTM_WCR = 0;
285 }
286
287 #define MCF_SCM_BCR_GBW (0x00000100)
288 #define MCF_SCM_BCR_GBR (0x00000200)
289
290 void scm_init(void)
291 {
292 /* All masters are trusted */
293 MCF_SCM_MPR = 0x77777777;
294
295 /* Allow supervisor/user, read/write, and trusted/untrusted
296 access to all slaves */
297 MCF_SCM_PACRA = 0;
298 MCF_SCM_PACRB = 0;
299 MCF_SCM_PACRC = 0;
300 MCF_SCM_PACRD = 0;
301 MCF_SCM_PACRE = 0;
302 MCF_SCM_PACRF = 0;
303
304 /* Enable bursts */
305 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
306 }
307
308
309 void fbcs_init(void)
310 {
311 MCF_GPIO_PAR_CS = 0x0000003E;
312
313 /* Latch chip select */
314 MCF_FBCS1_CSAR = 0x10080000;
315
316 MCF_FBCS1_CSCR = 0x002A3780;
317 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
318
319 /* Initialize latch to drive signals to inactive states */
320 *((u16 *)(0x10080000)) = 0xFFFF;
321
322 /* External SRAM */
323 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
324 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
325 | MCF_FBCS_CSCR_AA
326 | MCF_FBCS_CSCR_SBM
327 | MCF_FBCS_CSCR_WS(1));
328 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
329 | MCF_FBCS_CSMR_V);
330
331 /* Boot Flash connected to FBCS0 */
332 MCF_FBCS0_CSAR = FLASH_ADDRESS;
333 MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
334 | MCF_FBCS_CSCR_BEM
335 | MCF_FBCS_CSCR_AA
336 | MCF_FBCS_CSCR_SBM
337 | MCF_FBCS_CSCR_WS(7));
338 MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
339 | MCF_FBCS_CSMR_V);
340 }
341
342 void sdramc_init(void)
343 {
344 /*
345 * Check to see if the SDRAM has already been initialized
346 * by a run control tool
347 */
348 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
349 /* SDRAM chip select initialization */
350
351 /* Initialize SDRAM chip select */
352 MCF_SDRAMC_SDCS0 = (0
353 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
354 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
355
356 /*
357 * Basic configuration and initialization
358 */
359 MCF_SDRAMC_SDCFG1 = (0
360 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
361 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
362 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
363 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
364 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
365 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
366 | MCF_SDRAMC_SDCFG1_WTLAT(3));
367 MCF_SDRAMC_SDCFG2 = (0
368 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
369 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
370 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
371 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
372
373
374 /*
375 * Precharge and enable write to SDMR
376 */
377 MCF_SDRAMC_SDCR = (0
378 | MCF_SDRAMC_SDCR_MODE_EN
379 | MCF_SDRAMC_SDCR_CKE
380 | MCF_SDRAMC_SDCR_DDR
381 | MCF_SDRAMC_SDCR_MUX(1)
382 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
383 | MCF_SDRAMC_SDCR_PS_16
384 | MCF_SDRAMC_SDCR_IPALL);
385
386 /*
387 * Write extended mode register
388 */
389 MCF_SDRAMC_SDMR = (0
390 | MCF_SDRAMC_SDMR_BNKAD_LEMR
391 | MCF_SDRAMC_SDMR_AD(0x0)
392 | MCF_SDRAMC_SDMR_CMD);
393
394 /*
395 * Write mode register and reset DLL
396 */
397 MCF_SDRAMC_SDMR = (0
398 | MCF_SDRAMC_SDMR_BNKAD_LMR
399 | MCF_SDRAMC_SDMR_AD(0x163)
400 | MCF_SDRAMC_SDMR_CMD);
401
402 /*
403 * Execute a PALL command
404 */
405 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
406
407 /*
408 * Perform two REF cycles
409 */
410 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
411 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
412
413 /*
414 * Write mode register and clear reset DLL
415 */
416 MCF_SDRAMC_SDMR = (0
417 | MCF_SDRAMC_SDMR_BNKAD_LMR
418 | MCF_SDRAMC_SDMR_AD(0x063)
419 | MCF_SDRAMC_SDMR_CMD);
420
421 /*
422 * Enable auto refresh and lock SDMR
423 */
424 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
425 MCF_SDRAMC_SDCR |= (0
426 | MCF_SDRAMC_SDCR_REF
427 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
428 }
429 }
430
431 void gpio_init(void)
432 {
433 /* Enable UART0 pins */
434 MCF_GPIO_PAR_UART = ( 0
435 | MCF_GPIO_PAR_UART_PAR_URXD0
436 | MCF_GPIO_PAR_UART_PAR_UTXD0);
437
438 /* Initialize TIN3 as a GPIO output to enable the write
439 half of the latch */
440 MCF_GPIO_PAR_TIMER = 0x00;
441 MCF_GPIO_PDDR_TIMER = 0x08;
442 MCF_GPIO_PCLRR_TIMER = 0x0;
443
444 }
445
446 int clock_pll(int fsys, int flags)
447 {
448 int fref, temp, fout, mfd;
449 u32 i;
450
451 fref = FREF;
452
453 if (fsys == 0) {
454 /* Return current PLL output */
455 mfd = MCF_PLL_PFDR;
456
457 return (fref * mfd / (BUSDIV * 4));
458 }
459
460 /* Check bounds of requested system clock */
461 if (fsys > MAX_FSYS)
462 fsys = MAX_FSYS;
463 if (fsys < MIN_FSYS)
464 fsys = MIN_FSYS;
465
466 /* Multiplying by 100 when calculating the temp value,
467 and then dividing by 100 to calculate the mfd allows
468 for exact values without needing to include floating
469 point libraries. */
470 temp = 100 * fsys / fref;
471 mfd = 4 * BUSDIV * temp / 100;
472
473 /* Determine the output frequency for selected values */
474 fout = (fref * mfd / (BUSDIV * 4));
475
476 /*
477 * Check to see if the SDRAM has already been initialized.
478 * If it has then the SDRAM needs to be put into self refresh
479 * mode before reprogramming the PLL.
480 */
481 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
482 /* Put SDRAM into self refresh mode */
483 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
484
485 /*
486 * Initialize the PLL to generate the new system clock frequency.
487 * The device must be put into LIMP mode to reprogram the PLL.
488 */
489
490 /* Enter LIMP mode */
491 clock_limp(DEFAULT_LPD);
492
493 /* Reprogram PLL for desired fsys */
494 MCF_PLL_PODR = (0
495 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
496 | MCF_PLL_PODR_BUSDIV(BUSDIV));
497
498 MCF_PLL_PFDR = mfd;
499
500 /* Exit LIMP mode */
501 clock_exit_limp();
502
503 /*
504 * Return the SDRAM to normal operation if it is in use.
505 */
506 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
507 /* Exit self refresh mode */
508 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
509
510 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
511 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
512
513 /* wait for DQS logic to relock */
514 for (i = 0; i < 0x200; i++)
515 ;
516
517 return fout;
518 }
519
520 int clock_limp(int div)
521 {
522 u32 temp;
523
524 /* Check bounds of divider */
525 if (div < MIN_LPD)
526 div = MIN_LPD;
527 if (div > MAX_LPD)
528 div = MAX_LPD;
529
530 /* Save of the current value of the SSIDIV so we don't
531 overwrite the value*/
532 temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
533
534 /* Apply the divider to the system clock */
535 MCF_CCM_CDR = ( 0
536 | MCF_CCM_CDR_LPDIV(div)
537 | MCF_CCM_CDR_SSIDIV(temp));
538
539 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
540
541 return (FREF/(3*(1 << div)));
542 }
543
544 int clock_exit_limp(void)
545 {
546 int fout;
547
548 /* Exit LIMP mode */
549 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
550
551 /* Wait for PLL to lock */
552 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
553 ;
554
555 fout = get_sys_clock();
556
557 return fout;
558 }
559
560 int get_sys_clock(void)
561 {
562 int divider;
563
564 /* Test to see if device is in LIMP mode */
565 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
566 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
567 return (FREF/(2 << divider));
568 }
569 else
570 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
571 }
This page took 0.08306 seconds and 5 git commands to generate.