1 /*
2  * Copyright (C) 2012 Freescale Semiconductor, Inc.
3  *
4  * Author: Fabio Estevam <fabio.estevam@freescale.com>
5  *
6  * SPDX-License-Identifier:	GPL-2.0+
7  */
8 
9 #include <asm/arch/clock.h>
10 #include <asm/arch/imx-regs.h>
11 #include <asm/arch/iomux.h>
12 #include <asm/arch/mx6-pins.h>
13 #include <linux/errno.h>
14 #include <asm/gpio.h>
15 #include <asm/imx-common/mxc_i2c.h>
16 #include <asm/imx-common/iomux-v3.h>
17 #include <asm/imx-common/boot_mode.h>
18 #include <asm/imx-common/video.h>
19 #include <mmc.h>
20 #include <fsl_esdhc.h>
21 #include <miiphy.h>
22 #include <netdev.h>
23 #include <asm/arch/mxc_hdmi.h>
24 #include <asm/arch/crm_regs.h>
25 #include <asm/io.h>
26 #include <asm/arch/sys_proto.h>
27 #include <i2c.h>
28 #include <power/pmic.h>
29 #include <power/pfuze100_pmic.h>
30 #include "../common/pfuze.h"
31 #include <asm/arch/mx6-ddr.h>
32 #include <usb.h>
33 
34 DECLARE_GLOBAL_DATA_PTR;
35 
36 #define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
37 	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |			\
38 	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
39 
40 #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |			\
41 	PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |			\
42 	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
43 
44 #define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
45 	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
46 
47 #define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
48 		      PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
49 
50 #define I2C_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
51 	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS |	\
52 	PAD_CTL_ODE | PAD_CTL_SRE_FAST)
53 
54 #define I2C_PMIC	1
55 
56 #define I2C_PAD MUX_PAD_CTRL(I2C_PAD_CTRL)
57 
58 #define DISP0_PWR_EN	IMX_GPIO_NR(1, 21)
59 
60 #define KEY_VOL_UP	IMX_GPIO_NR(1, 4)
61 
62 int dram_init(void)
63 {
64 	gd->ram_size = imx_ddr_size();
65 	return 0;
66 }
67 
68 static iomux_v3_cfg_t const uart1_pads[] = {
69 	MX6_PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
70 	MX6_PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
71 };
72 
73 static iomux_v3_cfg_t const enet_pads[] = {
74 	MX6_PAD_ENET_MDIO__ENET_MDIO		| MUX_PAD_CTRL(ENET_PAD_CTRL),
75 	MX6_PAD_ENET_MDC__ENET_MDC		| MUX_PAD_CTRL(ENET_PAD_CTRL),
76 	MX6_PAD_RGMII_TXC__RGMII_TXC	| MUX_PAD_CTRL(ENET_PAD_CTRL),
77 	MX6_PAD_RGMII_TD0__RGMII_TD0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
78 	MX6_PAD_RGMII_TD1__RGMII_TD1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
79 	MX6_PAD_RGMII_TD2__RGMII_TD2	| MUX_PAD_CTRL(ENET_PAD_CTRL),
80 	MX6_PAD_RGMII_TD3__RGMII_TD3	| MUX_PAD_CTRL(ENET_PAD_CTRL),
81 	MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
82 	MX6_PAD_ENET_REF_CLK__ENET_TX_CLK	| MUX_PAD_CTRL(ENET_PAD_CTRL),
83 	MX6_PAD_RGMII_RXC__RGMII_RXC	| MUX_PAD_CTRL(ENET_PAD_CTRL),
84 	MX6_PAD_RGMII_RD0__RGMII_RD0	| MUX_PAD_CTRL(ENET_PAD_CTRL),
85 	MX6_PAD_RGMII_RD1__RGMII_RD1	| MUX_PAD_CTRL(ENET_PAD_CTRL),
86 	MX6_PAD_RGMII_RD2__RGMII_RD2	| MUX_PAD_CTRL(ENET_PAD_CTRL),
87 	MX6_PAD_RGMII_RD3__RGMII_RD3	| MUX_PAD_CTRL(ENET_PAD_CTRL),
88 	MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL	| MUX_PAD_CTRL(ENET_PAD_CTRL),
89 	/* AR8031 PHY Reset */
90 	MX6_PAD_ENET_CRS_DV__GPIO1_IO25		| MUX_PAD_CTRL(NO_PAD_CTRL),
91 };
92 
93 static void setup_iomux_enet(void)
94 {
95 	imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
96 
97 	/* Reset AR8031 PHY */
98 	gpio_direction_output(IMX_GPIO_NR(1, 25) , 0);
99 	mdelay(10);
100 	gpio_set_value(IMX_GPIO_NR(1, 25), 1);
101 	udelay(100);
102 }
103 
104 static iomux_v3_cfg_t const usdhc2_pads[] = {
105 	MX6_PAD_SD2_CLK__SD2_CLK	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
106 	MX6_PAD_SD2_CMD__SD2_CMD	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
107 	MX6_PAD_SD2_DAT0__SD2_DATA0	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
108 	MX6_PAD_SD2_DAT1__SD2_DATA1	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
109 	MX6_PAD_SD2_DAT2__SD2_DATA2	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
110 	MX6_PAD_SD2_DAT3__SD2_DATA3	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
111 	MX6_PAD_NANDF_D4__SD2_DATA4	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
112 	MX6_PAD_NANDF_D5__SD2_DATA5	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
113 	MX6_PAD_NANDF_D6__SD2_DATA6	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
114 	MX6_PAD_NANDF_D7__SD2_DATA7	| MUX_PAD_CTRL(USDHC_PAD_CTRL),
115 	MX6_PAD_NANDF_D2__GPIO2_IO02	| MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
116 };
117 
118 static iomux_v3_cfg_t const usdhc3_pads[] = {
119 	MX6_PAD_SD3_CLK__SD3_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
120 	MX6_PAD_SD3_CMD__SD3_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
121 	MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
122 	MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
123 	MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
124 	MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
125 	MX6_PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
126 	MX6_PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
127 	MX6_PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
128 	MX6_PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
129 	MX6_PAD_NANDF_D0__GPIO2_IO00    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
130 };
131 
132 static iomux_v3_cfg_t const usdhc4_pads[] = {
133 	MX6_PAD_SD4_CLK__SD4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
134 	MX6_PAD_SD4_CMD__SD4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
135 	MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
136 	MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
137 	MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
138 	MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
139 	MX6_PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
140 	MX6_PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
141 	MX6_PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
142 	MX6_PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
143 };
144 
145 static iomux_v3_cfg_t const ecspi1_pads[] = {
146 	MX6_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
147 	MX6_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
148 	MX6_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
149 	MX6_PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
150 };
151 
152 static iomux_v3_cfg_t const rgb_pads[] = {
153 	MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL),
154 	MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL),
155 	MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02 | MUX_PAD_CTRL(NO_PAD_CTRL),
156 	MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03 | MUX_PAD_CTRL(NO_PAD_CTRL),
157 	MX6_PAD_DI0_PIN4__IPU1_DI0_PIN04 | MUX_PAD_CTRL(NO_PAD_CTRL),
158 	MX6_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 | MUX_PAD_CTRL(NO_PAD_CTRL),
159 	MX6_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 | MUX_PAD_CTRL(NO_PAD_CTRL),
160 	MX6_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 | MUX_PAD_CTRL(NO_PAD_CTRL),
161 	MX6_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 | MUX_PAD_CTRL(NO_PAD_CTRL),
162 	MX6_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 | MUX_PAD_CTRL(NO_PAD_CTRL),
163 	MX6_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 | MUX_PAD_CTRL(NO_PAD_CTRL),
164 	MX6_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 | MUX_PAD_CTRL(NO_PAD_CTRL),
165 	MX6_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 | MUX_PAD_CTRL(NO_PAD_CTRL),
166 	MX6_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 | MUX_PAD_CTRL(NO_PAD_CTRL),
167 	MX6_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 | MUX_PAD_CTRL(NO_PAD_CTRL),
168 	MX6_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 | MUX_PAD_CTRL(NO_PAD_CTRL),
169 	MX6_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 | MUX_PAD_CTRL(NO_PAD_CTRL),
170 	MX6_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 | MUX_PAD_CTRL(NO_PAD_CTRL),
171 	MX6_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 | MUX_PAD_CTRL(NO_PAD_CTRL),
172 	MX6_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 | MUX_PAD_CTRL(NO_PAD_CTRL),
173 	MX6_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 | MUX_PAD_CTRL(NO_PAD_CTRL),
174 	MX6_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 | MUX_PAD_CTRL(NO_PAD_CTRL),
175 	MX6_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 | MUX_PAD_CTRL(NO_PAD_CTRL),
176 	MX6_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 | MUX_PAD_CTRL(NO_PAD_CTRL),
177 	MX6_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 | MUX_PAD_CTRL(NO_PAD_CTRL),
178 	MX6_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 | MUX_PAD_CTRL(NO_PAD_CTRL),
179 	MX6_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 | MUX_PAD_CTRL(NO_PAD_CTRL),
180 	MX6_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 | MUX_PAD_CTRL(NO_PAD_CTRL),
181 	MX6_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 | MUX_PAD_CTRL(NO_PAD_CTRL),
182 };
183 
184 static iomux_v3_cfg_t const bl_pads[] = {
185 	MX6_PAD_SD1_DAT3__GPIO1_IO21 | MUX_PAD_CTRL(NO_PAD_CTRL),
186 };
187 
188 static void enable_backlight(void)
189 {
190 	imx_iomux_v3_setup_multiple_pads(bl_pads, ARRAY_SIZE(bl_pads));
191 	gpio_direction_output(DISP0_PWR_EN, 1);
192 }
193 
194 static void enable_rgb(struct display_info_t const *dev)
195 {
196 	imx_iomux_v3_setup_multiple_pads(rgb_pads, ARRAY_SIZE(rgb_pads));
197 	enable_backlight();
198 }
199 
200 static void enable_lvds(struct display_info_t const *dev)
201 {
202 	enable_backlight();
203 }
204 
205 static struct i2c_pads_info i2c_pad_info1 = {
206 	.scl = {
207 		.i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | I2C_PAD,
208 		.gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12 | I2C_PAD,
209 		.gp = IMX_GPIO_NR(4, 12)
210 	},
211 	.sda = {
212 		.i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | I2C_PAD,
213 		.gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | I2C_PAD,
214 		.gp = IMX_GPIO_NR(4, 13)
215 	}
216 };
217 
218 static void setup_spi(void)
219 {
220 	imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
221 }
222 
223 iomux_v3_cfg_t const pcie_pads[] = {
224 	MX6_PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),	/* POWER */
225 	MX6_PAD_GPIO_17__GPIO7_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),	/* RESET */
226 };
227 
228 static void setup_pcie(void)
229 {
230 	imx_iomux_v3_setup_multiple_pads(pcie_pads, ARRAY_SIZE(pcie_pads));
231 }
232 
233 iomux_v3_cfg_t const di0_pads[] = {
234 	MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,	/* DISP0_CLK */
235 	MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02,		/* DISP0_HSYNC */
236 	MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03,		/* DISP0_VSYNC */
237 };
238 
239 static void setup_iomux_uart(void)
240 {
241 	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
242 }
243 
244 #ifdef CONFIG_FSL_ESDHC
245 struct fsl_esdhc_cfg usdhc_cfg[3] = {
246 	{USDHC2_BASE_ADDR},
247 	{USDHC3_BASE_ADDR},
248 	{USDHC4_BASE_ADDR},
249 };
250 
251 #define USDHC2_CD_GPIO	IMX_GPIO_NR(2, 2)
252 #define USDHC3_CD_GPIO	IMX_GPIO_NR(2, 0)
253 
254 int board_mmc_get_env_dev(int devno)
255 {
256 	return devno - 1;
257 }
258 
259 int board_mmc_getcd(struct mmc *mmc)
260 {
261 	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
262 	int ret = 0;
263 
264 	switch (cfg->esdhc_base) {
265 	case USDHC2_BASE_ADDR:
266 		ret = !gpio_get_value(USDHC2_CD_GPIO);
267 		break;
268 	case USDHC3_BASE_ADDR:
269 		ret = !gpio_get_value(USDHC3_CD_GPIO);
270 		break;
271 	case USDHC4_BASE_ADDR:
272 		ret = 1; /* eMMC/uSDHC4 is always present */
273 		break;
274 	}
275 
276 	return ret;
277 }
278 
279 int board_mmc_init(bd_t *bis)
280 {
281 #ifndef CONFIG_SPL_BUILD
282 	int ret;
283 	int i;
284 
285 	/*
286 	 * According to the board_mmc_init() the following map is done:
287 	 * (U-Boot device node)    (Physical Port)
288 	 * mmc0                    SD2
289 	 * mmc1                    SD3
290 	 * mmc2                    eMMC
291 	 */
292 	for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
293 		switch (i) {
294 		case 0:
295 			imx_iomux_v3_setup_multiple_pads(
296 				usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
297 			gpio_direction_input(USDHC2_CD_GPIO);
298 			usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
299 			break;
300 		case 1:
301 			imx_iomux_v3_setup_multiple_pads(
302 				usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
303 			gpio_direction_input(USDHC3_CD_GPIO);
304 			usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
305 			break;
306 		case 2:
307 			imx_iomux_v3_setup_multiple_pads(
308 				usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
309 			usdhc_cfg[2].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
310 			break;
311 		default:
312 			printf("Warning: you configured more USDHC controllers"
313 			       "(%d) then supported by the board (%d)\n",
314 			       i + 1, CONFIG_SYS_FSL_USDHC_NUM);
315 			return -EINVAL;
316 		}
317 
318 		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
319 		if (ret)
320 			return ret;
321 	}
322 
323 	return 0;
324 #else
325 	struct src *psrc = (struct src *)SRC_BASE_ADDR;
326 	unsigned reg = readl(&psrc->sbmr1) >> 11;
327 	/*
328 	 * Upon reading BOOT_CFG register the following map is done:
329 	 * Bit 11 and 12 of BOOT_CFG register can determine the current
330 	 * mmc port
331 	 * 0x1                  SD1
332 	 * 0x2                  SD2
333 	 * 0x3                  SD4
334 	 */
335 
336 	switch (reg & 0x3) {
337 	case 0x1:
338 		imx_iomux_v3_setup_multiple_pads(
339 			usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
340 		usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR;
341 		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
342 		gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
343 		break;
344 	case 0x2:
345 		imx_iomux_v3_setup_multiple_pads(
346 			usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
347 		usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR;
348 		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
349 		gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
350 		break;
351 	case 0x3:
352 		imx_iomux_v3_setup_multiple_pads(
353 			usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
354 		usdhc_cfg[0].esdhc_base = USDHC4_BASE_ADDR;
355 		usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
356 		gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
357 		break;
358 	}
359 
360 	return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
361 #endif
362 }
363 #endif
364 
365 static int ar8031_phy_fixup(struct phy_device *phydev)
366 {
367 	unsigned short val;
368 
369 	/* To enable AR8031 ouput a 125MHz clk from CLK_25M */
370 	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
371 	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
372 	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
373 
374 	val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
375 	val &= 0xffe3;
376 	val |= 0x18;
377 	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
378 
379 	/* introduce tx clock delay */
380 	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
381 	val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
382 	val |= 0x0100;
383 	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
384 
385 	return 0;
386 }
387 
388 int board_phy_config(struct phy_device *phydev)
389 {
390 	ar8031_phy_fixup(phydev);
391 
392 	if (phydev->drv->config)
393 		phydev->drv->config(phydev);
394 
395 	return 0;
396 }
397 
398 #if defined(CONFIG_VIDEO_IPUV3)
399 static void disable_lvds(struct display_info_t const *dev)
400 {
401 	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
402 
403 	int reg = readl(&iomux->gpr[2]);
404 
405 	reg &= ~(IOMUXC_GPR2_LVDS_CH0_MODE_MASK |
406 		 IOMUXC_GPR2_LVDS_CH1_MODE_MASK);
407 
408 	writel(reg, &iomux->gpr[2]);
409 }
410 
411 static void do_enable_hdmi(struct display_info_t const *dev)
412 {
413 	disable_lvds(dev);
414 	imx_enable_hdmi_phy();
415 }
416 
417 struct display_info_t const displays[] = {{
418 	.bus	= -1,
419 	.addr	= 0,
420 	.pixfmt	= IPU_PIX_FMT_RGB666,
421 	.detect	= NULL,
422 	.enable	= enable_lvds,
423 	.mode	= {
424 		.name           = "Hannstar-XGA",
425 		.refresh        = 60,
426 		.xres           = 1024,
427 		.yres           = 768,
428 		.pixclock       = 15384,
429 		.left_margin    = 160,
430 		.right_margin   = 24,
431 		.upper_margin   = 29,
432 		.lower_margin   = 3,
433 		.hsync_len      = 136,
434 		.vsync_len      = 6,
435 		.sync           = FB_SYNC_EXT,
436 		.vmode          = FB_VMODE_NONINTERLACED
437 } }, {
438 	.bus	= -1,
439 	.addr	= 0,
440 	.pixfmt	= IPU_PIX_FMT_RGB24,
441 	.detect	= detect_hdmi,
442 	.enable	= do_enable_hdmi,
443 	.mode	= {
444 		.name           = "HDMI",
445 		.refresh        = 60,
446 		.xres           = 1024,
447 		.yres           = 768,
448 		.pixclock       = 15384,
449 		.left_margin    = 160,
450 		.right_margin   = 24,
451 		.upper_margin   = 29,
452 		.lower_margin   = 3,
453 		.hsync_len      = 136,
454 		.vsync_len      = 6,
455 		.sync           = FB_SYNC_EXT,
456 		.vmode          = FB_VMODE_NONINTERLACED
457 } }, {
458 	.bus	= 0,
459 	.addr	= 0,
460 	.pixfmt	= IPU_PIX_FMT_RGB24,
461 	.detect	= NULL,
462 	.enable	= enable_rgb,
463 	.mode	= {
464 		.name           = "SEIKO-WVGA",
465 		.refresh        = 60,
466 		.xres           = 800,
467 		.yres           = 480,
468 		.pixclock       = 29850,
469 		.left_margin    = 89,
470 		.right_margin   = 164,
471 		.upper_margin   = 23,
472 		.lower_margin   = 10,
473 		.hsync_len      = 10,
474 		.vsync_len      = 10,
475 		.sync           = 0,
476 		.vmode          = FB_VMODE_NONINTERLACED
477 } } };
478 size_t display_count = ARRAY_SIZE(displays);
479 
480 static void setup_display(void)
481 {
482 	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
483 	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
484 	int reg;
485 
486 	/* Setup HSYNC, VSYNC, DISP_CLK for debugging purposes */
487 	imx_iomux_v3_setup_multiple_pads(di0_pads, ARRAY_SIZE(di0_pads));
488 
489 	enable_ipu_clock();
490 	imx_setup_hdmi();
491 
492 	/* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */
493 	reg = readl(&mxc_ccm->CCGR3);
494 	reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK;
495 	writel(reg, &mxc_ccm->CCGR3);
496 
497 	/* set LDB0, LDB1 clk select to 011/011 */
498 	reg = readl(&mxc_ccm->cs2cdr);
499 	reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
500 		 | MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
501 	reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
502 	      | (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
503 	writel(reg, &mxc_ccm->cs2cdr);
504 
505 	reg = readl(&mxc_ccm->cscmr2);
506 	reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
507 	writel(reg, &mxc_ccm->cscmr2);
508 
509 	reg = readl(&mxc_ccm->chsccdr);
510 	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
511 		<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
512 	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
513 		<< MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET);
514 	writel(reg, &mxc_ccm->chsccdr);
515 
516 	reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
517 	     | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW
518 	     | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
519 	     | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
520 	     | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
521 	     | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
522 	     | IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
523 	     | IOMUXC_GPR2_LVDS_CH0_MODE_DISABLED
524 	     | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0;
525 	writel(reg, &iomux->gpr[2]);
526 
527 	reg = readl(&iomux->gpr[3]);
528 	reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK
529 			| IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
530 	    | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
531 	       << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
532 	writel(reg, &iomux->gpr[3]);
533 }
534 #endif /* CONFIG_VIDEO_IPUV3 */
535 
536 /*
537  * Do not overwrite the console
538  * Use always serial for U-Boot console
539  */
540 int overwrite_console(void)
541 {
542 	return 1;
543 }
544 
545 int board_eth_init(bd_t *bis)
546 {
547 	setup_iomux_enet();
548 	setup_pcie();
549 
550 	return cpu_eth_init(bis);
551 }
552 
553 #ifdef CONFIG_USB_EHCI_MX6
554 #define USB_OTHERREGS_OFFSET	0x800
555 #define UCTRL_PWR_POL		(1 << 9)
556 
557 static iomux_v3_cfg_t const usb_otg_pads[] = {
558 	MX6_PAD_EIM_D22__USB_OTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
559 	MX6_PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
560 };
561 
562 static iomux_v3_cfg_t const usb_hc1_pads[] = {
563 	MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
564 };
565 
566 static void setup_usb(void)
567 {
568 	imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
569 					 ARRAY_SIZE(usb_otg_pads));
570 
571 	/*
572 	 * set daisy chain for otg_pin_id on 6q.
573 	 * for 6dl, this bit is reserved
574 	 */
575 	imx_iomux_set_gpr_register(1, 13, 1, 0);
576 
577 	imx_iomux_v3_setup_multiple_pads(usb_hc1_pads,
578 					 ARRAY_SIZE(usb_hc1_pads));
579 }
580 
581 int board_ehci_hcd_init(int port)
582 {
583 	u32 *usbnc_usb_ctrl;
584 
585 	if (port > 1)
586 		return -EINVAL;
587 
588 	usbnc_usb_ctrl = (u32 *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET +
589 				 port * 4);
590 
591 	setbits_le32(usbnc_usb_ctrl, UCTRL_PWR_POL);
592 
593 	return 0;
594 }
595 
596 int board_ehci_power(int port, int on)
597 {
598 	switch (port) {
599 	case 0:
600 		break;
601 	case 1:
602 		if (on)
603 			gpio_direction_output(IMX_GPIO_NR(1, 29), 1);
604 		else
605 			gpio_direction_output(IMX_GPIO_NR(1, 29), 0);
606 		break;
607 	default:
608 		printf("MXC USB port %d not yet supported\n", port);
609 		return -EINVAL;
610 	}
611 
612 	return 0;
613 }
614 #endif
615 
616 int board_early_init_f(void)
617 {
618 	setup_iomux_uart();
619 #if defined(CONFIG_VIDEO_IPUV3)
620 	setup_display();
621 #endif
622 
623 	return 0;
624 }
625 
626 int board_init(void)
627 {
628 	/* address of boot parameters */
629 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
630 
631 #ifdef CONFIG_MXC_SPI
632 	setup_spi();
633 #endif
634 	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
635 
636 #ifdef CONFIG_USB_EHCI_MX6
637 	setup_usb();
638 #endif
639 
640 	return 0;
641 }
642 
643 int power_init_board(void)
644 {
645 	struct pmic *p;
646 	unsigned int reg;
647 	int ret;
648 
649 	p = pfuze_common_init(I2C_PMIC);
650 	if (!p)
651 		return -ENODEV;
652 
653 	ret = pfuze_mode_init(p, APS_PFM);
654 	if (ret < 0)
655 		return ret;
656 
657 	/* Increase VGEN3 from 2.5 to 2.8V */
658 	pmic_reg_read(p, PFUZE100_VGEN3VOL, &reg);
659 	reg &= ~LDO_VOL_MASK;
660 	reg |= LDOB_2_80V;
661 	pmic_reg_write(p, PFUZE100_VGEN3VOL, reg);
662 
663 	/* Increase VGEN5 from 2.8 to 3V */
664 	pmic_reg_read(p, PFUZE100_VGEN5VOL, &reg);
665 	reg &= ~LDO_VOL_MASK;
666 	reg |= LDOB_3_00V;
667 	pmic_reg_write(p, PFUZE100_VGEN5VOL, reg);
668 
669 	return 0;
670 }
671 
672 #ifdef CONFIG_MXC_SPI
673 int board_spi_cs_gpio(unsigned bus, unsigned cs)
674 {
675 	return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(4, 9)) : -1;
676 }
677 #endif
678 
679 #ifdef CONFIG_CMD_BMODE
680 static const struct boot_mode board_boot_modes[] = {
681 	/* 4 bit bus width */
682 	{"sd2",	 MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
683 	{"sd3",	 MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
684 	/* 8 bit bus width */
685 	{"emmc", MAKE_CFGVAL(0x60, 0x58, 0x00, 0x00)},
686 	{NULL,	 0},
687 };
688 #endif
689 
690 int board_late_init(void)
691 {
692 #ifdef CONFIG_CMD_BMODE
693 	add_board_boot_modes(board_boot_modes);
694 #endif
695 
696 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
697 	setenv("board_name", "SABRESD");
698 
699 	if (is_mx6dqp())
700 		setenv("board_rev", "MX6QP");
701 	else if (is_mx6dq())
702 		setenv("board_rev", "MX6Q");
703 	else if (is_mx6sdl())
704 		setenv("board_rev", "MX6DL");
705 #endif
706 
707 	return 0;
708 }
709 
710 int checkboard(void)
711 {
712 	puts("Board: MX6-SabreSD\n");
713 	return 0;
714 }
715 
716 #ifdef CONFIG_SPL_BUILD
717 #include <spl.h>
718 #include <libfdt.h>
719 
720 #ifdef CONFIG_SPL_OS_BOOT
721 int spl_start_uboot(void)
722 {
723 	gpio_direction_input(KEY_VOL_UP);
724 
725 	/* Only enter in Falcon mode if KEY_VOL_UP is pressed */
726 	return gpio_get_value(KEY_VOL_UP);
727 }
728 #endif
729 
730 static void ccgr_init(void)
731 {
732 	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
733 
734 	writel(0x00C03F3F, &ccm->CCGR0);
735 	writel(0x0030FC03, &ccm->CCGR1);
736 	writel(0x0FFFC000, &ccm->CCGR2);
737 	writel(0x3FF00000, &ccm->CCGR3);
738 	writel(0x00FFF300, &ccm->CCGR4);
739 	writel(0x0F0000C3, &ccm->CCGR5);
740 	writel(0x000003FF, &ccm->CCGR6);
741 }
742 
743 static void gpr_init(void)
744 {
745 	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
746 
747 	/* enable AXI cache for VDOA/VPU/IPU */
748 	writel(0xF00000CF, &iomux->gpr[4]);
749 	if (is_mx6dqp()) {
750 		/* set IPU AXI-id1 Qos=0x1 AXI-id0/2/3 Qos=0x7 */
751 		writel(0x007F007F, &iomux->gpr[6]);
752 		writel(0x007F007F, &iomux->gpr[7]);
753 	} else {
754 		/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
755 		writel(0x007F007F, &iomux->gpr[6]);
756 		writel(0x007F007F, &iomux->gpr[7]);
757 	}
758 }
759 
760 static int mx6q_dcd_table[] = {
761 	0x020e0798, 0x000C0000,
762 	0x020e0758, 0x00000000,
763 	0x020e0588, 0x00000030,
764 	0x020e0594, 0x00000030,
765 	0x020e056c, 0x00000030,
766 	0x020e0578, 0x00000030,
767 	0x020e074c, 0x00000030,
768 	0x020e057c, 0x00000030,
769 	0x020e058c, 0x00000000,
770 	0x020e059c, 0x00000030,
771 	0x020e05a0, 0x00000030,
772 	0x020e078c, 0x00000030,
773 	0x020e0750, 0x00020000,
774 	0x020e05a8, 0x00000030,
775 	0x020e05b0, 0x00000030,
776 	0x020e0524, 0x00000030,
777 	0x020e051c, 0x00000030,
778 	0x020e0518, 0x00000030,
779 	0x020e050c, 0x00000030,
780 	0x020e05b8, 0x00000030,
781 	0x020e05c0, 0x00000030,
782 	0x020e0774, 0x00020000,
783 	0x020e0784, 0x00000030,
784 	0x020e0788, 0x00000030,
785 	0x020e0794, 0x00000030,
786 	0x020e079c, 0x00000030,
787 	0x020e07a0, 0x00000030,
788 	0x020e07a4, 0x00000030,
789 	0x020e07a8, 0x00000030,
790 	0x020e0748, 0x00000030,
791 	0x020e05ac, 0x00000030,
792 	0x020e05b4, 0x00000030,
793 	0x020e0528, 0x00000030,
794 	0x020e0520, 0x00000030,
795 	0x020e0514, 0x00000030,
796 	0x020e0510, 0x00000030,
797 	0x020e05bc, 0x00000030,
798 	0x020e05c4, 0x00000030,
799 	0x021b0800, 0xa1390003,
800 	0x021b080c, 0x001F001F,
801 	0x021b0810, 0x001F001F,
802 	0x021b480c, 0x001F001F,
803 	0x021b4810, 0x001F001F,
804 	0x021b083c, 0x43270338,
805 	0x021b0840, 0x03200314,
806 	0x021b483c, 0x431A032F,
807 	0x021b4840, 0x03200263,
808 	0x021b0848, 0x4B434748,
809 	0x021b4848, 0x4445404C,
810 	0x021b0850, 0x38444542,
811 	0x021b4850, 0x4935493A,
812 	0x021b081c, 0x33333333,
813 	0x021b0820, 0x33333333,
814 	0x021b0824, 0x33333333,
815 	0x021b0828, 0x33333333,
816 	0x021b481c, 0x33333333,
817 	0x021b4820, 0x33333333,
818 	0x021b4824, 0x33333333,
819 	0x021b4828, 0x33333333,
820 	0x021b08b8, 0x00000800,
821 	0x021b48b8, 0x00000800,
822 	0x021b0004, 0x00020036,
823 	0x021b0008, 0x09444040,
824 	0x021b000c, 0x555A7975,
825 	0x021b0010, 0xFF538F64,
826 	0x021b0014, 0x01FF00DB,
827 	0x021b0018, 0x00001740,
828 	0x021b001c, 0x00008000,
829 	0x021b002c, 0x000026d2,
830 	0x021b0030, 0x005A1023,
831 	0x021b0040, 0x00000027,
832 	0x021b0000, 0x831A0000,
833 	0x021b001c, 0x04088032,
834 	0x021b001c, 0x00008033,
835 	0x021b001c, 0x00048031,
836 	0x021b001c, 0x09408030,
837 	0x021b001c, 0x04008040,
838 	0x021b0020, 0x00005800,
839 	0x021b0818, 0x00011117,
840 	0x021b4818, 0x00011117,
841 	0x021b0004, 0x00025576,
842 	0x021b0404, 0x00011006,
843 	0x021b001c, 0x00000000,
844 };
845 
846 static int mx6qp_dcd_table[] = {
847 	0x020e0798, 0x000c0000,
848 	0x020e0758, 0x00000000,
849 	0x020e0588, 0x00000030,
850 	0x020e0594, 0x00000030,
851 	0x020e056c, 0x00000030,
852 	0x020e0578, 0x00000030,
853 	0x020e074c, 0x00000030,
854 	0x020e057c, 0x00000030,
855 	0x020e058c, 0x00000000,
856 	0x020e059c, 0x00000030,
857 	0x020e05a0, 0x00000030,
858 	0x020e078c, 0x00000030,
859 	0x020e0750, 0x00020000,
860 	0x020e05a8, 0x00000030,
861 	0x020e05b0, 0x00000030,
862 	0x020e0524, 0x00000030,
863 	0x020e051c, 0x00000030,
864 	0x020e0518, 0x00000030,
865 	0x020e050c, 0x00000030,
866 	0x020e05b8, 0x00000030,
867 	0x020e05c0, 0x00000030,
868 	0x020e0774, 0x00020000,
869 	0x020e0784, 0x00000030,
870 	0x020e0788, 0x00000030,
871 	0x020e0794, 0x00000030,
872 	0x020e079c, 0x00000030,
873 	0x020e07a0, 0x00000030,
874 	0x020e07a4, 0x00000030,
875 	0x020e07a8, 0x00000030,
876 	0x020e0748, 0x00000030,
877 	0x020e05ac, 0x00000030,
878 	0x020e05b4, 0x00000030,
879 	0x020e0528, 0x00000030,
880 	0x020e0520, 0x00000030,
881 	0x020e0514, 0x00000030,
882 	0x020e0510, 0x00000030,
883 	0x020e05bc, 0x00000030,
884 	0x020e05c4, 0x00000030,
885 	0x021b0800, 0xa1390003,
886 	0x021b080c, 0x001b001e,
887 	0x021b0810, 0x002e0029,
888 	0x021b480c, 0x001b002a,
889 	0x021b4810, 0x0019002c,
890 	0x021b083c, 0x43240334,
891 	0x021b0840, 0x0324031a,
892 	0x021b483c, 0x43340344,
893 	0x021b4840, 0x03280276,
894 	0x021b0848, 0x44383A3E,
895 	0x021b4848, 0x3C3C3846,
896 	0x021b0850, 0x2e303230,
897 	0x021b4850, 0x38283E34,
898 	0x021b081c, 0x33333333,
899 	0x021b0820, 0x33333333,
900 	0x021b0824, 0x33333333,
901 	0x021b0828, 0x33333333,
902 	0x021b481c, 0x33333333,
903 	0x021b4820, 0x33333333,
904 	0x021b4824, 0x33333333,
905 	0x021b4828, 0x33333333,
906 	0x021b08c0, 0x24912249,
907 	0x021b48c0, 0x24914289,
908 	0x021b08b8, 0x00000800,
909 	0x021b48b8, 0x00000800,
910 	0x021b0004, 0x00020036,
911 	0x021b0008, 0x24444040,
912 	0x021b000c, 0x555A7955,
913 	0x021b0010, 0xFF320F64,
914 	0x021b0014, 0x01ff00db,
915 	0x021b0018, 0x00001740,
916 	0x021b001c, 0x00008000,
917 	0x021b002c, 0x000026d2,
918 	0x021b0030, 0x005A1023,
919 	0x021b0040, 0x00000027,
920 	0x021b0400, 0x14420000,
921 	0x021b0000, 0x831A0000,
922 	0x021b0890, 0x00400C58,
923 	0x00bb0008, 0x00000000,
924 	0x00bb000c, 0x2891E41A,
925 	0x00bb0038, 0x00000564,
926 	0x00bb0014, 0x00000040,
927 	0x00bb0028, 0x00000020,
928 	0x00bb002c, 0x00000020,
929 	0x021b001c, 0x04088032,
930 	0x021b001c, 0x00008033,
931 	0x021b001c, 0x00048031,
932 	0x021b001c, 0x09408030,
933 	0x021b001c, 0x04008040,
934 	0x021b0020, 0x00005800,
935 	0x021b0818, 0x00011117,
936 	0x021b4818, 0x00011117,
937 	0x021b0004, 0x00025576,
938 	0x021b0404, 0x00011006,
939 	0x021b001c, 0x00000000,
940 };
941 
942 static void ddr_init(int *table, int size)
943 {
944 	int i;
945 
946 	for (i = 0; i < size / 2 ; i++)
947 		writel(table[2 * i + 1], table[2 * i]);
948 }
949 
950 static void spl_dram_init(void)
951 {
952 	if (is_mx6dq())
953 		ddr_init(mx6q_dcd_table, ARRAY_SIZE(mx6q_dcd_table));
954 	else if (is_mx6dqp())
955 		ddr_init(mx6qp_dcd_table, ARRAY_SIZE(mx6qp_dcd_table));
956 }
957 
958 void board_init_f(ulong dummy)
959 {
960 	/* DDR initialization */
961 	spl_dram_init();
962 
963 	/* setup AIPS and disable watchdog */
964 	arch_cpu_init();
965 
966 	ccgr_init();
967 	gpr_init();
968 
969 	/* iomux and setup of i2c */
970 	board_early_init_f();
971 
972 	/* setup GP timer */
973 	timer_init();
974 
975 	/* UART clocks enabled and gd valid - init serial console */
976 	preloader_console_init();
977 
978 	/* Clear the BSS. */
979 	memset(__bss_start, 0, __bss_end - __bss_start);
980 
981 	/* load/boot image from boot device */
982 	board_init_r(NULL, 0);
983 }
984 #endif
985