blob: f77328b7b6db0439dcf63d2877bfef40e737ac76 [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 Ungerer3196cf82006-06-26 10:33:10 +100024#include <asm/dma.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>
28#include <asm/mcfdma.h>
29#include <asm/mcfwdebug.h>
30
31/***************************************************************************/
32
Greg Ungerer3196cf82006-06-26 10:33:10 +100033void coldfire_reset(void);
34
35extern unsigned int mcf_timervector;
36extern unsigned int mcf_profilevector;
37extern unsigned int mcf_timerlevel;
38
39/***************************************************************************/
40
41/*
42 * DMA channel base address table.
43 */
44unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { };
45unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
46
47/***************************************************************************/
48
49void mcf_settimericr(unsigned int timer, unsigned int level)
50{
51 volatile unsigned char *icrp;
52 unsigned int icr;
53 unsigned char irq;
54
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;
59 }
60
61 icrp = (volatile unsigned char *) (MCF_MBAR + icr);
62 *icrp = level;
63 mcf_enable_irq0(irq);
64 }
65}
66
67/***************************************************************************/
68
69int mcf_timerirqpending(int timer)
70{
71 unsigned int imr = 0;
72
73 switch (timer) {
74 case 1: imr = 0x1; break;
75 case 2: imr = 0x2; break;
76 default: break;
77 }
78 return (mcf_getiprh() & imr);
79}
80
81/***************************************************************************/
82
83void config_BSP(char *commandp, int size)
84{
85 mcf_setimr(MCFSIM_IMR_MASKALL);
86
Greg Ungererbc724502007-07-25 22:07:20 +100087#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +100088 /* 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);
95 }
96#endif
97
98 mcf_timervector = 64+32;
99 mcf_profilevector = 64+33;
Greg Ungerer3196cf82006-06-26 10:33:10 +1000100 mach_reset = coldfire_reset;
101
102#ifdef MCF_BDM_DISABLE
103 /*
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.
107 */
108 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
109#endif
110}
111
112/***************************************************************************/
113/* Board initialization */
114
115/********************************************************************/
116/*
117 * PLL min/max specifications
118 */
119#define MAX_FVCO 500000 /* KHz */
120#define MAX_FSYS 80000 /* KHz */
121#define MIN_FSYS 58333 /* KHz */
122#define FREF 16000 /* KHz */
123
124
125#define MAX_MFD 135 /* Multiplier */
126#define MIN_MFD 88 /* Multiplier */
127#define BUSDIV 6 /* Divider */
128
129/*
130 * Low Power Divider specifications
131 */
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) */
135
136#define SYS_CLK_KHZ 80000
137#define SYSTEM_PERIOD 12.5
138/*
139 * SDRAM Timing Parameters
140 */
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 */
148
149#define EXT_SRAM_ADDRESS (0xC0000000)
150#define FLASH_ADDRESS (0x00000000)
151#define SDRAM_ADDRESS (0x40000000)
152
153#define NAND_FLASH_ADDRESS (0xD0000000)
154
155int sys_clk_khz = 0;
156int sys_clk_mhz = 0;
157
158void wtm_init(void);
159void scm_init(void);
160void gpio_init(void);
161void fbcs_init(void);
162void sdramc_init(void);
163int clock_pll (int fsys, int flags);
164int clock_limp (int);
165int clock_exit_limp (void);
166int get_sys_clock (void);
167
168asmlinkage void __init sysinit(void)
169{
170 sys_clk_khz = clock_pll(0, 0);
171 sys_clk_mhz = sys_clk_khz/1000;
172
173 wtm_init();
174 scm_init();
175 gpio_init();
176 fbcs_init();
177 sdramc_init();
178}
179
180void wtm_init(void)
181{
182 /* Disable watchdog timer */
183 MCF_WTM_WCR = 0;
184}
185
186#define MCF_SCM_BCR_GBW (0x00000100)
187#define MCF_SCM_BCR_GBR (0x00000200)
188
189void scm_init(void)
190{
191 /* All masters are trusted */
192 MCF_SCM_MPR = 0x77777777;
193
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;
202
203 /* Enable bursts */
204 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
205}
206
207
208void fbcs_init(void)
209{
210 MCF_GPIO_PAR_CS = 0x0000003E;
211
212 /* Latch chip select */
213 MCF_FBCS1_CSAR = 0x10080000;
214
215 MCF_FBCS1_CSCR = 0x002A3780;
216 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
217
218 /* Initialize latch to drive signals to inactive states */
219 *((u16 *)(0x10080000)) = 0xFFFF;
220
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);
229
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);
239}
240
241void sdramc_init(void)
242{
243 /*
244 * Check to see if the SDRAM has already been initialized
245 * by a run control tool
246 */
247 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
248 /* SDRAM chip select initialization */
249
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));
254
255 /*
256 * Basic configuration and initialization
257 */
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));
271
272
273 /*
274 * Precharge and enable write to SDMR
275 */
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);
284
285 /*
286 * Write extended mode register
287 */
288 MCF_SDRAMC_SDMR = (0
289 | MCF_SDRAMC_SDMR_BNKAD_LEMR
290 | MCF_SDRAMC_SDMR_AD(0x0)
291 | MCF_SDRAMC_SDMR_CMD);
292
293 /*
294 * Write mode register and reset DLL
295 */
296 MCF_SDRAMC_SDMR = (0
297 | MCF_SDRAMC_SDMR_BNKAD_LMR
298 | MCF_SDRAMC_SDMR_AD(0x163)
299 | MCF_SDRAMC_SDMR_CMD);
300
301 /*
302 * Execute a PALL command
303 */
304 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
305
306 /*
307 * Perform two REF cycles
308 */
309 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
310 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
311
312 /*
313 * Write mode register and clear reset DLL
314 */
315 MCF_SDRAMC_SDMR = (0
316 | MCF_SDRAMC_SDMR_BNKAD_LMR
317 | MCF_SDRAMC_SDMR_AD(0x063)
318 | MCF_SDRAMC_SDMR_CMD);
319
320 /*
321 * Enable auto refresh and lock SDMR
322 */
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));
327 }
328}
329
330void gpio_init(void)
331{
332 /* Enable UART0 pins */
333 MCF_GPIO_PAR_UART = ( 0
334 | MCF_GPIO_PAR_UART_PAR_URXD0
335 | MCF_GPIO_PAR_UART_PAR_UTXD0);
336
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;
342
343}
344
345int clock_pll(int fsys, int flags)
346{
347 int fref, temp, fout, mfd;
348 u32 i;
349
350 fref = FREF;
351
352 if (fsys == 0) {
353 /* Return current PLL output */
354 mfd = MCF_PLL_PFDR;
355
356 return (fref * mfd / (BUSDIV * 4));
357 }
358
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;
364
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;
371
372 /* Determine the output frequency for selected values */
373 fout = (fref * mfd / (BUSDIV * 4));
374
375 /*
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.
379 */
380 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
381 /* Put SDRAM into self refresh mode */
382 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
383
384 /*
385 * Initialize the PLL to generate the new system clock frequency.
386 * The device must be put into LIMP mode to reprogram the PLL.
387 */
388
389 /* Enter LIMP mode */
390 clock_limp(DEFAULT_LPD);
391
392 /* Reprogram PLL for desired fsys */
393 MCF_PLL_PODR = (0
394 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
395 | MCF_PLL_PODR_BUSDIV(BUSDIV));
396
397 MCF_PLL_PFDR = mfd;
398
399 /* Exit LIMP mode */
400 clock_exit_limp();
401
402 /*
403 * Return the SDRAM to normal operation if it is in use.
404 */
405 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
406 /* Exit self refresh mode */
407 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
408
409 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
410 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
411
412 /* wait for DQS logic to relock */
413 for (i = 0; i < 0x200; i++)
414 ;
415
416 return fout;
417}
418
419int clock_limp(int div)
420{
421 u32 temp;
422
423 /* Check bounds of divider */
424 if (div < MIN_LPD)
425 div = MIN_LPD;
426 if (div > MAX_LPD)
427 div = MAX_LPD;
428
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));
432
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));
437
438 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
439
440 return (FREF/(3*(1 << div)));
441}
442
443int clock_exit_limp(void)
444{
445 int fout;
446
447 /* Exit LIMP mode */
448 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
449
450 /* Wait for PLL to lock */
451 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
452 ;
453
454 fout = get_sys_clock();
455
456 return fout;
457}
458
459int get_sys_clock(void)
460{
461 int divider;
462
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));
467 }
468 else
469 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
470}