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