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