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