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