blob: 13157ae3190551082f51ab39e80b2f8c9679c5df [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>
Greg Ungererb2e18102008-02-01 17:34:58 +100023#include <linux/io.h>
Steven King91d60412010-01-22 12:43:03 -080024#include <linux/spi/spi.h>
25#include <linux/gpio.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100026#include <asm/machdep.h>
27#include <asm/coldfire.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100028#include <asm/mcfsim.h>
Greg Ungererb2e18102008-02-01 17:34:58 +100029#include <asm/mcfuart.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100030#include <asm/mcfdma.h>
31#include <asm/mcfwdebug.h>
Steven King91d60412010-01-22 12:43:03 -080032#include <asm/mcfqspi.h>
Greg Ungerer3196cf82006-06-26 10:33:10 +100033
34/***************************************************************************/
35
Steven King91d60412010-01-22 12:43:03 -080036#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
37static struct resource m532x_qspi_resources[] = {
38 {
39 .start = MCFQSPI_IOBASE,
40 .end = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
41 .flags = IORESOURCE_MEM,
42 },
43 {
44 .start = MCFINT_VECBASE + MCFINT_QSPI,
45 .end = MCFINT_VECBASE + MCFINT_QSPI,
46 .flags = IORESOURCE_IRQ,
47 },
48};
49
50#define MCFQSPI_CS0 84
51#define MCFQSPI_CS1 85
52#define MCFQSPI_CS2 86
53
54static int m532x_cs_setup(struct mcfqspi_cs_control *cs_control)
55{
56 int status;
57
58 status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
59 if (status) {
60 pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
61 goto fail0;
62 }
63 status = gpio_direction_output(MCFQSPI_CS0, 1);
64 if (status) {
65 pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
66 goto fail1;
67 }
68
69 status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
70 if (status) {
71 pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
72 goto fail1;
73 }
74 status = gpio_direction_output(MCFQSPI_CS1, 1);
75 if (status) {
76 pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
77 goto fail2;
78 }
79
80 status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
81 if (status) {
82 pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
83 goto fail2;
84 }
85 status = gpio_direction_output(MCFQSPI_CS2, 1);
86 if (status) {
87 pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
88 goto fail3;
89 }
90
91 return 0;
92
93fail3:
94 gpio_free(MCFQSPI_CS2);
95fail2:
96 gpio_free(MCFQSPI_CS1);
97fail1:
98 gpio_free(MCFQSPI_CS0);
99fail0:
100 return status;
101}
102
103static void m532x_cs_teardown(struct mcfqspi_cs_control *cs_control)
104{
105 gpio_free(MCFQSPI_CS2);
106 gpio_free(MCFQSPI_CS1);
107 gpio_free(MCFQSPI_CS0);
108}
109
110static void m532x_cs_select(struct mcfqspi_cs_control *cs_control,
111 u8 chip_select, bool cs_high)
112{
113 gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
114}
115
116static void m532x_cs_deselect(struct mcfqspi_cs_control *cs_control,
117 u8 chip_select, bool cs_high)
118{
119 gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
120}
121
122static struct mcfqspi_cs_control m532x_cs_control = {
123 .setup = m532x_cs_setup,
124 .teardown = m532x_cs_teardown,
125 .select = m532x_cs_select,
126 .deselect = m532x_cs_deselect,
127};
128
129static struct mcfqspi_platform_data m532x_qspi_data = {
130 .bus_num = 0,
131 .num_chipselect = 3,
132 .cs_control = &m532x_cs_control,
133};
134
135static struct platform_device m532x_qspi = {
136 .name = "mcfqspi",
137 .id = 0,
138 .num_resources = ARRAY_SIZE(m532x_qspi_resources),
139 .resource = m532x_qspi_resources,
140 .dev.platform_data = &m532x_qspi_data,
141};
142
143static void __init m532x_qspi_init(void)
144{
145 /* setup QSPS pins for QSPI with gpio CS control */
146 writew(0x01f0, MCF_GPIO_PAR_QSPI);
147}
148#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
149
150
Greg Ungererb2e18102008-02-01 17:34:58 +1000151static struct platform_device *m532x_devices[] __initdata = {
Steven King91d60412010-01-22 12:43:03 -0800152#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
153 &m532x_qspi,
154#endif
Greg Ungererb2e18102008-02-01 17:34:58 +1000155};
156
157/***************************************************************************/
158
Greg Ungererb2e18102008-02-01 17:34:58 +1000159static void __init m532x_uarts_init(void)
160{
Greg Ungerera75bc612011-12-24 01:04:22 +1000161 /* UART GPIO initialization */
162 MCF_GPIO_PAR_UART |= 0x0FFF;
Greg Ungererb2e18102008-02-01 17:34:58 +1000163}
Greg Ungerera75bc612011-12-24 01:04:22 +1000164
Greg Ungererffba3f42009-02-26 22:40:38 -0800165/***************************************************************************/
166
167static void __init m532x_fec_init(void)
168{
Greg Ungererffba3f42009-02-26 22:40:38 -0800169 /* Set multi-function pins to ethernet mode for fec0 */
170 MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
171 MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
172 MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
173 MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
174}
Greg Ungerer3196cf82006-06-26 10:33:10 +1000175
176/***************************************************************************/
177
Greg Ungerer384feb92009-04-30 22:03:43 +1000178static void m532x_cpu_reset(void)
179{
180 local_irq_disable();
181 __raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
182}
183
184/***************************************************************************/
185
Greg Ungererb2e18102008-02-01 17:34:58 +1000186void __init config_BSP(char *commandp, int size)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000187{
Greg Ungererbc724502007-07-25 22:07:20 +1000188#if !defined(CONFIG_BOOTPARAM)
Greg Ungerer3196cf82006-06-26 10:33:10 +1000189 /* Copy command line from FLASH to local buffer... */
190 memcpy(commandp, (char *) 0x4000, 4);
191 if(strncmp(commandp, "kcl ", 4) == 0){
192 memcpy(commandp, (char *) 0x4004, size);
193 commandp[size-1] = 0;
194 } else {
195 memset(commandp, 0, size);
196 }
197#endif
198
Greg Ungerer35aefb22012-01-23 15:34:58 +1000199 mach_sched_init = hw_timer_init;
200
Greg Ungererb2e18102008-02-01 17:34:58 +1000201#ifdef CONFIG_BDM_DISABLE
Greg Ungerer3196cf82006-06-26 10:33:10 +1000202 /*
203 * Disable the BDM clocking. This also turns off most of the rest of
204 * the BDM device. This is good for EMC reasons. This option is not
205 * incompatible with the memory protection option.
206 */
207 wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
208#endif
209}
210
211/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000212
Greg Ungererb2e18102008-02-01 17:34:58 +1000213static int __init init_BSP(void)
214{
215 m532x_uarts_init();
Greg Ungererffba3f42009-02-26 22:40:38 -0800216 m532x_fec_init();
Steven King91d60412010-01-22 12:43:03 -0800217#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
218 m532x_qspi_init();
219#endif
Greg Ungererb2e18102008-02-01 17:34:58 +1000220 platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
221 return 0;
222}
223
224arch_initcall(init_BSP);
225
226/***************************************************************************/
227/* Board initialization */
228/***************************************************************************/
Greg Ungerer3196cf82006-06-26 10:33:10 +1000229/*
230 * PLL min/max specifications
231 */
232#define MAX_FVCO 500000 /* KHz */
233#define MAX_FSYS 80000 /* KHz */
234#define MIN_FSYS 58333 /* KHz */
235#define FREF 16000 /* KHz */
236
237
238#define MAX_MFD 135 /* Multiplier */
239#define MIN_MFD 88 /* Multiplier */
240#define BUSDIV 6 /* Divider */
241
242/*
243 * Low Power Divider specifications
244 */
245#define MIN_LPD (1 << 0) /* Divider (not encoded) */
246#define MAX_LPD (1 << 15) /* Divider (not encoded) */
247#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
248
249#define SYS_CLK_KHZ 80000
250#define SYSTEM_PERIOD 12.5
251/*
252 * SDRAM Timing Parameters
253 */
254#define SDRAM_BL 8 /* # of beats in a burst */
255#define SDRAM_TWR 2 /* in clocks */
256#define SDRAM_CASL 2.5 /* CASL in clocks */
257#define SDRAM_TRCD 2 /* in clocks */
258#define SDRAM_TRP 2 /* in clocks */
259#define SDRAM_TRFC 7 /* in clocks */
260#define SDRAM_TREFI 7800 /* in ns */
261
262#define EXT_SRAM_ADDRESS (0xC0000000)
263#define FLASH_ADDRESS (0x00000000)
264#define SDRAM_ADDRESS (0x40000000)
265
266#define NAND_FLASH_ADDRESS (0xD0000000)
267
268int sys_clk_khz = 0;
269int sys_clk_mhz = 0;
270
271void wtm_init(void);
272void scm_init(void);
273void gpio_init(void);
274void fbcs_init(void);
275void sdramc_init(void);
276int clock_pll (int fsys, int flags);
277int clock_limp (int);
278int clock_exit_limp (void);
279int get_sys_clock (void);
280
281asmlinkage void __init sysinit(void)
282{
283 sys_clk_khz = clock_pll(0, 0);
284 sys_clk_mhz = sys_clk_khz/1000;
285
286 wtm_init();
287 scm_init();
288 gpio_init();
289 fbcs_init();
290 sdramc_init();
291}
292
293void wtm_init(void)
294{
295 /* Disable watchdog timer */
296 MCF_WTM_WCR = 0;
297}
298
299#define MCF_SCM_BCR_GBW (0x00000100)
300#define MCF_SCM_BCR_GBR (0x00000200)
301
302void scm_init(void)
303{
304 /* All masters are trusted */
305 MCF_SCM_MPR = 0x77777777;
306
307 /* Allow supervisor/user, read/write, and trusted/untrusted
308 access to all slaves */
309 MCF_SCM_PACRA = 0;
310 MCF_SCM_PACRB = 0;
311 MCF_SCM_PACRC = 0;
312 MCF_SCM_PACRD = 0;
313 MCF_SCM_PACRE = 0;
314 MCF_SCM_PACRF = 0;
315
316 /* Enable bursts */
317 MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
318}
319
320
321void fbcs_init(void)
322{
323 MCF_GPIO_PAR_CS = 0x0000003E;
324
325 /* Latch chip select */
326 MCF_FBCS1_CSAR = 0x10080000;
327
328 MCF_FBCS1_CSCR = 0x002A3780;
329 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
330
331 /* Initialize latch to drive signals to inactive states */
332 *((u16 *)(0x10080000)) = 0xFFFF;
333
334 /* External SRAM */
335 MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
336 MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
337 | MCF_FBCS_CSCR_AA
338 | MCF_FBCS_CSCR_SBM
339 | MCF_FBCS_CSCR_WS(1));
340 MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
341 | MCF_FBCS_CSMR_V);
342
343 /* Boot Flash connected to FBCS0 */
344 MCF_FBCS0_CSAR = FLASH_ADDRESS;
345 MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
346 | MCF_FBCS_CSCR_BEM
347 | MCF_FBCS_CSCR_AA
348 | MCF_FBCS_CSCR_SBM
349 | MCF_FBCS_CSCR_WS(7));
350 MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
351 | MCF_FBCS_CSMR_V);
352}
353
354void sdramc_init(void)
355{
356 /*
357 * Check to see if the SDRAM has already been initialized
358 * by a run control tool
359 */
360 if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
361 /* SDRAM chip select initialization */
362
363 /* Initialize SDRAM chip select */
364 MCF_SDRAMC_SDCS0 = (0
365 | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
366 | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
367
368 /*
369 * Basic configuration and initialization
370 */
371 MCF_SDRAMC_SDCFG1 = (0
372 | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
373 | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
374 | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
375 | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
376 | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
377 | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
378 | MCF_SDRAMC_SDCFG1_WTLAT(3));
379 MCF_SDRAMC_SDCFG2 = (0
380 | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
381 | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
382 | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
383 | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
384
385
386 /*
387 * Precharge and enable write to SDMR
388 */
389 MCF_SDRAMC_SDCR = (0
390 | MCF_SDRAMC_SDCR_MODE_EN
391 | MCF_SDRAMC_SDCR_CKE
392 | MCF_SDRAMC_SDCR_DDR
393 | MCF_SDRAMC_SDCR_MUX(1)
394 | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
395 | MCF_SDRAMC_SDCR_PS_16
396 | MCF_SDRAMC_SDCR_IPALL);
397
398 /*
399 * Write extended mode register
400 */
401 MCF_SDRAMC_SDMR = (0
402 | MCF_SDRAMC_SDMR_BNKAD_LEMR
403 | MCF_SDRAMC_SDMR_AD(0x0)
404 | MCF_SDRAMC_SDMR_CMD);
405
406 /*
407 * Write mode register and reset DLL
408 */
409 MCF_SDRAMC_SDMR = (0
410 | MCF_SDRAMC_SDMR_BNKAD_LMR
411 | MCF_SDRAMC_SDMR_AD(0x163)
412 | MCF_SDRAMC_SDMR_CMD);
413
414 /*
415 * Execute a PALL command
416 */
417 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
418
419 /*
420 * Perform two REF cycles
421 */
422 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
423 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
424
425 /*
426 * Write mode register and clear reset DLL
427 */
428 MCF_SDRAMC_SDMR = (0
429 | MCF_SDRAMC_SDMR_BNKAD_LMR
430 | MCF_SDRAMC_SDMR_AD(0x063)
431 | MCF_SDRAMC_SDMR_CMD);
432
433 /*
434 * Enable auto refresh and lock SDMR
435 */
436 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
437 MCF_SDRAMC_SDCR |= (0
438 | MCF_SDRAMC_SDCR_REF
439 | MCF_SDRAMC_SDCR_DQS_OE(0xC));
440 }
441}
442
443void gpio_init(void)
444{
445 /* Enable UART0 pins */
446 MCF_GPIO_PAR_UART = ( 0
447 | MCF_GPIO_PAR_UART_PAR_URXD0
448 | MCF_GPIO_PAR_UART_PAR_UTXD0);
449
450 /* Initialize TIN3 as a GPIO output to enable the write
451 half of the latch */
452 MCF_GPIO_PAR_TIMER = 0x00;
sfking@fdwdc.com7846fe82009-06-19 18:11:10 -0700453 __raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
454 __raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
Greg Ungerer3196cf82006-06-26 10:33:10 +1000455
456}
457
458int clock_pll(int fsys, int flags)
459{
460 int fref, temp, fout, mfd;
461 u32 i;
462
463 fref = FREF;
464
465 if (fsys == 0) {
466 /* Return current PLL output */
467 mfd = MCF_PLL_PFDR;
468
469 return (fref * mfd / (BUSDIV * 4));
470 }
471
472 /* Check bounds of requested system clock */
473 if (fsys > MAX_FSYS)
474 fsys = MAX_FSYS;
475 if (fsys < MIN_FSYS)
476 fsys = MIN_FSYS;
477
478 /* Multiplying by 100 when calculating the temp value,
479 and then dividing by 100 to calculate the mfd allows
480 for exact values without needing to include floating
481 point libraries. */
482 temp = 100 * fsys / fref;
483 mfd = 4 * BUSDIV * temp / 100;
484
485 /* Determine the output frequency for selected values */
486 fout = (fref * mfd / (BUSDIV * 4));
487
488 /*
489 * Check to see if the SDRAM has already been initialized.
490 * If it has then the SDRAM needs to be put into self refresh
491 * mode before reprogramming the PLL.
492 */
493 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
494 /* Put SDRAM into self refresh mode */
495 MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
496
497 /*
498 * Initialize the PLL to generate the new system clock frequency.
499 * The device must be put into LIMP mode to reprogram the PLL.
500 */
501
502 /* Enter LIMP mode */
503 clock_limp(DEFAULT_LPD);
504
505 /* Reprogram PLL for desired fsys */
506 MCF_PLL_PODR = (0
507 | MCF_PLL_PODR_CPUDIV(BUSDIV/3)
508 | MCF_PLL_PODR_BUSDIV(BUSDIV));
509
510 MCF_PLL_PFDR = mfd;
511
512 /* Exit LIMP mode */
513 clock_exit_limp();
514
515 /*
516 * Return the SDRAM to normal operation if it is in use.
517 */
518 if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
519 /* Exit self refresh mode */
520 MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
521
522 /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
523 MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
524
525 /* wait for DQS logic to relock */
526 for (i = 0; i < 0x200; i++)
527 ;
528
529 return fout;
530}
531
532int clock_limp(int div)
533{
534 u32 temp;
535
536 /* Check bounds of divider */
537 if (div < MIN_LPD)
538 div = MIN_LPD;
539 if (div > MAX_LPD)
540 div = MAX_LPD;
541
542 /* Save of the current value of the SSIDIV so we don't
543 overwrite the value*/
544 temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
545
546 /* Apply the divider to the system clock */
547 MCF_CCM_CDR = ( 0
548 | MCF_CCM_CDR_LPDIV(div)
549 | MCF_CCM_CDR_SSIDIV(temp));
550
551 MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
552
553 return (FREF/(3*(1 << div)));
554}
555
556int clock_exit_limp(void)
557{
558 int fout;
559
560 /* Exit LIMP mode */
561 MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
562
563 /* Wait for PLL to lock */
564 while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
565 ;
566
567 fout = get_sys_clock();
568
569 return fout;
570}
571
572int get_sys_clock(void)
573{
574 int divider;
575
576 /* Test to see if device is in LIMP mode */
577 if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
578 divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
579 return (FREF/(2 << divider));
580 }
581 else
582 return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
583}