blob: 5394223639f8f5d5bc4c508895562d9075394d20 [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
Linus Torvaldse8650a02012-05-22 19:22:50 -070010 * Copyright (c) 2006, emlix, Sebastian Hess <shess@hessware.de>
Greg Ungerer3196cf82006-06-26 10:33:10 +100011 *
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>
Greg Ungererb2e18102008-02-01 17:34:58 +100023#include <linux/io.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100024#include <asm/machdep.h>
25#include <asm/coldfire.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100026#include <asm/mcfsim.h>
Greg Ungererb2e18102008-02-01 17:34:58 +100027#include <asm/mcfuart.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100028#include <asm/mcfdma.h>
Greg Ungererbb70e212012-04-17 14:25:20 +100029#include <asm/mcfgpio.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100030#include <asm/mcfwdebug.h>
31
32/***************************************************************************/
33
Greg Ungererbb70e212012-04-17 14:25:20 +100034struct mcf_gpio_chip mcf_gpio_chips[] = {
35 MCFGPS(PIRQ, 0, 8, MCFEPORT_EPDDR, MCFEPORT_EPDR, MCFEPORT_EPPDR),
36 MCFGPF(FECH, 8, 8),
37 MCFGPF(FECL, 16, 8),
38 MCFGPF(SSI, 24, 5),
39 MCFGPF(BUSCTL, 32, 4),
40 MCFGPF(BE, 40, 4),
41 MCFGPF(CS, 49, 5),
42 MCFGPF(PWM, 58, 4),
43 MCFGPF(FECI2C, 64, 4),
44 MCFGPF(UART, 72, 8),
45 MCFGPF(QSPI, 80, 6),
46 MCFGPF(TIMER, 88, 4),
47 MCFGPF(LCDDATAH, 96, 2),
48 MCFGPF(LCDDATAM, 104, 8),
49 MCFGPF(LCDDATAL, 112, 8),
50 MCFGPF(LCDCTLH, 120, 1),
51 MCFGPF(LCDCTLL, 128, 8),
52};
53
54unsigned int mcf_gpio_chips_size = ARRAY_SIZE(mcf_gpio_chips);
55
56/***************************************************************************/
57
Steven King83ca6002012-05-06 12:22:53 -070058#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
Steven King91d60412010-01-22 12:43:03 -080059
60static void __init m532x_qspi_init(void)
61{
62 /* setup QSPS pins for QSPI with gpio CS control */
63 writew(0x01f0, MCF_GPIO_PAR_QSPI);
64}
Steven King91d60412010-01-22 12:43:03 -080065
Steven King83ca6002012-05-06 12:22:53 -070066#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
Greg Ungererb2e18102008-02-01 17:34:58 +100067
68/***************************************************************************/
69
Greg Ungererb2e18102008-02-01 17:34:58 +100070static void __init m532x_uarts_init(void)
71{
Greg Ungerera75bc612011-12-24 01:04:22 +100072 /* UART GPIO initialization */
73 MCF_GPIO_PAR_UART |= 0x0FFF;
Greg Ungererb2e18102008-02-01 17:34:58 +100074}
Greg Ungerera75bc612011-12-24 01:04:22 +100075
Greg Ungererffba3f42009-02-26 22:40:38 -080076/***************************************************************************/
77
78static void __init m532x_fec_init(void)
79{
Greg Ungererffba3f42009-02-26 22:40:38 -080080 /* Set multi-function pins to ethernet mode for fec0 */
81 MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
82 MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
83 MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
84 MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
85}
Greg Ungerer3196cf82006-06-26 10:33:10 +100086
87/***************************************************************************/
88
Greg Ungererb2e18102008-02-01 17:34:58 +100089void __init config_BSP(char *commandp, int size)
Greg Ungerer3196cf82006-06-26 10:33:10 +100090{
Greg Ungererbc724502007-07-25 22:07:20 +100091#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +100092 /* Copy command line from FLASH to local buffer... */
93 memcpy(commandp, (char *) 0x4000, 4);
94 if(strncmp(commandp, "kcl ", 4) == 0){
95 memcpy(commandp, (char *) 0x4004, size);
96 commandp[size-1] = 0;
97 } else {
98 memset(commandp, 0, size);
99 }
100#endif
101
Greg Ungerer35aefb22012-01-23 15:34:58 +1000102 mach_sched_init = hw_timer_init;
Greg Ungererc05793c2011-12-24 13:06:33 +1000103 m532x_uarts_init();
104 m532x_fec_init();
Steven King83ca6002012-05-06 12:22:53 -0700105#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
Greg Ungererc05793c2011-12-24 13:06:33 +1000106 m532x_qspi_init();
107#endif
Greg Ungerer35aefb22012-01-23 15:34:58 +1000108
Greg Ungererb2e18102008-02-01 17:34:58 +1000109#ifdef CONFIG_BDM_DISABLE
Greg Ungerer3196cf82006-06-26 10:33:10 +1000110 /*
111 * Disable the BDM clocking. This also turns off most of the rest of
112 * the BDM device. This is good for EMC reasons. This option is not
113 * incompatible with the memory protection option.
114 */
115 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
116#endif
117}
118
119/***************************************************************************/
Greg Ungererb2e18102008-02-01 17:34:58 +1000120/* Board initialization */
121/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000122/*
123 * PLL min/max specifications
124 */
125#define MAX_FVCO 500000 /* KHz */
126#define MAX_FSYS 80000 /* KHz */
127#define MIN_FSYS 58333 /* KHz */
128#define FREF 16000 /* KHz */
129
130
131#define MAX_MFD 135 /* Multiplier */
132#define MIN_MFD 88 /* Multiplier */
133#define BUSDIV 6 /* Divider */
134
135/*
136 * Low Power Divider specifications
137 */
138#define MIN_LPD (1 << 0) /* Divider (not encoded) */
139#define MAX_LPD (1 << 15) /* Divider (not encoded) */
140#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
141
142#define SYS_CLK_KHZ 80000
143#define SYSTEM_PERIOD 12.5
144/*
145 * SDRAM Timing Parameters
146 */
147#define SDRAM_BL 8 /* # of beats in a burst */
148#define SDRAM_TWR 2 /* in clocks */
149#define SDRAM_CASL 2.5 /* CASL in clocks */
150#define SDRAM_TRCD 2 /* in clocks */
151#define SDRAM_TRP 2 /* in clocks */
152#define SDRAM_TRFC 7 /* in clocks */
153#define SDRAM_TREFI 7800 /* in ns */
154
155#define EXT_SRAM_ADDRESS (0xC0000000)
156#define FLASH_ADDRESS (0x00000000)
157#define SDRAM_ADDRESS (0x40000000)
158
159#define NAND_FLASH_ADDRESS (0xD0000000)
160
161int sys_clk_khz = 0;
162int sys_clk_mhz = 0;
163
164void wtm_init(void);
165void scm_init(void);
166void gpio_init(void);
167void fbcs_init(void);
168void sdramc_init(void);
169int clock_pll (int fsys, int flags);
170int clock_limp (int);
171int clock_exit_limp (void);
172int get_sys_clock (void);
173
174asmlinkage void __init sysinit(void)
175{
176 sys_clk_khz = clock_pll(0, 0);
177 sys_clk_mhz = sys_clk_khz/1000;
178
179 wtm_init();
180 scm_init();
181 gpio_init();
182 fbcs_init();
183 sdramc_init();
184}
185
186void wtm_init(void)
187{
188 /* Disable watchdog timer */
189 MCF_WTM_WCR = 0;
190}
191
192#define MCF_SCM_BCR_GBW (0x00000100)
193#define MCF_SCM_BCR_GBR (0x00000200)
194
195void scm_init(void)
196{
197 /* All masters are trusted */
198 MCF_SCM_MPR = 0x77777777;
199
200 /* Allow supervisor/user, read/write, and trusted/untrusted
201 access to all slaves */
202 MCF_SCM_PACRA = 0;
203 MCF_SCM_PACRB = 0;
204 MCF_SCM_PACRC = 0;
205 MCF_SCM_PACRD = 0;
206 MCF_SCM_PACRE = 0;
207 MCF_SCM_PACRF = 0;
208
209 /* Enable bursts */
210 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
211}
212
213
214void fbcs_init(void)
215{
216 MCF_GPIO_PAR_CS = 0x0000003E;
217
218 /* Latch chip select */
219 MCF_FBCS1_CSAR = 0x10080000;
220
221 MCF_FBCS1_CSCR = 0x002A3780;
222 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
223
224 /* Initialize latch to drive signals to inactive states */
225 *((u16 *)(0x10080000)) = 0xFFFF;
226
227 /* External SRAM */
228 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
229 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
230 | MCF_FBCS_CSCR_AA
231 | MCF_FBCS_CSCR_SBM
232 | MCF_FBCS_CSCR_WS(1));
233 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
234 | MCF_FBCS_CSMR_V);
235
236 /* Boot Flash connected to FBCS0 */
237 MCF_FBCS0_CSAR = FLASH_ADDRESS;
238 MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
239 | MCF_FBCS_CSCR_BEM
240 | MCF_FBCS_CSCR_AA
241 | MCF_FBCS_CSCR_SBM
242 | MCF_FBCS_CSCR_WS(7));
243 MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
244 | MCF_FBCS_CSMR_V);
245}
246
247void sdramc_init(void)
248{
249 /*
250 * Check to see if the SDRAM has already been initialized
251 * by a run control tool
252 */
253 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
254 /* SDRAM chip select initialization */
255
256 /* Initialize SDRAM chip select */
257 MCF_SDRAMC_SDCS0 = (0
258 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
259 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
260
261 /*
262 * Basic configuration and initialization
263 */
264 MCF_SDRAMC_SDCFG1 = (0
265 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
266 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
267 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
268 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
269 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
270 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
271 | MCF_SDRAMC_SDCFG1_WTLAT(3));
272 MCF_SDRAMC_SDCFG2 = (0
273 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
274 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
275 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
276 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
277
278
279 /*
280 * Precharge and enable write to SDMR
281 */
282 MCF_SDRAMC_SDCR = (0
283 | MCF_SDRAMC_SDCR_MODE_EN
284 | MCF_SDRAMC_SDCR_CKE
285 | MCF_SDRAMC_SDCR_DDR
286 | MCF_SDRAMC_SDCR_MUX(1)
287 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
288 | MCF_SDRAMC_SDCR_PS_16
289 | MCF_SDRAMC_SDCR_IPALL);
290
291 /*
292 * Write extended mode register
293 */
294 MCF_SDRAMC_SDMR = (0
295 | MCF_SDRAMC_SDMR_BNKAD_LEMR
296 | MCF_SDRAMC_SDMR_AD(0x0)
297 | MCF_SDRAMC_SDMR_CMD);
298
299 /*
300 * Write mode register and reset DLL
301 */
302 MCF_SDRAMC_SDMR = (0
303 | MCF_SDRAMC_SDMR_BNKAD_LMR
304 | MCF_SDRAMC_SDMR_AD(0x163)
305 | MCF_SDRAMC_SDMR_CMD);
306
307 /*
308 * Execute a PALL command
309 */
310 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
311
312 /*
313 * Perform two REF cycles
314 */
315 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
316 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
317
318 /*
319 * Write mode register and clear reset DLL
320 */
321 MCF_SDRAMC_SDMR = (0
322 | MCF_SDRAMC_SDMR_BNKAD_LMR
323 | MCF_SDRAMC_SDMR_AD(0x063)
324 | MCF_SDRAMC_SDMR_CMD);
325
326 /*
327 * Enable auto refresh and lock SDMR
328 */
329 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
330 MCF_SDRAMC_SDCR |= (0
331 | MCF_SDRAMC_SDCR_REF
332 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
333 }
334}
335
336void gpio_init(void)
337{
338 /* Enable UART0 pins */
339 MCF_GPIO_PAR_UART = ( 0
340 | MCF_GPIO_PAR_UART_PAR_URXD0
341 | MCF_GPIO_PAR_UART_PAR_UTXD0);
342
343 /* Initialize TIN3 as a GPIO output to enable the write
344 half of the latch */
345 MCF_GPIO_PAR_TIMER = 0x00;
sfking@fdwdc.com7846fe82009-06-19 18:11:10 -0700346 __raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
347 __raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000348
349}
350
351int clock_pll(int fsys, int flags)
352{
353 int fref, temp, fout, mfd;
354 u32 i;
355
356 fref = FREF;
357
358 if (fsys == 0) {
359 /* Return current PLL output */
360 mfd = MCF_PLL_PFDR;
361
362 return (fref * mfd / (BUSDIV * 4));
363 }
364
365 /* Check bounds of requested system clock */
366 if (fsys > MAX_FSYS)
367 fsys = MAX_FSYS;
368 if (fsys < MIN_FSYS)
369 fsys = MIN_FSYS;
370
371 /* Multiplying by 100 when calculating the temp value,
372 and then dividing by 100 to calculate the mfd allows
373 for exact values without needing to include floating
374 point libraries. */
375 temp = 100 * fsys / fref;
376 mfd = 4 * BUSDIV * temp / 100;
377
378 /* Determine the output frequency for selected values */
379 fout = (fref * mfd / (BUSDIV * 4));
380
381 /*
382 * Check to see if the SDRAM has already been initialized.
383 * If it has then the SDRAM needs to be put into self refresh
384 * mode before reprogramming the PLL.
385 */
386 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
387 /* Put SDRAM into self refresh mode */
388 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
389
390 /*
391 * Initialize the PLL to generate the new system clock frequency.
392 * The device must be put into LIMP mode to reprogram the PLL.
393 */
394
395 /* Enter LIMP mode */
396 clock_limp(DEFAULT_LPD);
397
398 /* Reprogram PLL for desired fsys */
399 MCF_PLL_PODR = (0
400 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
401 | MCF_PLL_PODR_BUSDIV(BUSDIV));
402
403 MCF_PLL_PFDR = mfd;
404
405 /* Exit LIMP mode */
406 clock_exit_limp();
407
408 /*
409 * Return the SDRAM to normal operation if it is in use.
410 */
411 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
412 /* Exit self refresh mode */
413 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
414
415 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
416 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
417
418 /* wait for DQS logic to relock */
419 for (i = 0; i < 0x200; i++)
420 ;
421
422 return fout;
423}
424
425int clock_limp(int div)
426{
427 u32 temp;
428
429 /* Check bounds of divider */
430 if (div < MIN_LPD)
431 div = MIN_LPD;
432 if (div > MAX_LPD)
433 div = MAX_LPD;
434
435 /* Save of the current value of the SSIDIV so we don't
436 overwrite the value*/
437 temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
438
439 /* Apply the divider to the system clock */
440 MCF_CCM_CDR = ( 0
441 | MCF_CCM_CDR_LPDIV(div)
442 | MCF_CCM_CDR_SSIDIV(temp));
443
444 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
445
446 return (FREF/(3*(1 << div)));
447}
448
449int clock_exit_limp(void)
450{
451 int fout;
452
453 /* Exit LIMP mode */
454 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
455
456 /* Wait for PLL to lock */
457 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
458 ;
459
460 fout = get_sys_clock();
461
462 return fout;
463}
464
465int get_sys_clock(void)
466{
467 int divider;
468
469 /* Test to see if device is in LIMP mode */
470 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
471 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
472 return (FREF/(2 << divider));
473 }
474 else
475 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
476}