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