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