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