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 (gerg@snapgear.com)
8 * Copyright (C) 2000, Lineo (www.lineo.com)
9 * Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
10 * Copyright Freescale Semiconductor, Inc 2006
11 * Copyright (c) 2006, emlix, Sebastian Hess <shess@hessware.de>
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
31DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
32DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
33DEFINE_CLK(0, "fec.0", 12, MCF_CLK);
34DEFINE_CLK(0, "edma", 17, MCF_CLK);
35DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
36DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
37DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
38DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
39DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
40DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
41DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
42DEFINE_CLK(0, "mcfuart.2", 26, MCF_BUSCLK);
43DEFINE_CLK(0, "mcftmr.0", 28, MCF_CLK);
44DEFINE_CLK(0, "mcftmr.1", 29, MCF_CLK);
45DEFINE_CLK(0, "mcftmr.2", 30, MCF_CLK);
46DEFINE_CLK(0, "mcftmr.3", 31, MCF_CLK);
47
48DEFINE_CLK(0, "mcfpit.0", 32, MCF_CLK);
49DEFINE_CLK(0, "mcfpit.1", 33, MCF_CLK);
50DEFINE_CLK(0, "mcfpit.2", 34, MCF_CLK);
51DEFINE_CLK(0, "mcfpit.3", 35, MCF_CLK);
52DEFINE_CLK(0, "mcfpwm.0", 36, MCF_CLK);
53DEFINE_CLK(0, "mcfeport.0", 37, MCF_CLK);
54DEFINE_CLK(0, "mcfwdt.0", 38, MCF_CLK);
55DEFINE_CLK(0, "sys.0", 40, MCF_BUSCLK);
56DEFINE_CLK(0, "gpio.0", 41, MCF_BUSCLK);
57DEFINE_CLK(0, "mcfrtc.0", 42, MCF_CLK);
58DEFINE_CLK(0, "mcflcd.0", 43, MCF_CLK);
59DEFINE_CLK(0, "mcfusb-otg.0", 44, MCF_CLK);
60DEFINE_CLK(0, "mcfusb-host.0", 45, MCF_CLK);
61DEFINE_CLK(0, "sdram.0", 46, MCF_CLK);
62DEFINE_CLK(0, "ssi.0", 47, MCF_CLK);
63DEFINE_CLK(0, "pll.0", 48, MCF_CLK);
64
65DEFINE_CLK(1, "mdha.0", 32, MCF_CLK);
66DEFINE_CLK(1, "skha.0", 33, MCF_CLK);
67DEFINE_CLK(1, "rng.0", 34, MCF_CLK);
68
69static 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
107static 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
126static 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
149static 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
165static 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
175static 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
188static 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
196static 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
213void __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
284void wtm_init(void);
285void scm_init(void);
286void gpio_init(void);
287void fbcs_init(void);
288void sdramc_init(void);
289int clock_pll (int fsys, int flags);
290int clock_limp (int);
291int clock_exit_limp (void);
292int get_sys_clock (void);
293
294asmlinkage void __init sysinit(void)
295{
296 clock_pll(fsys: 0, flags: 0);
297
298 wtm_init();
299 scm_init();
300 gpio_init();
301 fbcs_init();
302 sdramc_init();
303}
304
305void 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
314void 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
333void 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(val: 0xffff, addr: 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
366void 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
455void 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
470int 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
545int 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
567int 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
583int 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

source code of linux/arch/m68k/coldfire/m53xx.c