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