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