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