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