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