Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/m68k/coldfire/m53xx.c
26451 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/***************************************************************************/
3
4
/*
5
* m53xx.c -- platform support for ColdFire 53xx based boards
6
*
7
* Copyright (C) 1999-2002, Greg Ungerer ([email protected])
8
* Copyright (C) 2000, Lineo (www.lineo.com)
9
* Yaroslav Vinogradov [email protected]
10
* Copyright Freescale Semiconductor, Inc 2006
11
* Copyright (c) 2006, emlix, Sebastian Hess <[email protected]>
12
*/
13
14
/***************************************************************************/
15
16
#include <linux/clkdev.h>
17
#include <linux/kernel.h>
18
#include <linux/param.h>
19
#include <linux/init.h>
20
#include <linux/io.h>
21
#include <asm/machdep.h>
22
#include <asm/coldfire.h>
23
#include <asm/mcfsim.h>
24
#include <asm/mcfuart.h>
25
#include <asm/mcfdma.h>
26
#include <asm/mcfwdebug.h>
27
#include <asm/mcfclk.h>
28
29
/***************************************************************************/
30
31
DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
32
DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
33
DEFINE_CLK(0, "fec.0", 12, MCF_CLK);
34
DEFINE_CLK(0, "edma", 17, MCF_CLK);
35
DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
36
DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
37
DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
38
DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
39
DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
40
DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
41
DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
42
DEFINE_CLK(0, "mcfuart.2", 26, MCF_BUSCLK);
43
DEFINE_CLK(0, "mcftmr.0", 28, MCF_CLK);
44
DEFINE_CLK(0, "mcftmr.1", 29, MCF_CLK);
45
DEFINE_CLK(0, "mcftmr.2", 30, MCF_CLK);
46
DEFINE_CLK(0, "mcftmr.3", 31, MCF_CLK);
47
48
DEFINE_CLK(0, "mcfpit.0", 32, MCF_CLK);
49
DEFINE_CLK(0, "mcfpit.1", 33, MCF_CLK);
50
DEFINE_CLK(0, "mcfpit.2", 34, MCF_CLK);
51
DEFINE_CLK(0, "mcfpit.3", 35, MCF_CLK);
52
DEFINE_CLK(0, "mcfpwm.0", 36, MCF_CLK);
53
DEFINE_CLK(0, "mcfeport.0", 37, MCF_CLK);
54
DEFINE_CLK(0, "mcfwdt.0", 38, MCF_CLK);
55
DEFINE_CLK(0, "sys.0", 40, MCF_BUSCLK);
56
DEFINE_CLK(0, "gpio.0", 41, MCF_BUSCLK);
57
DEFINE_CLK(0, "mcfrtc.0", 42, MCF_CLK);
58
DEFINE_CLK(0, "mcflcd.0", 43, MCF_CLK);
59
DEFINE_CLK(0, "mcfusb-otg.0", 44, MCF_CLK);
60
DEFINE_CLK(0, "mcfusb-host.0", 45, MCF_CLK);
61
DEFINE_CLK(0, "sdram.0", 46, MCF_CLK);
62
DEFINE_CLK(0, "ssi.0", 47, MCF_CLK);
63
DEFINE_CLK(0, "pll.0", 48, MCF_CLK);
64
65
DEFINE_CLK(1, "mdha.0", 32, MCF_CLK);
66
DEFINE_CLK(1, "skha.0", 33, MCF_CLK);
67
DEFINE_CLK(1, "rng.0", 34, MCF_CLK);
68
69
static struct clk_lookup m53xx_clk_lookup[] = {
70
CLKDEV_INIT("flexbus", NULL, &__clk_0_2),
71
CLKDEV_INIT("mcfcan.0", NULL, &__clk_0_8),
72
CLKDEV_INIT("fec.0", NULL, &__clk_0_12),
73
CLKDEV_INIT("edma", NULL, &__clk_0_17),
74
CLKDEV_INIT("intc.0", NULL, &__clk_0_18),
75
CLKDEV_INIT("intc.1", NULL, &__clk_0_19),
76
CLKDEV_INIT("iack.0", NULL, &__clk_0_21),
77
CLKDEV_INIT("imx1-i2c.0", NULL, &__clk_0_22),
78
CLKDEV_INIT("mcfqspi.0", NULL, &__clk_0_23),
79
CLKDEV_INIT("mcfuart.0", NULL, &__clk_0_24),
80
CLKDEV_INIT("mcfuart.1", NULL, &__clk_0_25),
81
CLKDEV_INIT("mcfuart.2", NULL, &__clk_0_26),
82
CLKDEV_INIT("mcftmr.0", NULL, &__clk_0_28),
83
CLKDEV_INIT("mcftmr.1", NULL, &__clk_0_29),
84
CLKDEV_INIT("mcftmr.2", NULL, &__clk_0_30),
85
CLKDEV_INIT("mcftmr.3", NULL, &__clk_0_31),
86
CLKDEV_INIT("mcfpit.0", NULL, &__clk_0_32),
87
CLKDEV_INIT("mcfpit.1", NULL, &__clk_0_33),
88
CLKDEV_INIT("mcfpit.2", NULL, &__clk_0_34),
89
CLKDEV_INIT("mcfpit.3", NULL, &__clk_0_35),
90
CLKDEV_INIT("mcfpwm.0", NULL, &__clk_0_36),
91
CLKDEV_INIT("mcfeport.0", NULL, &__clk_0_37),
92
CLKDEV_INIT("mcfwdt.0", NULL, &__clk_0_38),
93
CLKDEV_INIT(NULL, "sys.0", &__clk_0_40),
94
CLKDEV_INIT("gpio.0", NULL, &__clk_0_41),
95
CLKDEV_INIT("mcfrtc.0", NULL, &__clk_0_42),
96
CLKDEV_INIT("mcflcd.0", NULL, &__clk_0_43),
97
CLKDEV_INIT("mcfusb-otg.0", NULL, &__clk_0_44),
98
CLKDEV_INIT("mcfusb-host.0", NULL, &__clk_0_45),
99
CLKDEV_INIT("sdram.0", NULL, &__clk_0_46),
100
CLKDEV_INIT("ssi.0", NULL, &__clk_0_47),
101
CLKDEV_INIT(NULL, "pll.0", &__clk_0_48),
102
CLKDEV_INIT("mdha.0", NULL, &__clk_1_32),
103
CLKDEV_INIT("skha.0", NULL, &__clk_1_33),
104
CLKDEV_INIT("rng.0", NULL, &__clk_1_34),
105
};
106
107
static struct clk * const enable_clks[] __initconst = {
108
&__clk_0_2, /* flexbus */
109
&__clk_0_18, /* intc.0 */
110
&__clk_0_19, /* intc.1 */
111
&__clk_0_21, /* iack.0 */
112
&__clk_0_24, /* mcfuart.0 */
113
&__clk_0_25, /* mcfuart.1 */
114
&__clk_0_26, /* mcfuart.2 */
115
&__clk_0_28, /* mcftmr.0 */
116
&__clk_0_29, /* mcftmr.1 */
117
&__clk_0_32, /* mcfpit.0 */
118
&__clk_0_33, /* mcfpit.1 */
119
&__clk_0_37, /* mcfeport.0 */
120
&__clk_0_40, /* sys.0 */
121
&__clk_0_41, /* gpio.0 */
122
&__clk_0_46, /* sdram.0 */
123
&__clk_0_48, /* pll.0 */
124
};
125
126
static struct clk * const disable_clks[] __initconst = {
127
&__clk_0_8, /* mcfcan.0 */
128
&__clk_0_12, /* fec.0 */
129
&__clk_0_17, /* edma */
130
&__clk_0_22, /* imx1-i2c.0 */
131
&__clk_0_23, /* mcfqspi.0 */
132
&__clk_0_30, /* mcftmr.2 */
133
&__clk_0_31, /* mcftmr.3 */
134
&__clk_0_34, /* mcfpit.2 */
135
&__clk_0_35, /* mcfpit.3 */
136
&__clk_0_36, /* mcfpwm.0 */
137
&__clk_0_38, /* mcfwdt.0 */
138
&__clk_0_42, /* mcfrtc.0 */
139
&__clk_0_43, /* mcflcd.0 */
140
&__clk_0_44, /* mcfusb-otg.0 */
141
&__clk_0_45, /* mcfusb-host.0 */
142
&__clk_0_47, /* ssi.0 */
143
&__clk_1_32, /* mdha.0 */
144
&__clk_1_33, /* skha.0 */
145
&__clk_1_34, /* rng.0 */
146
};
147
148
149
static void __init m53xx_clk_init(void)
150
{
151
unsigned i;
152
153
/* make sure these clocks are enabled */
154
for (i = 0; i < ARRAY_SIZE(enable_clks); ++i)
155
__clk_init_enabled(enable_clks[i]);
156
/* make sure these clocks are disabled */
157
for (i = 0; i < ARRAY_SIZE(disable_clks); ++i)
158
__clk_init_disabled(disable_clks[i]);
159
160
clkdev_add_table(m53xx_clk_lookup, ARRAY_SIZE(m53xx_clk_lookup));
161
}
162
163
/***************************************************************************/
164
165
static void __init m53xx_qspi_init(void)
166
{
167
#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
168
/* setup QSPS pins for QSPI with gpio CS control */
169
writew(0x01f0, MCFGPIO_PAR_QSPI);
170
#endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
171
}
172
173
/***************************************************************************/
174
175
static void __init m53xx_i2c_init(void)
176
{
177
#if IS_ENABLED(CONFIG_I2C_IMX)
178
/* setup Port AS Pin Assignment Register for I2C */
179
/* set PASPA0 to SCL and PASPA1 to SDA */
180
u8 r = readb(MCFGPIO_PAR_FECI2C);
181
r |= 0x0f;
182
writeb(r, MCFGPIO_PAR_FECI2C);
183
#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
184
}
185
186
/***************************************************************************/
187
188
static void __init m53xx_uarts_init(void)
189
{
190
/* UART GPIO initialization */
191
writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART);
192
}
193
194
/***************************************************************************/
195
196
static void __init m53xx_fec_init(void)
197
{
198
u8 v;
199
200
/* Set multi-function pins to ethernet mode for fec0 */
201
v = readb(MCFGPIO_PAR_FECI2C);
202
v |= MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
203
MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO;
204
writeb(v, MCFGPIO_PAR_FECI2C);
205
206
v = readb(MCFGPIO_PAR_FEC);
207
v = MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC | MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC;
208
writeb(v, MCFGPIO_PAR_FEC);
209
}
210
211
/***************************************************************************/
212
213
void __init config_BSP(char *commandp, int size)
214
{
215
#if !defined(CONFIG_BOOTPARAM)
216
/* Copy command line from FLASH to local buffer... */
217
memcpy(commandp, (char *) 0x4000, 4);
218
if(strncmp(commandp, "kcl ", 4) == 0){
219
memcpy(commandp, (char *) 0x4004, size);
220
commandp[size-1] = 0;
221
} else {
222
memset(commandp, 0, size);
223
}
224
#endif
225
mach_sched_init = hw_timer_init;
226
m53xx_clk_init();
227
m53xx_uarts_init();
228
m53xx_fec_init();
229
m53xx_qspi_init();
230
m53xx_i2c_init();
231
232
#ifdef CONFIG_BDM_DISABLE
233
/*
234
* Disable the BDM clocking. This also turns off most of the rest of
235
* the BDM device. This is good for EMC reasons. This option is not
236
* incompatible with the memory protection option.
237
*/
238
wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
239
#endif
240
}
241
242
/***************************************************************************/
243
/* Board initialization */
244
/***************************************************************************/
245
/*
246
* PLL min/max specifications
247
*/
248
#define MAX_FVCO 500000 /* KHz */
249
#define MAX_FSYS 80000 /* KHz */
250
#define MIN_FSYS 58333 /* KHz */
251
#define FREF 16000 /* KHz */
252
253
254
#define MAX_MFD 135 /* Multiplier */
255
#define MIN_MFD 88 /* Multiplier */
256
#define BUSDIV 6 /* Divider */
257
258
/*
259
* Low Power Divider specifications
260
*/
261
#define MIN_LPD (1 << 0) /* Divider (not encoded) */
262
#define MAX_LPD (1 << 15) /* Divider (not encoded) */
263
#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
264
265
#define SYS_CLK_KHZ 80000
266
#define SYSTEM_PERIOD 12.5
267
/*
268
* SDRAM Timing Parameters
269
*/
270
#define SDRAM_BL 8 /* # of beats in a burst */
271
#define SDRAM_TWR 2 /* in clocks */
272
#define SDRAM_CASL 2.5 /* CASL in clocks */
273
#define SDRAM_TRCD 2 /* in clocks */
274
#define SDRAM_TRP 2 /* in clocks */
275
#define SDRAM_TRFC 7 /* in clocks */
276
#define SDRAM_TREFI 7800 /* in ns */
277
278
#define EXT_SRAM_ADDRESS (0xC0000000)
279
#define FLASH_ADDRESS (0x00000000)
280
#define SDRAM_ADDRESS (0x40000000)
281
282
#define NAND_FLASH_ADDRESS (0xD0000000)
283
284
void wtm_init(void);
285
void scm_init(void);
286
void gpio_init(void);
287
void fbcs_init(void);
288
void sdramc_init(void);
289
int clock_pll (int fsys, int flags);
290
int clock_limp (int);
291
int clock_exit_limp (void);
292
int get_sys_clock (void);
293
294
asmlinkage void __init sysinit(void)
295
{
296
clock_pll(0, 0);
297
298
wtm_init();
299
scm_init();
300
gpio_init();
301
fbcs_init();
302
sdramc_init();
303
}
304
305
void wtm_init(void)
306
{
307
/* Disable watchdog timer */
308
writew(0, MCF_WTM_WCR);
309
}
310
311
#define MCF_SCM_BCR_GBW (0x00000100)
312
#define MCF_SCM_BCR_GBR (0x00000200)
313
314
void scm_init(void)
315
{
316
/* All masters are trusted */
317
writel(0x77777777, MCF_SCM_MPR);
318
319
/* Allow supervisor/user, read/write, and trusted/untrusted
320
access to all slaves */
321
writel(0, MCF_SCM_PACRA);
322
writel(0, MCF_SCM_PACRB);
323
writel(0, MCF_SCM_PACRC);
324
writel(0, MCF_SCM_PACRD);
325
writel(0, MCF_SCM_PACRE);
326
writel(0, MCF_SCM_PACRF);
327
328
/* Enable bursts */
329
writel(MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW, MCF_SCM_BCR);
330
}
331
332
333
void fbcs_init(void)
334
{
335
writeb(0x3E, MCFGPIO_PAR_CS);
336
337
/* Latch chip select */
338
writel(0x10080000, MCF_FBCS1_CSAR);
339
340
writel(0x002A3780, MCF_FBCS1_CSCR);
341
writel(MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
342
343
/* Initialize latch to drive signals to inactive states */
344
writew(0xffff, 0x10080000);
345
346
/* External SRAM */
347
writel(EXT_SRAM_ADDRESS, MCF_FBCS1_CSAR);
348
writel(MCF_FBCS_CSCR_PS_16 |
349
MCF_FBCS_CSCR_AA |
350
MCF_FBCS_CSCR_SBM |
351
MCF_FBCS_CSCR_WS(1),
352
MCF_FBCS1_CSCR);
353
writel(MCF_FBCS_CSMR_BAM_512K | MCF_FBCS_CSMR_V, MCF_FBCS1_CSMR);
354
355
/* Boot Flash connected to FBCS0 */
356
writel(FLASH_ADDRESS, MCF_FBCS0_CSAR);
357
writel(MCF_FBCS_CSCR_PS_16 |
358
MCF_FBCS_CSCR_BEM |
359
MCF_FBCS_CSCR_AA |
360
MCF_FBCS_CSCR_SBM |
361
MCF_FBCS_CSCR_WS(7),
362
MCF_FBCS0_CSCR);
363
writel(MCF_FBCS_CSMR_BAM_32M | MCF_FBCS_CSMR_V, MCF_FBCS0_CSMR);
364
}
365
366
void sdramc_init(void)
367
{
368
/*
369
* Check to see if the SDRAM has already been initialized
370
* by a run control tool
371
*/
372
if (!(readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)) {
373
/* SDRAM chip select initialization */
374
375
/* Initialize SDRAM chip select */
376
writel(MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) |
377
MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE),
378
MCF_SDRAMC_SDCS0);
379
380
/*
381
* Basic configuration and initialization
382
*/
383
writel(MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5)) |
384
MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) |
385
MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL * 2) + 2)) |
386
MCF_SDRAMC_SDCFG1_ACT2RW((int)(SDRAM_TRCD + 0.5)) |
387
MCF_SDRAMC_SDCFG1_PRE2ACT((int)(SDRAM_TRP + 0.5)) |
388
MCF_SDRAMC_SDCFG1_REF2ACT((int)(SDRAM_TRFC + 0.5)) |
389
MCF_SDRAMC_SDCFG1_WTLAT(3),
390
MCF_SDRAMC_SDCFG1);
391
writel(MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL / 2 + 1) |
392
MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL / 2 + SDRAM_TWR) |
393
MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL + SDRAM_BL / 2 - 1.0) + 0.5)) |
394
MCF_SDRAMC_SDCFG2_BL(SDRAM_BL - 1),
395
MCF_SDRAMC_SDCFG2);
396
397
398
/*
399
* Precharge and enable write to SDMR
400
*/
401
writel(MCF_SDRAMC_SDCR_MODE_EN |
402
MCF_SDRAMC_SDCR_CKE |
403
MCF_SDRAMC_SDCR_DDR |
404
MCF_SDRAMC_SDCR_MUX(1) |
405
MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI / (SYSTEM_PERIOD * 64)) - 1) + 0.5)) |
406
MCF_SDRAMC_SDCR_PS_16 |
407
MCF_SDRAMC_SDCR_IPALL,
408
MCF_SDRAMC_SDCR);
409
410
/*
411
* Write extended mode register
412
*/
413
writel(MCF_SDRAMC_SDMR_BNKAD_LEMR |
414
MCF_SDRAMC_SDMR_AD(0x0) |
415
MCF_SDRAMC_SDMR_CMD,
416
MCF_SDRAMC_SDMR);
417
418
/*
419
* Write mode register and reset DLL
420
*/
421
writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
422
MCF_SDRAMC_SDMR_AD(0x163) |
423
MCF_SDRAMC_SDMR_CMD,
424
MCF_SDRAMC_SDMR);
425
426
/*
427
* Execute a PALL command
428
*/
429
writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IPALL, MCF_SDRAMC_SDCR);
430
431
/*
432
* Perform two REF cycles
433
*/
434
writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
435
writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_IREF, MCF_SDRAMC_SDCR);
436
437
/*
438
* Write mode register and clear reset DLL
439
*/
440
writel(MCF_SDRAMC_SDMR_BNKAD_LMR |
441
MCF_SDRAMC_SDMR_AD(0x063) |
442
MCF_SDRAMC_SDMR_CMD,
443
MCF_SDRAMC_SDMR);
444
445
/*
446
* Enable auto refresh and lock SDMR
447
*/
448
writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_MODE_EN,
449
MCF_SDRAMC_SDCR);
450
writel(MCF_SDRAMC_SDCR_REF | MCF_SDRAMC_SDCR_DQS_OE(0xC),
451
MCF_SDRAMC_SDCR);
452
}
453
}
454
455
void gpio_init(void)
456
{
457
/* Enable UART0 pins */
458
writew(MCF_GPIO_PAR_UART_PAR_URXD0 | MCF_GPIO_PAR_UART_PAR_UTXD0,
459
MCFGPIO_PAR_UART);
460
461
/*
462
* Initialize TIN3 as a GPIO output to enable the write
463
* half of the latch.
464
*/
465
writeb(0x00, MCFGPIO_PAR_TIMER);
466
writeb(0x08, MCFGPIO_PDDR_TIMER);
467
writeb(0x00, MCFGPIO_PCLRR_TIMER);
468
}
469
470
int clock_pll(int fsys, int flags)
471
{
472
int fref, temp, fout, mfd;
473
u32 i;
474
475
fref = FREF;
476
477
if (fsys == 0) {
478
/* Return current PLL output */
479
mfd = readb(MCF_PLL_PFDR);
480
481
return (fref * mfd / (BUSDIV * 4));
482
}
483
484
/* Check bounds of requested system clock */
485
if (fsys > MAX_FSYS)
486
fsys = MAX_FSYS;
487
if (fsys < MIN_FSYS)
488
fsys = MIN_FSYS;
489
490
/* Multiplying by 100 when calculating the temp value,
491
and then dividing by 100 to calculate the mfd allows
492
for exact values without needing to include floating
493
point libraries. */
494
temp = 100 * fsys / fref;
495
mfd = 4 * BUSDIV * temp / 100;
496
497
/* Determine the output frequency for selected values */
498
fout = (fref * mfd / (BUSDIV * 4));
499
500
/*
501
* Check to see if the SDRAM has already been initialized.
502
* If it has then the SDRAM needs to be put into self refresh
503
* mode before reprogramming the PLL.
504
*/
505
if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
506
/* Put SDRAM into self refresh mode */
507
writel(readl(MCF_SDRAMC_SDCR) & ~MCF_SDRAMC_SDCR_CKE,
508
MCF_SDRAMC_SDCR);
509
510
/*
511
* Initialize the PLL to generate the new system clock frequency.
512
* The device must be put into LIMP mode to reprogram the PLL.
513
*/
514
515
/* Enter LIMP mode */
516
clock_limp(DEFAULT_LPD);
517
518
/* Reprogram PLL for desired fsys */
519
writeb(MCF_PLL_PODR_CPUDIV(BUSDIV/3) | MCF_PLL_PODR_BUSDIV(BUSDIV),
520
MCF_PLL_PODR);
521
522
writeb(mfd, MCF_PLL_PFDR);
523
524
/* Exit LIMP mode */
525
clock_exit_limp();
526
527
/*
528
* Return the SDRAM to normal operation if it is in use.
529
*/
530
if (readl(MCF_SDRAMC_SDCR) & MCF_SDRAMC_SDCR_REF)
531
/* Exit self refresh mode */
532
writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE,
533
MCF_SDRAMC_SDCR);
534
535
/* Errata - workaround for SDRAM operation after exiting LIMP mode */
536
writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX);
537
538
/* wait for DQS logic to relock */
539
for (i = 0; i < 0x200; i++)
540
;
541
542
return fout;
543
}
544
545
int clock_limp(int div)
546
{
547
u32 temp;
548
549
/* Check bounds of divider */
550
if (div < MIN_LPD)
551
div = MIN_LPD;
552
if (div > MAX_LPD)
553
div = MAX_LPD;
554
555
/* Save of the current value of the SSIDIV so we don't
556
overwrite the value*/
557
temp = readw(MCF_CCM_CDR) & MCF_CCM_CDR_SSIDIV(0xF);
558
559
/* Apply the divider to the system clock */
560
writew(MCF_CCM_CDR_LPDIV(div) | MCF_CCM_CDR_SSIDIV(temp), MCF_CCM_CDR);
561
562
writew(readw(MCF_CCM_MISCCR) | MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
563
564
return (FREF/(3*(1 << div)));
565
}
566
567
int clock_exit_limp(void)
568
{
569
int fout;
570
571
/* Exit LIMP mode */
572
writew(readw(MCF_CCM_MISCCR) & ~MCF_CCM_MISCCR_LIMP, MCF_CCM_MISCCR);
573
574
/* Wait for PLL to lock */
575
while (!(readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_PLL_LOCK))
576
;
577
578
fout = get_sys_clock();
579
580
return fout;
581
}
582
583
int get_sys_clock(void)
584
{
585
int divider;
586
587
/* Test to see if device is in LIMP mode */
588
if (readw(MCF_CCM_MISCCR) & MCF_CCM_MISCCR_LIMP) {
589
divider = readw(MCF_CCM_CDR) & MCF_CCM_CDR_LPDIV(0xF);
590
return (FREF/(2 << divider));
591
}
592
else
593
return (FREF * readb(MCF_PLL_PFDR)) / (BUSDIV * 4);
594
}
595
596