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