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