m68knommu: cleanup m68knommu timer code
[linux-2.6/openmoko-kernel/knife-kernel.git] / arch / m68knommu / platform / 532x / config.c
blobf77328b7b6db0439dcf63d2877bfef40e737ac76
1 /***************************************************************************/
3 /*
4 * linux/arch/m68knommu/platform/532x/config.c
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>
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.
18 /***************************************************************************/
20 #include <linux/kernel.h>
21 #include <linux/param.h>
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <asm/dma.h>
25 #include <asm/machdep.h>
26 #include <asm/coldfire.h>
27 #include <asm/mcfsim.h>
28 #include <asm/mcfdma.h>
29 #include <asm/mcfwdebug.h>
31 /***************************************************************************/
33 void coldfire_reset(void);
35 extern unsigned int mcf_timervector;
36 extern unsigned int mcf_profilevector;
37 extern unsigned int mcf_timerlevel;
39 /***************************************************************************/
42 * DMA channel base address table.
44 unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { };
45 unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
47 /***************************************************************************/
49 void mcf_settimericr(unsigned int timer, unsigned int level)
51 volatile unsigned char *icrp;
52 unsigned int icr;
53 unsigned char irq;
55 if (timer <= 2) {
56 switch (timer) {
57 case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break;
58 default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
61 icrp = (volatile unsigned char *) (MCF_MBAR + icr);
62 *icrp = level;
63 mcf_enable_irq0(irq);
67 /***************************************************************************/
69 int mcf_timerirqpending(int timer)
71 unsigned int imr = 0;
73 switch (timer) {
74 case 1: imr = 0x1; break;
75 case 2: imr = 0x2; break;
76 default: break;
78 return (mcf_getiprh() & imr);
81 /***************************************************************************/
83 void config_BSP(char *commandp, int size)
85 mcf_setimr(MCFSIM_IMR_MASKALL);
87 #if !defined(CONFIG_BOOTPARAM)
88 /* Copy command line from FLASH to local buffer... */
89 memcpy(commandp, (char *) 0x4000, 4);
90 if(strncmp(commandp, "kcl ", 4) == 0){
91 memcpy(commandp, (char *) 0x4004, size);
92 commandp[size-1] = 0;
93 } else {
94 memset(commandp, 0, size);
96 #endif
98 mcf_timervector = 64+32;
99 mcf_profilevector = 64+33;
100 mach_reset = coldfire_reset;
102 #ifdef MCF_BDM_DISABLE
104 * Disable the BDM clocking. This also turns off most of the rest of
105 * the BDM device. This is good for EMC reasons. This option is not
106 * incompatible with the memory protection option.
108 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
109 #endif
112 /***************************************************************************/
113 /* Board initialization */
115 /********************************************************************/
117 * PLL min/max specifications
119 #define MAX_FVCO 500000 /* KHz */
120 #define MAX_FSYS 80000 /* KHz */
121 #define MIN_FSYS 58333 /* KHz */
122 #define FREF 16000 /* KHz */
125 #define MAX_MFD 135 /* Multiplier */
126 #define MIN_MFD 88 /* Multiplier */
127 #define BUSDIV 6 /* Divider */
130 * Low Power Divider specifications
132 #define MIN_LPD (1 << 0) /* Divider (not encoded) */
133 #define MAX_LPD (1 << 15) /* Divider (not encoded) */
134 #define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
136 #define SYS_CLK_KHZ 80000
137 #define SYSTEM_PERIOD 12.5
139 * SDRAM Timing Parameters
141 #define SDRAM_BL 8 /* # of beats in a burst */
142 #define SDRAM_TWR 2 /* in clocks */
143 #define SDRAM_CASL 2.5 /* CASL in clocks */
144 #define SDRAM_TRCD 2 /* in clocks */
145 #define SDRAM_TRP 2 /* in clocks */
146 #define SDRAM_TRFC 7 /* in clocks */
147 #define SDRAM_TREFI 7800 /* in ns */
149 #define EXT_SRAM_ADDRESS (0xC0000000)
150 #define FLASH_ADDRESS (0x00000000)
151 #define SDRAM_ADDRESS (0x40000000)
153 #define NAND_FLASH_ADDRESS (0xD0000000)
155 int sys_clk_khz = 0;
156 int sys_clk_mhz = 0;
158 void wtm_init(void);
159 void scm_init(void);
160 void gpio_init(void);
161 void fbcs_init(void);
162 void sdramc_init(void);
163 int clock_pll (int fsys, int flags);
164 int clock_limp (int);
165 int clock_exit_limp (void);
166 int get_sys_clock (void);
168 asmlinkage void __init sysinit(void)
170 sys_clk_khz = clock_pll(0, 0);
171 sys_clk_mhz = sys_clk_khz/1000;
173 wtm_init();
174 scm_init();
175 gpio_init();
176 fbcs_init();
177 sdramc_init();
180 void wtm_init(void)
182 /* Disable watchdog timer */
183 MCF_WTM_WCR = 0;
186 #define MCF_SCM_BCR_GBW (0x00000100)
187 #define MCF_SCM_BCR_GBR (0x00000200)
189 void scm_init(void)
191 /* All masters are trusted */
192 MCF_SCM_MPR = 0x77777777;
194 /* Allow supervisor/user, read/write, and trusted/untrusted
195 access to all slaves */
196 MCF_SCM_PACRA = 0;
197 MCF_SCM_PACRB = 0;
198 MCF_SCM_PACRC = 0;
199 MCF_SCM_PACRD = 0;
200 MCF_SCM_PACRE = 0;
201 MCF_SCM_PACRF = 0;
203 /* Enable bursts */
204 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
208 void fbcs_init(void)
210 MCF_GPIO_PAR_CS = 0x0000003E;
212 /* Latch chip select */
213 MCF_FBCS1_CSAR = 0x10080000;
215 MCF_FBCS1_CSCR = 0x002A3780;
216 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
218 /* Initialize latch to drive signals to inactive states */
219 *((u16 *)(0x10080000)) = 0xFFFF;
221 /* External SRAM */
222 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
223 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
224 | MCF_FBCS_CSCR_AA
225 | MCF_FBCS_CSCR_SBM
226 | MCF_FBCS_CSCR_WS(1));
227 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
228 | MCF_FBCS_CSMR_V);
230 /* Boot Flash connected to FBCS0 */
231 MCF_FBCS0_CSAR = FLASH_ADDRESS;
232 MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
233 | MCF_FBCS_CSCR_BEM
234 | MCF_FBCS_CSCR_AA
235 | MCF_FBCS_CSCR_SBM
236 | MCF_FBCS_CSCR_WS(7));
237 MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
238 | MCF_FBCS_CSMR_V);
241 void sdramc_init(void)
244 * Check to see if the SDRAM has already been initialized
245 * by a run control tool
247 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
248 /* SDRAM chip select initialization */
250 /* Initialize SDRAM chip select */
251 MCF_SDRAMC_SDCS0 = (0
252 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
253 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
256 * Basic configuration and initialization
258 MCF_SDRAMC_SDCFG1 = (0
259 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
260 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
261 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
262 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
263 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
264 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
265 | MCF_SDRAMC_SDCFG1_WTLAT(3));
266 MCF_SDRAMC_SDCFG2 = (0
267 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
268 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
269 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
270 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
274 * Precharge and enable write to SDMR
276 MCF_SDRAMC_SDCR = (0
277 | MCF_SDRAMC_SDCR_MODE_EN
278 | MCF_SDRAMC_SDCR_CKE
279 | MCF_SDRAMC_SDCR_DDR
280 | MCF_SDRAMC_SDCR_MUX(1)
281 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
282 | MCF_SDRAMC_SDCR_PS_16
283 | MCF_SDRAMC_SDCR_IPALL);
286 * Write extended mode register
288 MCF_SDRAMC_SDMR = (0
289 | MCF_SDRAMC_SDMR_BNKAD_LEMR
290 | MCF_SDRAMC_SDMR_AD(0x0)
291 | MCF_SDRAMC_SDMR_CMD);
294 * Write mode register and reset DLL
296 MCF_SDRAMC_SDMR = (0
297 | MCF_SDRAMC_SDMR_BNKAD_LMR
298 | MCF_SDRAMC_SDMR_AD(0x163)
299 | MCF_SDRAMC_SDMR_CMD);
302 * Execute a PALL command
304 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
307 * Perform two REF cycles
309 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
310 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
313 * Write mode register and clear reset DLL
315 MCF_SDRAMC_SDMR = (0
316 | MCF_SDRAMC_SDMR_BNKAD_LMR
317 | MCF_SDRAMC_SDMR_AD(0x063)
318 | MCF_SDRAMC_SDMR_CMD);
321 * Enable auto refresh and lock SDMR
323 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
324 MCF_SDRAMC_SDCR |= (0
325 | MCF_SDRAMC_SDCR_REF
326 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
330 void gpio_init(void)
332 /* Enable UART0 pins */
333 MCF_GPIO_PAR_UART = ( 0
334 | MCF_GPIO_PAR_UART_PAR_URXD0
335 | MCF_GPIO_PAR_UART_PAR_UTXD0);
337 /* Initialize TIN3 as a GPIO output to enable the write
338 half of the latch */
339 MCF_GPIO_PAR_TIMER = 0x00;
340 MCF_GPIO_PDDR_TIMER = 0x08;
341 MCF_GPIO_PCLRR_TIMER = 0x0;
345 int clock_pll(int fsys, int flags)
347 int fref, temp, fout, mfd;
348 u32 i;
350 fref = FREF;
352 if (fsys == 0) {
353 /* Return current PLL output */
354 mfd = MCF_PLL_PFDR;
356 return (fref * mfd / (BUSDIV * 4));
359 /* Check bounds of requested system clock */
360 if (fsys > MAX_FSYS)
361 fsys = MAX_FSYS;
362 if (fsys < MIN_FSYS)
363 fsys = MIN_FSYS;
365 /* Multiplying by 100 when calculating the temp value,
366 and then dividing by 100 to calculate the mfd allows
367 for exact values without needing to include floating
368 point libraries. */
369 temp = 100 * fsys / fref;
370 mfd = 4 * BUSDIV * temp / 100;
372 /* Determine the output frequency for selected values */
373 fout = (fref * mfd / (BUSDIV * 4));
376 * Check to see if the SDRAM has already been initialized.
377 * If it has then the SDRAM needs to be put into self refresh
378 * mode before reprogramming the PLL.
380 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
381 /* Put SDRAM into self refresh mode */
382 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
385 * Initialize the PLL to generate the new system clock frequency.
386 * The device must be put into LIMP mode to reprogram the PLL.
389 /* Enter LIMP mode */
390 clock_limp(DEFAULT_LPD);
392 /* Reprogram PLL for desired fsys */
393 MCF_PLL_PODR = (0
394 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
395 | MCF_PLL_PODR_BUSDIV(BUSDIV));
397 MCF_PLL_PFDR = mfd;
399 /* Exit LIMP mode */
400 clock_exit_limp();
403 * Return the SDRAM to normal operation if it is in use.
405 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
406 /* Exit self refresh mode */
407 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
409 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
410 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
412 /* wait for DQS logic to relock */
413 for (i = 0; i < 0x200; i++)
416 return fout;
419 int clock_limp(int div)
421 u32 temp;
423 /* Check bounds of divider */
424 if (div < MIN_LPD)
425 div = MIN_LPD;
426 if (div > MAX_LPD)
427 div = MAX_LPD;
429 /* Save of the current value of the SSIDIV so we don't
430 overwrite the value*/
431 temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
433 /* Apply the divider to the system clock */
434 MCF_CCM_CDR = ( 0
435 | MCF_CCM_CDR_LPDIV(div)
436 | MCF_CCM_CDR_SSIDIV(temp));
438 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
440 return (FREF/(3*(1 << div)));
443 int clock_exit_limp(void)
445 int fout;
447 /* Exit LIMP mode */
448 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
450 /* Wait for PLL to lock */
451 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
454 fout = get_sys_clock();
456 return fout;
459 int get_sys_clock(void)
461 int divider;
463 /* Test to see if device is in LIMP mode */
464 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
465 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
466 return (FREF/(2 << divider));
468 else
469 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));