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