blob: ceef9bc181eabf791a727cbd6d6409ecd07109e7 [file] [log] [blame]
Greg Ungerer3196cf82006-06-26 10:33:10 +10001/***************************************************************************/
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
38void coldfire_tick(void);
39void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
40unsigned long coldfire_timer_offset(void);
41void coldfire_trap_init(void);
42void coldfire_reset(void);
43
44extern unsigned int mcf_timervector;
45extern unsigned int mcf_profilevector;
46extern unsigned int mcf_timerlevel;
47
48/***************************************************************************/
49
50/*
51 * DMA channel base address table.
52 */
53unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { };
54unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
55
56/***************************************************************************/
57
58void 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
78int 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
92void 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
171int sys_clk_khz = 0;
172int sys_clk_mhz = 0;
173
174void wtm_init(void);
175void scm_init(void);
176void gpio_init(void);
177void fbcs_init(void);
178void sdramc_init(void);
179int clock_pll (int fsys, int flags);
180int clock_limp (int);
181int clock_exit_limp (void);
182int get_sys_clock (void);
183
184asmlinkage 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
196void 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
205void 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
224void 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
257void 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
346void 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
361int 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
435int 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
459int 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
475int 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}