xref: /rk3399_rockchip-uboot/arch/arm/cpu/arm1136/mx35/generic.c (revision 09bc3d04d95c7a2be965d4f173a5e2946ca903c3)
1b9bb0531SStefano Babic /*
2b9bb0531SStefano Babic  * (C) Copyright 2007
3b9bb0531SStefano Babic  * Sascha Hauer, Pengutronix
4b9bb0531SStefano Babic  *
5b9bb0531SStefano Babic  * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
6b9bb0531SStefano Babic  *
7b9bb0531SStefano Babic  * See file CREDITS for list of people who contributed to this
8b9bb0531SStefano Babic  * project.
9b9bb0531SStefano Babic  *
10b9bb0531SStefano Babic  * This program is free software; you can redistribute it and/or
11b9bb0531SStefano Babic  * modify it under the terms of the GNU General Public License as
12b9bb0531SStefano Babic  * published by the Free Software Foundation; either version 2 of
13b9bb0531SStefano Babic  * the License, or (at your option) any later version.
14b9bb0531SStefano Babic  *
15b9bb0531SStefano Babic  * This program is distributed in the hope that it will be useful,
16b9bb0531SStefano Babic  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17b9bb0531SStefano Babic  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18b9bb0531SStefano Babic  * GNU General Public License for more details.
19b9bb0531SStefano Babic  *
20b9bb0531SStefano Babic  * You should have received a copy of the GNU General Public License
21b9bb0531SStefano Babic  * along with this program; if not, write to the Free Software
22b9bb0531SStefano Babic  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23b9bb0531SStefano Babic  * MA 02111-1307 USA
24b9bb0531SStefano Babic  */
25b9bb0531SStefano Babic 
26b9bb0531SStefano Babic #include <common.h>
27b9bb0531SStefano Babic #include <asm/io.h>
28b9bb0531SStefano Babic #include <asm/errno.h>
29b9bb0531SStefano Babic #include <asm/arch/imx-regs.h>
30b9bb0531SStefano Babic #include <asm/arch/crm_regs.h>
31b9bb0531SStefano Babic #include <asm/arch/clock.h>
32b9bb0531SStefano Babic #include <asm/arch/sys_proto.h>
33*09bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC
34*09bc3d04SBenoît Thébaudeau #include <fsl_esdhc.h>
35*09bc3d04SBenoît Thébaudeau #endif
36b9bb0531SStefano Babic #include <netdev.h>
37b9bb0531SStefano Babic 
38b9bb0531SStefano Babic #define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel))
39b9bb0531SStefano Babic #define CLK_CODE_ARM(c)		(((c) >> 16) & 0xFF)
40b9bb0531SStefano Babic #define CLK_CODE_AHB(c)		(((c) >>  8) & 0xFF)
41b9bb0531SStefano Babic #define CLK_CODE_PATH(c)	((c) & 0xFF)
42b9bb0531SStefano Babic 
43b9bb0531SStefano Babic #define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o))
44b9bb0531SStefano Babic 
45b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC
46b9bb0531SStefano Babic DECLARE_GLOBAL_DATA_PTR;
47b9bb0531SStefano Babic #endif
48b9bb0531SStefano Babic 
49b9bb0531SStefano Babic static int g_clk_mux_auto[8] = {
50b9bb0531SStefano Babic 	CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1,
51b9bb0531SStefano Babic 	CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1,
52b9bb0531SStefano Babic };
53b9bb0531SStefano Babic 
54b9bb0531SStefano Babic static int g_clk_mux_consumer[16] = {
55b9bb0531SStefano Babic 	CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1,
56b9bb0531SStefano Babic 	-1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0),
57b9bb0531SStefano Babic 	CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1,
58b9bb0531SStefano Babic 	-1, -1, CLK_CODE(4, 2, 0), -1,
59b9bb0531SStefano Babic };
60b9bb0531SStefano Babic 
61b9bb0531SStefano Babic static int hsp_div_table[3][16] = {
62b9bb0531SStefano Babic 	{4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1},
63b9bb0531SStefano Babic 	{-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1},
64b9bb0531SStefano Babic 	{3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1},
65b9bb0531SStefano Babic };
66b9bb0531SStefano Babic 
67b9bb0531SStefano Babic u32 get_cpu_rev(void)
68b9bb0531SStefano Babic {
69b9bb0531SStefano Babic 	int reg;
70b9bb0531SStefano Babic 	struct iim_regs *iim =
71b9bb0531SStefano Babic 		(struct iim_regs *)IIM_BASE_ADDR;
72b9bb0531SStefano Babic 	reg = readl(&iim->iim_srev);
73b9bb0531SStefano Babic 	if (!reg) {
74b9bb0531SStefano Babic 		reg = readw(ROMPATCH_REV);
75b9bb0531SStefano Babic 		reg <<= 4;
76b9bb0531SStefano Babic 	} else {
77b9bb0531SStefano Babic 		reg += CHIP_REV_1_0;
78b9bb0531SStefano Babic 	}
79b9bb0531SStefano Babic 
80b9bb0531SStefano Babic 	return 0x35000 + (reg & 0xFF);
81b9bb0531SStefano Babic }
82b9bb0531SStefano Babic 
83b9bb0531SStefano Babic static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd)
84b9bb0531SStefano Babic {
85b9bb0531SStefano Babic 	int *pclk_mux;
86b9bb0531SStefano Babic 	if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
87b9bb0531SStefano Babic 		pclk_mux = g_clk_mux_consumer +
88b9bb0531SStefano Babic 			((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
89b9bb0531SStefano Babic 			MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
90b9bb0531SStefano Babic 	} else {
91b9bb0531SStefano Babic 		pclk_mux = g_clk_mux_auto +
92b9bb0531SStefano Babic 			((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >>
93b9bb0531SStefano Babic 			MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET);
94b9bb0531SStefano Babic 	}
95b9bb0531SStefano Babic 
96b9bb0531SStefano Babic 	if ((*pclk_mux) == -1)
97b9bb0531SStefano Babic 		return -1;
98b9bb0531SStefano Babic 
99b9bb0531SStefano Babic 	if (fi && fd) {
100b9bb0531SStefano Babic 		if (!CLK_CODE_PATH(*pclk_mux)) {
101b9bb0531SStefano Babic 			*fi = *fd = 1;
102b9bb0531SStefano Babic 			return CLK_CODE_ARM(*pclk_mux);
103b9bb0531SStefano Babic 		}
104b9bb0531SStefano Babic 		if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
105b9bb0531SStefano Babic 			*fi = 3;
106b9bb0531SStefano Babic 			*fd = 4;
107b9bb0531SStefano Babic 		} else {
108b9bb0531SStefano Babic 			*fi = 2;
109b9bb0531SStefano Babic 			*fd = 3;
110b9bb0531SStefano Babic 		}
111b9bb0531SStefano Babic 	}
112b9bb0531SStefano Babic 	return CLK_CODE_ARM(*pclk_mux);
113b9bb0531SStefano Babic }
114b9bb0531SStefano Babic 
115b9bb0531SStefano Babic static int get_ahb_div(u32 pdr0)
116b9bb0531SStefano Babic {
117b9bb0531SStefano Babic 	int *pclk_mux;
118b9bb0531SStefano Babic 
119b9bb0531SStefano Babic 	pclk_mux = g_clk_mux_consumer +
120b9bb0531SStefano Babic 		((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
121b9bb0531SStefano Babic 		MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
122b9bb0531SStefano Babic 
123b9bb0531SStefano Babic 	if ((*pclk_mux) == -1)
124b9bb0531SStefano Babic 		return -1;
125b9bb0531SStefano Babic 
126b9bb0531SStefano Babic 	return CLK_CODE_AHB(*pclk_mux);
127b9bb0531SStefano Babic }
128b9bb0531SStefano Babic 
129b9bb0531SStefano Babic static u32 decode_pll(u32 reg, u32 infreq)
130b9bb0531SStefano Babic {
131b9bb0531SStefano Babic 	u32 mfi = (reg >> 10) & 0xf;
132b9bb0531SStefano Babic 	u32 mfn = reg & 0x3f;
133b9bb0531SStefano Babic 	u32 mfd = (reg >> 16) & 0x3f;
134b9bb0531SStefano Babic 	u32 pd = (reg >> 26) & 0xf;
135b9bb0531SStefano Babic 
136b9bb0531SStefano Babic 	mfi = mfi <= 5 ? 5 : mfi;
137b9bb0531SStefano Babic 	mfd += 1;
138b9bb0531SStefano Babic 	pd += 1;
139b9bb0531SStefano Babic 
140b9bb0531SStefano Babic 	return ((2 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000;
141b9bb0531SStefano Babic }
142b9bb0531SStefano Babic 
143b9bb0531SStefano Babic static u32 get_mcu_main_clk(void)
144b9bb0531SStefano Babic {
145b9bb0531SStefano Babic 	u32 arm_div = 0, fi = 0, fd = 0;
146b9bb0531SStefano Babic 	struct ccm_regs *ccm =
147b9bb0531SStefano Babic 		(struct ccm_regs *)IMX_CCM_BASE;
148b9bb0531SStefano Babic 	arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd);
149b9bb0531SStefano Babic 	fi *=
150b9bb0531SStefano Babic 		decode_pll(readl(&ccm->mpctl),
151b9bb0531SStefano Babic 			CONFIG_MX35_HCLK_FREQ);
152b9bb0531SStefano Babic 	return fi / (arm_div * fd);
153b9bb0531SStefano Babic }
154b9bb0531SStefano Babic 
155b9bb0531SStefano Babic static u32 get_ipg_clk(void)
156b9bb0531SStefano Babic {
157b9bb0531SStefano Babic 	u32 freq = get_mcu_main_clk();
158b9bb0531SStefano Babic 	struct ccm_regs *ccm =
159b9bb0531SStefano Babic 		(struct ccm_regs *)IMX_CCM_BASE;
160b9bb0531SStefano Babic 	u32 pdr0 = readl(&ccm->pdr0);
161b9bb0531SStefano Babic 
162b9bb0531SStefano Babic 	return freq / (get_ahb_div(pdr0) * 2);
163b9bb0531SStefano Babic }
164b9bb0531SStefano Babic 
165b9bb0531SStefano Babic static u32 get_ipg_per_clk(void)
166b9bb0531SStefano Babic {
167b9bb0531SStefano Babic 	u32 freq = get_mcu_main_clk();
168b9bb0531SStefano Babic 	struct ccm_regs *ccm =
169b9bb0531SStefano Babic 		(struct ccm_regs *)IMX_CCM_BASE;
170b9bb0531SStefano Babic 	u32 pdr0 = readl(&ccm->pdr0);
171b9bb0531SStefano Babic 	u32 pdr4 = readl(&ccm->pdr4);
172b9bb0531SStefano Babic 	u32 div;
173b9bb0531SStefano Babic 	if (pdr0 & MXC_CCM_PDR0_PER_SEL) {
174b9bb0531SStefano Babic 		div = (CCM_GET_DIVIDER(pdr4,
175b9bb0531SStefano Babic 			MXC_CCM_PDR4_PER0_PRDF_MASK,
176b9bb0531SStefano Babic 			MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1) *
177b9bb0531SStefano Babic 			(CCM_GET_DIVIDER(pdr4,
178b9bb0531SStefano Babic 			MXC_CCM_PDR4_PER0_PODF_MASK,
179b9bb0531SStefano Babic 			MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1);
180b9bb0531SStefano Babic 	} else {
181b9bb0531SStefano Babic 		div = CCM_GET_DIVIDER(pdr0,
182b9bb0531SStefano Babic 			MXC_CCM_PDR0_PER_PODF_MASK,
183b9bb0531SStefano Babic 			MXC_CCM_PDR0_PER_PODF_OFFSET) + 1;
184b9bb0531SStefano Babic 		freq /= get_ahb_div(pdr0);
185b9bb0531SStefano Babic 	}
186b9bb0531SStefano Babic 	return freq / div;
187b9bb0531SStefano Babic }
188b9bb0531SStefano Babic 
189b9bb0531SStefano Babic u32 imx_get_uartclk(void)
190b9bb0531SStefano Babic {
191b9bb0531SStefano Babic 	u32 freq;
192b9bb0531SStefano Babic 	struct ccm_regs *ccm =
193b9bb0531SStefano Babic 		(struct ccm_regs *)IMX_CCM_BASE;
194b9bb0531SStefano Babic 	u32 pdr4 = readl(&ccm->pdr4);
195b9bb0531SStefano Babic 
196b9bb0531SStefano Babic 	if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) {
197b9bb0531SStefano Babic 		freq = get_mcu_main_clk();
198b9bb0531SStefano Babic 	} else {
199b9bb0531SStefano Babic 		freq = decode_pll(readl(&ccm->ppctl),
200b9bb0531SStefano Babic 			CONFIG_MX35_HCLK_FREQ);
201b9bb0531SStefano Babic 	}
202b9bb0531SStefano Babic 	freq /= ((CCM_GET_DIVIDER(pdr4,
203b9bb0531SStefano Babic 			MXC_CCM_PDR4_UART_PRDF_MASK,
204b9bb0531SStefano Babic 			MXC_CCM_PDR4_UART_PRDF_OFFSET) + 1) *
205b9bb0531SStefano Babic 		(CCM_GET_DIVIDER(pdr4,
206b9bb0531SStefano Babic 			MXC_CCM_PDR4_UART_PODF_MASK,
207b9bb0531SStefano Babic 			MXC_CCM_PDR4_UART_PODF_OFFSET) + 1));
208b9bb0531SStefano Babic 	return freq;
209b9bb0531SStefano Babic }
210b9bb0531SStefano Babic 
211b9bb0531SStefano Babic unsigned int mxc_get_main_clock(enum mxc_main_clocks clk)
212b9bb0531SStefano Babic {
213b9bb0531SStefano Babic 	u32 nfc_pdf, hsp_podf;
214b9bb0531SStefano Babic 	u32 pll, ret_val = 0, usb_prdf, usb_podf;
215b9bb0531SStefano Babic 	struct ccm_regs *ccm =
216b9bb0531SStefano Babic 		(struct ccm_regs *)IMX_CCM_BASE;
217b9bb0531SStefano Babic 
218b9bb0531SStefano Babic 	u32 reg = readl(&ccm->pdr0);
219b9bb0531SStefano Babic 	u32 reg4 = readl(&ccm->pdr4);
220b9bb0531SStefano Babic 
221b9bb0531SStefano Babic 	reg |= 0x1;
222b9bb0531SStefano Babic 
223b9bb0531SStefano Babic 	switch (clk) {
224b9bb0531SStefano Babic 	case CPU_CLK:
225b9bb0531SStefano Babic 		ret_val = get_mcu_main_clk();
226b9bb0531SStefano Babic 		break;
227b9bb0531SStefano Babic 	case AHB_CLK:
228b9bb0531SStefano Babic 		ret_val = get_mcu_main_clk();
229b9bb0531SStefano Babic 		break;
230b9bb0531SStefano Babic 	case HSP_CLK:
231b9bb0531SStefano Babic 		if (reg & CLKMODE_CONSUMER) {
232b9bb0531SStefano Babic 			hsp_podf = (reg >> 20) & 0x3;
233b9bb0531SStefano Babic 			pll = get_mcu_main_clk();
234b9bb0531SStefano Babic 			hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF];
235b9bb0531SStefano Babic 			if (hsp_podf > 0) {
236b9bb0531SStefano Babic 				ret_val = pll / hsp_podf;
237b9bb0531SStefano Babic 			} else {
238b9bb0531SStefano Babic 				puts("mismatch HSP with ARM clock setting\n");
239b9bb0531SStefano Babic 				ret_val = 0;
240b9bb0531SStefano Babic 			}
241b9bb0531SStefano Babic 		} else {
242b9bb0531SStefano Babic 			ret_val = get_mcu_main_clk();
243b9bb0531SStefano Babic 		}
244b9bb0531SStefano Babic 		break;
245b9bb0531SStefano Babic 	case IPG_CLK:
24677f11a99SFabio Estevam 		ret_val = get_ipg_clk();
247b9bb0531SStefano Babic 		break;
248b9bb0531SStefano Babic 	case IPG_PER_CLK:
249b9bb0531SStefano Babic 		ret_val = get_ipg_per_clk();
250b9bb0531SStefano Babic 		break;
251b9bb0531SStefano Babic 	case NFC_CLK:
252b9bb0531SStefano Babic 		nfc_pdf = (reg4 >> 28) & 0xF;
253b9bb0531SStefano Babic 		pll = get_mcu_main_clk();
254b9bb0531SStefano Babic 		/* AHB/nfc_pdf */
255b9bb0531SStefano Babic 		ret_val = pll / (nfc_pdf + 1);
256b9bb0531SStefano Babic 		break;
257b9bb0531SStefano Babic 	case USB_CLK:
258b9bb0531SStefano Babic 		usb_prdf = (reg4 >> 25) & 0x7;
259b9bb0531SStefano Babic 		usb_podf = (reg4 >> 22) & 0x7;
260b9bb0531SStefano Babic 		if (reg4 & 0x200) {
261b9bb0531SStefano Babic 			pll = get_mcu_main_clk();
262b9bb0531SStefano Babic 		} else {
263b9bb0531SStefano Babic 			pll = decode_pll(readl(&ccm->ppctl),
264b9bb0531SStefano Babic 				CONFIG_MX35_HCLK_FREQ);
265b9bb0531SStefano Babic 		}
266b9bb0531SStefano Babic 
267b9bb0531SStefano Babic 		ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
268b9bb0531SStefano Babic 		break;
269b9bb0531SStefano Babic 	default:
270b9bb0531SStefano Babic 		printf("Unknown clock: %d\n", clk);
271b9bb0531SStefano Babic 		break;
272b9bb0531SStefano Babic 	}
273b9bb0531SStefano Babic 
274b9bb0531SStefano Babic 	return ret_val;
275b9bb0531SStefano Babic }
276b9bb0531SStefano Babic unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk)
277b9bb0531SStefano Babic {
278b9bb0531SStefano Babic 	u32 ret_val = 0, pdf, pre_pdf, clk_sel;
279b9bb0531SStefano Babic 	struct ccm_regs *ccm =
280b9bb0531SStefano Babic 		(struct ccm_regs *)IMX_CCM_BASE;
281b9bb0531SStefano Babic 	u32 mpdr2 = readl(&ccm->pdr2);
282b9bb0531SStefano Babic 	u32 mpdr3 = readl(&ccm->pdr3);
283b9bb0531SStefano Babic 	u32 mpdr4 = readl(&ccm->pdr4);
284b9bb0531SStefano Babic 
285b9bb0531SStefano Babic 	switch (clk) {
286b9bb0531SStefano Babic 	case UART1_BAUD:
287b9bb0531SStefano Babic 	case UART2_BAUD:
288b9bb0531SStefano Babic 	case UART3_BAUD:
289b9bb0531SStefano Babic 		clk_sel = mpdr3 & (1 << 14);
290b9bb0531SStefano Babic 		pre_pdf = (mpdr4 >> 13) & 0x7;
291b9bb0531SStefano Babic 		pdf = (mpdr4 >> 10) & 0x7;
292b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
293b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
294b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
295b9bb0531SStefano Babic 		break;
296b9bb0531SStefano Babic 	case SSI1_BAUD:
297b9bb0531SStefano Babic 		pre_pdf = (mpdr2 >> 24) & 0x7;
298b9bb0531SStefano Babic 		pdf = mpdr2 & 0x3F;
299b9bb0531SStefano Babic 		clk_sel = mpdr2 & (1 << 6);
300b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
301b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
302b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
303b9bb0531SStefano Babic 		break;
304b9bb0531SStefano Babic 	case SSI2_BAUD:
305b9bb0531SStefano Babic 		pre_pdf = (mpdr2 >> 27) & 0x7;
306b9bb0531SStefano Babic 		pdf = (mpdr2 >> 8) & 0x3F;
307b9bb0531SStefano Babic 		clk_sel = mpdr2 & (1 << 6);
308b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
309b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
310b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
311b9bb0531SStefano Babic 		break;
312b9bb0531SStefano Babic 	case CSI_BAUD:
313b9bb0531SStefano Babic 		clk_sel = mpdr2 & (1 << 7);
314b9bb0531SStefano Babic 		pre_pdf = (mpdr2 >> 16) & 0x7;
315b9bb0531SStefano Babic 		pdf = (mpdr2 >> 19) & 0x7;
316b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
317b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
318b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
319b9bb0531SStefano Babic 		break;
320b9bb0531SStefano Babic 	case MSHC_CLK:
321b9bb0531SStefano Babic 		pre_pdf = readl(&ccm->pdr1);
322b9bb0531SStefano Babic 		clk_sel = (pre_pdf & 0x80);
323b9bb0531SStefano Babic 		pdf = (pre_pdf >> 22) & 0x3F;
324b9bb0531SStefano Babic 		pre_pdf = (pre_pdf >> 28) & 0x7;
325b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
326b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
327b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
328b9bb0531SStefano Babic 		break;
329b9bb0531SStefano Babic 	case ESDHC1_CLK:
330b9bb0531SStefano Babic 		clk_sel = mpdr3 & 0x40;
331b9bb0531SStefano Babic 		pre_pdf = mpdr3 & 0x7;
332b9bb0531SStefano Babic 		pdf = (mpdr3>>3) & 0x7;
333b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
334b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
335b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
336b9bb0531SStefano Babic 		break;
337b9bb0531SStefano Babic 	case ESDHC2_CLK:
338b9bb0531SStefano Babic 		clk_sel = mpdr3 & 0x40;
339b9bb0531SStefano Babic 		pre_pdf = (mpdr3 >> 8) & 0x7;
340b9bb0531SStefano Babic 		pdf = (mpdr3 >> 11) & 0x7;
341b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
342b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
343b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
344b9bb0531SStefano Babic 		break;
345b9bb0531SStefano Babic 	case ESDHC3_CLK:
346b9bb0531SStefano Babic 		clk_sel = mpdr3 & 0x40;
347b9bb0531SStefano Babic 		pre_pdf = (mpdr3 >> 16) & 0x7;
348b9bb0531SStefano Babic 		pdf = (mpdr3 >> 19) & 0x7;
349b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
350b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
351b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
352b9bb0531SStefano Babic 		break;
353b9bb0531SStefano Babic 	case SPDIF_CLK:
354b9bb0531SStefano Babic 		clk_sel = mpdr3 & 0x400000;
355b9bb0531SStefano Babic 		pre_pdf = (mpdr3 >> 29) & 0x7;
356b9bb0531SStefano Babic 		pdf = (mpdr3 >> 23) & 0x3F;
357b9bb0531SStefano Babic 		ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
358b9bb0531SStefano Babic 			decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
359b9bb0531SStefano Babic 				((pre_pdf + 1) * (pdf + 1));
360b9bb0531SStefano Babic 		break;
361b9bb0531SStefano Babic 	default:
362b9bb0531SStefano Babic 		printf("%s(): This clock: %d not supported yet\n",
363b9bb0531SStefano Babic 				__func__, clk);
364b9bb0531SStefano Babic 		break;
365b9bb0531SStefano Babic 	}
366b9bb0531SStefano Babic 
367b9bb0531SStefano Babic 	return ret_val;
368b9bb0531SStefano Babic }
369b9bb0531SStefano Babic 
370b9bb0531SStefano Babic unsigned int mxc_get_clock(enum mxc_clock clk)
371b9bb0531SStefano Babic {
372b9bb0531SStefano Babic 	switch (clk) {
373b9bb0531SStefano Babic 	case MXC_ARM_CLK:
374b9bb0531SStefano Babic 		return get_mcu_main_clk();
375b9bb0531SStefano Babic 	case MXC_AHB_CLK:
376b9bb0531SStefano Babic 		break;
377b9bb0531SStefano Babic 	case MXC_IPG_CLK:
378b9bb0531SStefano Babic 		return get_ipg_clk();
379b9bb0531SStefano Babic 	case MXC_IPG_PERCLK:
380b9bb0531SStefano Babic 		return get_ipg_per_clk();
381b9bb0531SStefano Babic 	case MXC_UART_CLK:
382b9bb0531SStefano Babic 		return imx_get_uartclk();
383b9bb0531SStefano Babic 	case MXC_ESDHC_CLK:
384b9bb0531SStefano Babic 		return mxc_get_peri_clock(ESDHC1_CLK);
385b9bb0531SStefano Babic 	case MXC_USB_CLK:
386b9bb0531SStefano Babic 		return mxc_get_main_clock(USB_CLK);
387b9bb0531SStefano Babic 	case MXC_FEC_CLK:
388b9bb0531SStefano Babic 		return get_ipg_clk();
389b9bb0531SStefano Babic 	case MXC_CSPI_CLK:
390b9bb0531SStefano Babic 		return get_ipg_clk();
391b9bb0531SStefano Babic 	}
392b9bb0531SStefano Babic 	return -1;
393b9bb0531SStefano Babic }
394b9bb0531SStefano Babic 
395b9bb0531SStefano Babic #ifdef CONFIG_FEC_MXC
396b9bb0531SStefano Babic /*
397b9bb0531SStefano Babic  * The MX35 has no fuse for MAC, return a NULL MAC
398b9bb0531SStefano Babic  */
399be252b65SFabio Estevam void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
400b9bb0531SStefano Babic {
401b9bb0531SStefano Babic 	memset(mac, 0, 6);
402b9bb0531SStefano Babic }
403b9bb0531SStefano Babic 
404b9bb0531SStefano Babic u32 imx_get_fecclk(void)
405b9bb0531SStefano Babic {
406b9bb0531SStefano Babic 	return mxc_get_clock(MXC_IPG_CLK);
407b9bb0531SStefano Babic }
408b9bb0531SStefano Babic #endif
409b9bb0531SStefano Babic 
410b9bb0531SStefano Babic int do_mx35_showclocks(cmd_tbl_t *cmdtp,
411b9bb0531SStefano Babic 	int flag, int argc, char * const argv[])
412b9bb0531SStefano Babic {
413b9bb0531SStefano Babic 	u32 cpufreq = get_mcu_main_clk();
414b9bb0531SStefano Babic 	printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000);
415b9bb0531SStefano Babic 	printf("ipg clock     : %dHz\n", get_ipg_clk());
416b9bb0531SStefano Babic 	printf("ipg per clock : %dHz\n", get_ipg_per_clk());
417b9bb0531SStefano Babic 	printf("uart clock    : %dHz\n", mxc_get_clock(MXC_UART_CLK));
418b9bb0531SStefano Babic 
419b9bb0531SStefano Babic 	return 0;
420b9bb0531SStefano Babic }
421b9bb0531SStefano Babic 
422b9bb0531SStefano Babic U_BOOT_CMD(
4237acec259SStefano Babic 	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks,
4247acec259SStefano Babic 	"display clocks",
425b9bb0531SStefano Babic 	""
426b9bb0531SStefano Babic );
427b9bb0531SStefano Babic 
428ec0919f5SFabio Estevam #if defined(CONFIG_DISPLAY_CPUINFO)
429d330883fSStefano Babic static char *get_reset_cause(void)
430d330883fSStefano Babic {
431d330883fSStefano Babic 	/* read RCSR register from CCM module */
432d330883fSStefano Babic 	struct ccm_regs *ccm =
433d330883fSStefano Babic 		(struct ccm_regs *)IMX_CCM_BASE;
434d330883fSStefano Babic 
435d330883fSStefano Babic 	u32 cause = readl(&ccm->rcsr) & 0x0F;
436d330883fSStefano Babic 
437d330883fSStefano Babic 	switch (cause) {
438d330883fSStefano Babic 	case 0x0000:
439d330883fSStefano Babic 		return "POR";
440d330883fSStefano Babic 	case 0x0002:
441d330883fSStefano Babic 		return "JTAG";
442d330883fSStefano Babic 	case 0x0004:
443d330883fSStefano Babic 		return "RST";
444d330883fSStefano Babic 	case 0x0008:
445d330883fSStefano Babic 		return "WDOG";
446d330883fSStefano Babic 	default:
447d330883fSStefano Babic 		return "unknown reset";
448d330883fSStefano Babic 	}
449d330883fSStefano Babic }
450d330883fSStefano Babic 
451b9bb0531SStefano Babic int print_cpuinfo(void)
452b9bb0531SStefano Babic {
453d330883fSStefano Babic 	u32 srev = get_cpu_rev();
454d330883fSStefano Babic 
455d330883fSStefano Babic 	printf("CPU:   Freescale i.MX35 rev %d.%d at %d MHz.\n",
456d330883fSStefano Babic 		(srev & 0xF0) >> 4, (srev & 0x0F),
457b9bb0531SStefano Babic 		get_mcu_main_clk() / 1000000);
458d330883fSStefano Babic 
459d330883fSStefano Babic 	printf("Reset cause: %s\n", get_reset_cause());
460d330883fSStefano Babic 
461b9bb0531SStefano Babic 	return 0;
462b9bb0531SStefano Babic }
463b9bb0531SStefano Babic #endif
464b9bb0531SStefano Babic 
465b9bb0531SStefano Babic /*
466b9bb0531SStefano Babic  * Initializes on-chip ethernet controllers.
467b9bb0531SStefano Babic  * to override, implement board_eth_init()
468b9bb0531SStefano Babic  */
469b9bb0531SStefano Babic int cpu_eth_init(bd_t *bis)
470b9bb0531SStefano Babic {
471b9bb0531SStefano Babic 	int rc = -ENODEV;
472b9bb0531SStefano Babic 
473b9bb0531SStefano Babic #if defined(CONFIG_FEC_MXC)
474b9bb0531SStefano Babic 	rc = fecmxc_initialize(bis);
475b9bb0531SStefano Babic #endif
476b9bb0531SStefano Babic 
477b9bb0531SStefano Babic 	return rc;
478b9bb0531SStefano Babic }
479b9bb0531SStefano Babic 
480*09bc3d04SBenoît Thébaudeau #ifdef CONFIG_FSL_ESDHC
481*09bc3d04SBenoît Thébaudeau /*
482*09bc3d04SBenoît Thébaudeau  * Initializes on-chip MMC controllers.
483*09bc3d04SBenoît Thébaudeau  * to override, implement board_mmc_init()
484*09bc3d04SBenoît Thébaudeau  */
485*09bc3d04SBenoît Thébaudeau int cpu_mmc_init(bd_t *bis)
486*09bc3d04SBenoît Thébaudeau {
487*09bc3d04SBenoît Thébaudeau 	return fsl_esdhc_mmc_init(bis);
488*09bc3d04SBenoît Thébaudeau }
489*09bc3d04SBenoît Thébaudeau #endif
490*09bc3d04SBenoît Thébaudeau 
491b9bb0531SStefano Babic int get_clocks(void)
492b9bb0531SStefano Babic {
493b9bb0531SStefano Babic #ifdef CONFIG_FSL_ESDHC
494b9bb0531SStefano Babic 	gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
495b9bb0531SStefano Babic #endif
496b9bb0531SStefano Babic 	return 0;
497b9bb0531SStefano Babic }
498b9bb0531SStefano Babic 
499b9bb0531SStefano Babic void reset_cpu(ulong addr)
500b9bb0531SStefano Babic {
501b9bb0531SStefano Babic 	struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
502b9bb0531SStefano Babic 	writew(4, &wdog->wcr);
503b9bb0531SStefano Babic }
504