xref: /openbmc/u-boot/arch/arm/cpu/arm926ejs/mxs/mxs.c (revision 34a31bf5)
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, int timeout)
85 {
86 	while (--timeout) {
87 		if ((readl(&reg->reg) & mask) == mask)
88 			break;
89 		udelay(1);
90 	}
91 
92 	return !timeout;
93 }
94 
95 int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, int timeout)
96 {
97 	while (--timeout) {
98 		if ((readl(&reg->reg) & mask) == 0)
99 			break;
100 		udelay(1);
101 	}
102 
103 	return !timeout;
104 }
105 
106 int mxs_reset_block(struct mxs_register_32 *reg)
107 {
108 	/* Clear SFTRST */
109 	writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
110 
111 	if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
112 		return 1;
113 
114 	/* Clear CLKGATE */
115 	writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
116 
117 	/* Set SFTRST */
118 	writel(MXS_BLOCK_SFTRST, &reg->reg_set);
119 
120 	/* Wait for CLKGATE being set */
121 	if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
122 		return 1;
123 
124 	/* Clear SFTRST */
125 	writel(MXS_BLOCK_SFTRST, &reg->reg_clr);
126 
127 	if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT))
128 		return 1;
129 
130 	/* Clear CLKGATE */
131 	writel(MXS_BLOCK_CLKGATE, &reg->reg_clr);
132 
133 	if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT))
134 		return 1;
135 
136 	return 0;
137 }
138 
139 void mx28_fixup_vt(uint32_t start_addr)
140 {
141 	uint32_t *vt = (uint32_t *)0x20;
142 	int i;
143 
144 	for (i = 0; i < 8; i++)
145 		vt[i] = start_addr + (4 * i);
146 }
147 
148 #ifdef	CONFIG_ARCH_MISC_INIT
149 int arch_misc_init(void)
150 {
151 	mx28_fixup_vt(gd->relocaddr);
152 	return 0;
153 }
154 #endif
155 
156 int arch_cpu_init(void)
157 {
158 	struct mxs_clkctrl_regs *clkctrl_regs =
159 		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
160 	extern uint32_t _start;
161 
162 	mx28_fixup_vt((uint32_t)&_start);
163 
164 	/*
165 	 * Enable NAND clock
166 	 */
167 	/* Clear bypass bit */
168 	writel(CLKCTRL_CLKSEQ_BYPASS_GPMI,
169 		&clkctrl_regs->hw_clkctrl_clkseq_set);
170 
171 	/* Set GPMI clock to ref_gpmi / 12 */
172 	clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi,
173 		CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1);
174 
175 	udelay(1000);
176 
177 	/*
178 	 * Configure GPIO unit
179 	 */
180 	mxs_gpio_init();
181 
182 #ifdef	CONFIG_APBH_DMA
183 	/* Start APBH DMA */
184 	mxs_dma_init();
185 #endif
186 
187 	return 0;
188 }
189 
190 #if defined(CONFIG_DISPLAY_CPUINFO)
191 static const char *get_cpu_type(void)
192 {
193 	struct mxs_digctl_regs *digctl_regs =
194 		(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
195 
196 	switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
197 	case HW_DIGCTL_CHIPID_MX28:
198 		return "28";
199 	default:
200 		return "??";
201 	}
202 }
203 
204 static const char *get_cpu_rev(void)
205 {
206 	struct mxs_digctl_regs *digctl_regs =
207 		(struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
208 	uint8_t rev = readl(&digctl_regs->hw_digctl_chipid) & 0x000000FF;
209 
210 	switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
211 	case HW_DIGCTL_CHIPID_MX28:
212 		switch (rev) {
213 		case 0x1:
214 			return "1.2";
215 		default:
216 			return "??";
217 		}
218 	default:
219 		return "??";
220 	}
221 }
222 
223 int print_cpuinfo(void)
224 {
225 	struct mxs_spl_data *data = (struct mxs_spl_data *)
226 		((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
227 
228 	printf("CPU:   Freescale i.MX%s rev%s at %d MHz\n",
229 		get_cpu_type(),
230 		get_cpu_rev(),
231 		mxc_get_clock(MXC_ARM_CLK) / 1000000);
232 	printf("BOOT:  %s\n", mxs_boot_modes[data->boot_mode_idx].mode);
233 	return 0;
234 }
235 #endif
236 
237 int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
238 {
239 	printf("CPU:   %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
240 	printf("BUS:   %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000);
241 	printf("EMI:   %3d MHz\n", mxc_get_clock(MXC_EMI_CLK));
242 	printf("GPMI:  %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000);
243 	return 0;
244 }
245 
246 /*
247  * Initializes on-chip ethernet controllers.
248  */
249 #ifdef	CONFIG_CMD_NET
250 int cpu_eth_init(bd_t *bis)
251 {
252 	struct mxs_clkctrl_regs *clkctrl_regs =
253 		(struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
254 
255 	/* Turn on ENET clocks */
256 	clrbits_le32(&clkctrl_regs->hw_clkctrl_enet,
257 		CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE);
258 
259 	/* Set up ENET PLL for 50 MHz */
260 	/* Power on ENET PLL */
261 	writel(CLKCTRL_PLL2CTRL0_POWER,
262 		&clkctrl_regs->hw_clkctrl_pll2ctrl0_set);
263 
264 	udelay(10);
265 
266 	/* Gate on ENET PLL */
267 	writel(CLKCTRL_PLL2CTRL0_CLKGATE,
268 		&clkctrl_regs->hw_clkctrl_pll2ctrl0_clr);
269 
270 	/* Enable pad output */
271 	setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN);
272 
273 	return 0;
274 }
275 #endif
276 
277 static void __mx28_adjust_mac(int dev_id, unsigned char *mac)
278 {
279 	mac[0] = 0x00;
280 	mac[1] = 0x04; /* Use FSL vendor MAC address by default */
281 
282 	if (dev_id == 1) /* Let MAC1 be MAC0 + 1 by default */
283 		mac[5] += 1;
284 }
285 
286 void mx28_adjust_mac(int dev_id, unsigned char *mac)
287 	__attribute__((weak, alias("__mx28_adjust_mac")));
288 
289 #ifdef	CONFIG_MX28_FEC_MAC_IN_OCOTP
290 
291 #define	MXS_OCOTP_MAX_TIMEOUT	1000000
292 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
293 {
294 	struct mxs_ocotp_regs *ocotp_regs =
295 		(struct mxs_ocotp_regs *)MXS_OCOTP_BASE;
296 	uint32_t data;
297 
298 	memset(mac, 0, 6);
299 
300 	writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set);
301 
302 	if (mxs_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY,
303 				MXS_OCOTP_MAX_TIMEOUT)) {
304 		printf("MXS FEC: Can't get MAC from OCOTP\n");
305 		return;
306 	}
307 
308 	data = readl(&ocotp_regs->hw_ocotp_cust0);
309 
310 	mac[2] = (data >> 24) & 0xff;
311 	mac[3] = (data >> 16) & 0xff;
312 	mac[4] = (data >> 8) & 0xff;
313 	mac[5] = data & 0xff;
314 	mx28_adjust_mac(dev_id, mac);
315 }
316 #else
317 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
318 {
319 	memset(mac, 0, 6);
320 }
321 #endif
322 
323 int mx28_dram_init(void)
324 {
325 	struct mxs_spl_data *data = (struct mxs_spl_data *)
326 		((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
327 
328 	if (data->mem_dram_size == 0) {
329 		printf("MX28:\n"
330 			"Error, the RAM size passed up from SPL is 0!\n");
331 		hang();
332 	}
333 
334 	gd->ram_size = data->mem_dram_size;
335 	return 0;
336 }
337 
338 U_BOOT_CMD(
339 	clocks,	CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks,
340 	"display clocks",
341 	""
342 );
343