xref: /openbmc/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs.c (revision 25b26ec6)
1 /*
2  * Freescale i.MX28 common code
3  *
4  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
5  * on behalf of DENX Software Engineering GmbH
6  *
7  * Based on code from LTIB:
8  * Copyright (C) 2010 Freescale Semiconductor, Inc.
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation; either version 2 of
16  * the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26  * MA 02111-1307 USA
27  */
28 
29 #include <common.h>
30 #include <asm/errno.h>
31 #include <asm/io.h>
32 #include <asm/arch/clock.h>
33 #include <asm/arch/dma.h>
34 #include <asm/arch/gpio.h>
35 #include <asm/arch/iomux.h>
36 #include <asm/arch/imx-regs.h>
37 #include <asm/arch/sys_proto.h>
38 
39 DECLARE_GLOBAL_DATA_PTR;
40 
41 /* 1 second delay should be plenty of time for block reset. */
42 #define	RESET_MAX_TIMEOUT	1000000
43 
44 #define	MXS_BLOCK_SFTRST	(1 << 31)
45 #define	MXS_BLOCK_CLKGATE	(1 << 30)
46 
47 /* Lowlevel init isn't used on i.MX28, so just have a dummy here */
48 inline void lowlevel_init(void) {}
49 
50 void reset_cpu(ulong ignored) __attribute__((noreturn));
51 
52 void reset_cpu(ulong ignored)
53 {
54 	struct mxs_rtc_regs *rtc_regs =
55 		(struct mxs_rtc_regs *)MXS_RTC_BASE;
56 	struct mxs_lcdif_regs *lcdif_regs =
57 		(struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
58 
59 	/*
60 	 * Shut down the LCD controller as it interferes with BootROM boot mode
61 	 * pads sampling.
62 	 */
63 	writel(LCDIF_CTRL_RUN, &lcdif_regs->hw_lcdif_ctrl_clr);
64 
65 	/* Wait 1 uS before doing the actual watchdog reset */
66 	writel(1, &rtc_regs->hw_rtc_watchdog);
67 	writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set);
68 
69 	/* Endless loop, reset will exit from here */
70 	for (;;)
71 		;
72 }
73 
74 void enable_caches(void)
75 {
76 #ifndef CONFIG_SYS_ICACHE_OFF
77 	icache_enable();
78 #endif
79 #ifndef CONFIG_SYS_DCACHE_OFF
80 	dcache_enable();
81 #endif
82 }
83 
84 int mxs_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned
85 								int timeout)
86 {
87 	while (--timeout) {
88 		if ((readl(&reg->reg) & mask) == mask)
89 			break;
90 		udelay(1);
91 	}
92 
93 	return !timeout;
94 }
95 
96 int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned
97 								int timeout)
98 {
99 	while (--timeout) {
100 		if ((readl(&reg->reg) & mask) == 0)
101 			break;
102 		udelay(1);
103 	}
104 
105 	return !timeout;
106 }
107 
108 int mxs_reset_block(struct mxs_register_32 *reg)
109 {
110 	/* Clear SFTRST */
111 	writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
112 
113 	if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
114 		return 1;
115 
116 	/* Clear CLKGATE */
117 	writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
118 
119 	/* Set SFTRST */
120 	writel(MXS_BLOCK_SFTRST, &reg->reg_set);
121 
122 	/* Wait for CLKGATE being set */
123 	if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
124 		return 1;
125 
126 	/* Clear SFTRST */
127 	writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
128 
129 	if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
130 		return 1;
131 
132 	/* Clear CLKGATE */
133 	writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
134 
135 	if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
136 		return 1;
137 
138 	return 0;
139 }
140 
141 void mx28_fixup_vt(uint32_t start_addr)
142 {
143 	uint32_t *vt = (uint32_t *)0x20;
144 	int i;
145 
146 	for (i = 0; i < 8; i++)
147 		vt[i] = start_addr + (4 * i);
148 }
149 
150 #ifdef	CONFIG_ARCH_MISC_INIT
151 int arch_misc_init(void)
152 {
153 	mx28_fixup_vt(gd->relocaddr);
154 	return 0;
155 }
156 #endif
157 
158 int arch_cpu_init(void)
159 {
160 	struct mxs_clkctrl_regs *clkctrl_regs =
161 		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
162 	extern uint32_t _start;
163 
164 	mx28_fixup_vt((uint32_t)&_start);
165 
166 	/*
167 	 * Enable NAND clock
168 	 */
169 	/* Clear bypass bit */
170 	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
171 		&clkctrl_regs->hw_clkctrl_clkseq_set);
172 
173 	/* Set GPMI clock to ref_gpmi / 12 */
174 	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
175 		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
176 
177 	udelay(1000);
178 
179 	/*
180 	 * Configure GPIO unit
181 	 */
182 	mxs_gpio_init();
183 
184 #ifdef	CONFIG_APBH_DMA
185 	/* Start APBH DMA */
186 	mxs_dma_init();
187 #endif
188 
189 	return 0;
190 }
191 
192 #if defined(CONFIG_DISPLAY_CPUINFO)
193 static const char *get_cpu_type(void)
194 {
195 	struct mxs_digctl_regs *digctl_regs =
196 		(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
197 
198 	switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
199 	case HW_DIGCTL_CHIPID_MX28:
200 		return "28";
201 	default:
202 		return "??";
203 	}
204 }
205 
206 static const char *get_cpu_rev(void)
207 {
208 	struct mxs_digctl_regs *digctl_regs =
209 		(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
210 	uint8_t rev = readl(&digctl_regs->hw_digctl_chipid) & 0x000000FF;
211 
212 	switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
213 	case HW_DIGCTL_CHIPID_MX28:
214 		switch (rev) {
215 		case 0x1:
216 			return "1.2";
217 		default:
218 			return "??";
219 		}
220 	default:
221 		return "??";
222 	}
223 }
224 
225 int print_cpuinfo(void)
226 {
227 	struct mxs_spl_data *data = (struct mxs_spl_data *)
228 		((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
229 
230 	printf("CPU:   Freescale i.MX%s rev%s at %d MHz\n",
231 		get_cpu_type(),
232 		get_cpu_rev(),
233 		mxc_get_clock(MXC_ARM_CLK) / 1000000);
234 	printf("BOOT:  %s\n", mxs_boot_modes[data->boot_mode_idx].mode);
235 	return 0;
236 }
237 #endif
238 
239 int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
240 {
241 	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
242 	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
243 	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
244 	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
245 	return 0;
246 }
247 
248 /*
249  * Initializes on-chip ethernet controllers.
250  */
251 #if defined(CONFIG_MX28) && defined(CONFIG_CMD_NET)
252 int cpu_eth_init(bd_t *bis)
253 {
254 	struct mxs_clkctrl_regs *clkctrl_regs =
255 		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
256 
257 	/* Turn on ENET clocks */
258 	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
259 		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
260 
261 	/* Set up ENET PLL for 50 MHz */
262 	/* Power on ENET PLL */
263 	writel(CLKCTRL_PLL2CTRL0_POWER,
264 		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
265 
266 	udelay(10);
267 
268 	/* Gate on ENET PLL */
269 	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
270 		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
271 
272 	/* Enable pad output */
273 	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
274 
275 	return 0;
276 }
277 #endif
278 
279 static void __mx28_adjust_mac(int dev_id, unsigned char *mac)
280 {
281 	mac[0] = 0x00;
282 	mac[1] = 0x04; /* Use FSL vendor MAC address by default */
283 
284 	if (dev_id == 1) /* Let MAC1 be MAC0 + 1 by default */
285 		mac[5] += 1;
286 }
287 
288 void mx28_adjust_mac(int dev_id, unsigned char *mac)
289 	__attribute__((weak, alias("__mx28_adjust_mac")));
290 
291 #ifdef	CONFIG_MX28_FEC_MAC_IN_OCOTP
292 
293 #define	MXS_OCOTP_MAX_TIMEOUT	1000000
294 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
295 {
296 	struct mxs_ocotp_regs *ocotp_regs =
297 		(struct mxs_ocotp_regs *)MXS_OCOTP_BASE;
298 	uint32_t data;
299 
300 	memset(mac, 0, 6);
301 
302 	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
303 
304 	if (mxs_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
305 				MXS_OCOTP_MAX_TIMEOUT)) {
306 		printf("MXS FEC: Can't get MAC from OCOTP\n");
307 		return;
308 	}
309 
310 	data = readl(&ocotp_regs->hw_ocotp_cust0);
311 
312 	mac[2] = (data >> 24) & 0xff;
313 	mac[3] = (data >> 16) & 0xff;
314 	mac[4] = (data >> 8) & 0xff;
315 	mac[5] = data & 0xff;
316 	mx28_adjust_mac(dev_id, mac);
317 }
318 #else
319 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
320 {
321 	memset(mac, 0, 6);
322 }
323 #endif
324 
325 int mxs_dram_init(void)
326 {
327 	struct mxs_spl_data *data = (struct mxs_spl_data *)
328 		((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
329 
330 	if (data->mem_dram_size == 0) {
331 		printf("MXS:\n"
332 			"Error, the RAM size passed up from SPL is 0!\n");
333 		hang();
334 	}
335 
336 	gd->ram_size = data->mem_dram_size;
337 	return 0;
338 }
339 
340 U_BOOT_CMD(
341 	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
342 	"display clocks",
343 	""
344 );
345