blob: dc39c466e33f69c7309048a53e78e94f502a4730 [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
Greg Ungerer3196cf82006-06-26 10:33:10 +100020#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
37void coldfire_tick(void);
Greg Ungerereaefd5f2007-02-07 12:03:19 +100038void coldfire_timer_init(irq_handler_t handler);
Greg Ungerer3196cf82006-06-26 10:33:10 +100039unsigned long coldfire_timer_offset(void);
40void coldfire_trap_init(void);
41void coldfire_reset(void);
42
43extern unsigned int mcf_timervector;
44extern unsigned int mcf_profilevector;
45extern unsigned int mcf_timerlevel;
46
47/***************************************************************************/
48
49/*
50 * DMA channel base address table.
51 */
52unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { };
53unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
54
55/***************************************************************************/
56
57void 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
77int 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
91void config_BSP(char *commandp, int size)
92{
93 mcf_setimr(MCFSIM_IMR_MASKALL);
94
Greg Ungererbc724502007-07-25 22:07:20 +100095#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +100096 /* 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
167int sys_clk_khz = 0;
168int sys_clk_mhz = 0;
169
170void wtm_init(void);
171void scm_init(void);
172void gpio_init(void);
173void fbcs_init(void);
174void sdramc_init(void);
175int clock_pll (int fsys, int flags);
176int clock_limp (int);
177int clock_exit_limp (void);
178int get_sys_clock (void);
179
180asmlinkage 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
192void 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
201void 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
220void 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
253void 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
342void 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
357int 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
431int 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
455int 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
471int 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}