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