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 #if defined(CONFIG_VIDEO_IPUV3)
366 static void disable_lvds(struct display_info_t const *dev)
367 {
368 	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
369 
370 	int reg = readl(&iomux->gpr[2]);
371 
372 	reg &= ~(IOMUXC_GPR2_LVDS_CH0_MODE_MASK |
373 		 IOMUXC_GPR2_LVDS_CH1_MODE_MASK);
374 
375 	writel(reg, &iomux->gpr[2]);
376 }
377 
378 static void do_enable_hdmi(struct display_info_t const *dev)
379 {
380 	disable_lvds(dev);
381 	imx_enable_hdmi_phy();
382 }
383 
384 struct display_info_t const displays[] = {{
385 	.bus	= -1,
386 	.addr	= 0,
387 	.pixfmt	= IPU_PIX_FMT_RGB666,
388 	.detect	= NULL,
389 	.enable	= enable_lvds,
390 	.mode	= {
391 		.name           = "Hannstar-XGA",
392 		.refresh        = 60,
393 		.xres           = 1024,
394 		.yres           = 768,
395 		.pixclock       = 15384,
396 		.left_margin    = 160,
397 		.right_margin   = 24,
398 		.upper_margin   = 29,
399 		.lower_margin   = 3,
400 		.hsync_len      = 136,
401 		.vsync_len      = 6,
402 		.sync           = FB_SYNC_EXT,
403 		.vmode          = FB_VMODE_NONINTERLACED
404 } }, {
405 	.bus	= -1,
406 	.addr	= 0,
407 	.pixfmt	= IPU_PIX_FMT_RGB24,
408 	.detect	= detect_hdmi,
409 	.enable	= do_enable_hdmi,
410 	.mode	= {
411 		.name           = "HDMI",
412 		.refresh        = 60,
413 		.xres           = 1024,
414 		.yres           = 768,
415 		.pixclock       = 15384,
416 		.left_margin    = 160,
417 		.right_margin   = 24,
418 		.upper_margin   = 29,
419 		.lower_margin   = 3,
420 		.hsync_len      = 136,
421 		.vsync_len      = 6,
422 		.sync           = FB_SYNC_EXT,
423 		.vmode          = FB_VMODE_NONINTERLACED
424 } }, {
425 	.bus	= 0,
426 	.addr	= 0,
427 	.pixfmt	= IPU_PIX_FMT_RGB24,
428 	.detect	= NULL,
429 	.enable	= enable_rgb,
430 	.mode	= {
431 		.name           = "SEIKO-WVGA",
432 		.refresh        = 60,
433 		.xres           = 800,
434 		.yres           = 480,
435 		.pixclock       = 29850,
436 		.left_margin    = 89,
437 		.right_margin   = 164,
438 		.upper_margin   = 23,
439 		.lower_margin   = 10,
440 		.hsync_len      = 10,
441 		.vsync_len      = 10,
442 		.sync           = 0,
443 		.vmode          = FB_VMODE_NONINTERLACED
444 } } };
445 size_t display_count = ARRAY_SIZE(displays);
446 
447 static void setup_display(void)
448 {
449 	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
450 	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
451 	int reg;
452 
453 	/* Setup HSYNC, VSYNC, DISP_CLK for debugging purposes */
454 	imx_iomux_v3_setup_multiple_pads(di0_pads, ARRAY_SIZE(di0_pads));
455 
456 	enable_ipu_clock();
457 	imx_setup_hdmi();
458 
459 	/* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */
460 	reg = readl(&mxc_ccm->CCGR3);
461 	reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK;
462 	writel(reg, &mxc_ccm->CCGR3);
463 
464 	/* set LDB0, LDB1 clk select to 011/011 */
465 	reg = readl(&mxc_ccm->cs2cdr);
466 	reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
467 		 | MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
468 	reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
469 	      | (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
470 	writel(reg, &mxc_ccm->cs2cdr);
471 
472 	reg = readl(&mxc_ccm->cscmr2);
473 	reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
474 	writel(reg, &mxc_ccm->cscmr2);
475 
476 	reg = readl(&mxc_ccm->chsccdr);
477 	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
478 		<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
479 	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
480 		<< MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET);
481 	writel(reg, &mxc_ccm->chsccdr);
482 
483 	reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
484 	     | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW
485 	     | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
486 	     | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
487 	     | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
488 	     | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
489 	     | IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
490 	     | IOMUXC_GPR2_LVDS_CH0_MODE_DISABLED
491 	     | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0;
492 	writel(reg, &iomux->gpr[2]);
493 
494 	reg = readl(&iomux->gpr[3]);
495 	reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK
496 			| IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
497 	    | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
498 	       << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
499 	writel(reg, &iomux->gpr[3]);
500 }
501 #endif /* CONFIG_VIDEO_IPUV3 */
502 
503 /*
504  * Do not overwrite the console
505  * Use always serial for U-Boot console
506  */
507 int overwrite_console(void)
508 {
509 	return 1;
510 }
511 
512 int board_eth_init(bd_t *bis)
513 {
514 	setup_iomux_enet();
515 	setup_pcie();
516 
517 	return cpu_eth_init(bis);
518 }
519 
520 #ifdef CONFIG_USB_EHCI_MX6
521 #define USB_OTHERREGS_OFFSET	0x800
522 #define UCTRL_PWR_POL		(1 << 9)
523 
524 static iomux_v3_cfg_t const usb_otg_pads[] = {
525 	MX6_PAD_EIM_D22__USB_OTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
526 	MX6_PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
527 };
528 
529 static iomux_v3_cfg_t const usb_hc1_pads[] = {
530 	MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
531 };
532 
533 static void setup_usb(void)
534 {
535 	imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
536 					 ARRAY_SIZE(usb_otg_pads));
537 
538 	/*
539 	 * set daisy chain for otg_pin_id on 6q.
540 	 * for 6dl, this bit is reserved
541 	 */
542 	imx_iomux_set_gpr_register(1, 13, 1, 0);
543 
544 	imx_iomux_v3_setup_multiple_pads(usb_hc1_pads,
545 					 ARRAY_SIZE(usb_hc1_pads));
546 }
547 
548 int board_ehci_hcd_init(int port)
549 {
550 	u32 *usbnc_usb_ctrl;
551 
552 	if (port > 1)
553 		return -EINVAL;
554 
555 	usbnc_usb_ctrl = (u32 *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET +
556 				 port * 4);
557 
558 	setbits_le32(usbnc_usb_ctrl, UCTRL_PWR_POL);
559 
560 	return 0;
561 }
562 
563 int board_ehci_power(int port, int on)
564 {
565 	switch (port) {
566 	case 0:
567 		break;
568 	case 1:
569 		if (on)
570 			gpio_direction_output(IMX_GPIO_NR(1, 29), 1);
571 		else
572 			gpio_direction_output(IMX_GPIO_NR(1, 29), 0);
573 		break;
574 	default:
575 		printf("MXC USB port %d not yet supported\n", port);
576 		return -EINVAL;
577 	}
578 
579 	return 0;
580 }
581 #endif
582 
583 int board_early_init_f(void)
584 {
585 	setup_iomux_uart();
586 #if defined(CONFIG_VIDEO_IPUV3)
587 	setup_display();
588 #endif
589 
590 	return 0;
591 }
592 
593 int board_init(void)
594 {
595 	/* address of boot parameters */
596 	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
597 
598 #ifdef CONFIG_MXC_SPI
599 	setup_spi();
600 #endif
601 	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
602 
603 #ifdef CONFIG_USB_EHCI_MX6
604 	setup_usb();
605 #endif
606 
607 	return 0;
608 }
609 
610 int power_init_board(void)
611 {
612 	struct pmic *p;
613 	unsigned int reg;
614 	int ret;
615 
616 	p = pfuze_common_init(I2C_PMIC);
617 	if (!p)
618 		return -ENODEV;
619 
620 	ret = pfuze_mode_init(p, APS_PFM);
621 	if (ret < 0)
622 		return ret;
623 
624 	/* Increase VGEN3 from 2.5 to 2.8V */
625 	pmic_reg_read(p, PFUZE100_VGEN3VOL, &reg);
626 	reg &= ~LDO_VOL_MASK;
627 	reg |= LDOB_2_80V;
628 	pmic_reg_write(p, PFUZE100_VGEN3VOL, reg);
629 
630 	/* Increase VGEN5 from 2.8 to 3V */
631 	pmic_reg_read(p, PFUZE100_VGEN5VOL, &reg);
632 	reg &= ~LDO_VOL_MASK;
633 	reg |= LDOB_3_00V;
634 	pmic_reg_write(p, PFUZE100_VGEN5VOL, reg);
635 
636 	return 0;
637 }
638 
639 #ifdef CONFIG_MXC_SPI
640 int board_spi_cs_gpio(unsigned bus, unsigned cs)
641 {
642 	return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(4, 9)) : -1;
643 }
644 #endif
645 
646 #ifdef CONFIG_CMD_BMODE
647 static const struct boot_mode board_boot_modes[] = {
648 	/* 4 bit bus width */
649 	{"sd2",	 MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
650 	{"sd3",	 MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
651 	/* 8 bit bus width */
652 	{"emmc", MAKE_CFGVAL(0x60, 0x58, 0x00, 0x00)},
653 	{NULL,	 0},
654 };
655 #endif
656 
657 int board_late_init(void)
658 {
659 #ifdef CONFIG_CMD_BMODE
660 	add_board_boot_modes(board_boot_modes);
661 #endif
662 
663 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
664 	setenv("board_name", "SABRESD");
665 
666 	if (is_mx6dqp())
667 		setenv("board_rev", "MX6QP");
668 	else if (is_mx6dq())
669 		setenv("board_rev", "MX6Q");
670 	else if (is_mx6sdl())
671 		setenv("board_rev", "MX6DL");
672 #endif
673 
674 	return 0;
675 }
676 
677 int checkboard(void)
678 {
679 	puts("Board: MX6-SabreSD\n");
680 	return 0;
681 }
682 
683 #ifdef CONFIG_SPL_BUILD
684 #include <spl.h>
685 #include <libfdt.h>
686 
687 #ifdef CONFIG_SPL_OS_BOOT
688 int spl_start_uboot(void)
689 {
690 	gpio_direction_input(KEY_VOL_UP);
691 
692 	/* Only enter in Falcon mode if KEY_VOL_UP is pressed */
693 	return gpio_get_value(KEY_VOL_UP);
694 }
695 #endif
696 
697 static void ccgr_init(void)
698 {
699 	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
700 
701 	writel(0x00C03F3F, &ccm->CCGR0);
702 	writel(0x0030FC03, &ccm->CCGR1);
703 	writel(0x0FFFC000, &ccm->CCGR2);
704 	writel(0x3FF00000, &ccm->CCGR3);
705 	writel(0x00FFF300, &ccm->CCGR4);
706 	writel(0x0F0000C3, &ccm->CCGR5);
707 	writel(0x000003FF, &ccm->CCGR6);
708 }
709 
710 static void gpr_init(void)
711 {
712 	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
713 
714 	/* enable AXI cache for VDOA/VPU/IPU */
715 	writel(0xF00000CF, &iomux->gpr[4]);
716 	if (is_mx6dqp()) {
717 		/* set IPU AXI-id1 Qos=0x1 AXI-id0/2/3 Qos=0x7 */
718 		writel(0x007F007F, &iomux->gpr[6]);
719 		writel(0x007F007F, &iomux->gpr[7]);
720 	} else {
721 		/* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
722 		writel(0x007F007F, &iomux->gpr[6]);
723 		writel(0x007F007F, &iomux->gpr[7]);
724 	}
725 }
726 
727 static int mx6q_dcd_table[] = {
728 	0x020e0798, 0x000C0000,
729 	0x020e0758, 0x00000000,
730 	0x020e0588, 0x00000030,
731 	0x020e0594, 0x00000030,
732 	0x020e056c, 0x00000030,
733 	0x020e0578, 0x00000030,
734 	0x020e074c, 0x00000030,
735 	0x020e057c, 0x00000030,
736 	0x020e058c, 0x00000000,
737 	0x020e059c, 0x00000030,
738 	0x020e05a0, 0x00000030,
739 	0x020e078c, 0x00000030,
740 	0x020e0750, 0x00020000,
741 	0x020e05a8, 0x00000030,
742 	0x020e05b0, 0x00000030,
743 	0x020e0524, 0x00000030,
744 	0x020e051c, 0x00000030,
745 	0x020e0518, 0x00000030,
746 	0x020e050c, 0x00000030,
747 	0x020e05b8, 0x00000030,
748 	0x020e05c0, 0x00000030,
749 	0x020e0774, 0x00020000,
750 	0x020e0784, 0x00000030,
751 	0x020e0788, 0x00000030,
752 	0x020e0794, 0x00000030,
753 	0x020e079c, 0x00000030,
754 	0x020e07a0, 0x00000030,
755 	0x020e07a4, 0x00000030,
756 	0x020e07a8, 0x00000030,
757 	0x020e0748, 0x00000030,
758 	0x020e05ac, 0x00000030,
759 	0x020e05b4, 0x00000030,
760 	0x020e0528, 0x00000030,
761 	0x020e0520, 0x00000030,
762 	0x020e0514, 0x00000030,
763 	0x020e0510, 0x00000030,
764 	0x020e05bc, 0x00000030,
765 	0x020e05c4, 0x00000030,
766 	0x021b0800, 0xa1390003,
767 	0x021b080c, 0x001F001F,
768 	0x021b0810, 0x001F001F,
769 	0x021b480c, 0x001F001F,
770 	0x021b4810, 0x001F001F,
771 	0x021b083c, 0x43270338,
772 	0x021b0840, 0x03200314,
773 	0x021b483c, 0x431A032F,
774 	0x021b4840, 0x03200263,
775 	0x021b0848, 0x4B434748,
776 	0x021b4848, 0x4445404C,
777 	0x021b0850, 0x38444542,
778 	0x021b4850, 0x4935493A,
779 	0x021b081c, 0x33333333,
780 	0x021b0820, 0x33333333,
781 	0x021b0824, 0x33333333,
782 	0x021b0828, 0x33333333,
783 	0x021b481c, 0x33333333,
784 	0x021b4820, 0x33333333,
785 	0x021b4824, 0x33333333,
786 	0x021b4828, 0x33333333,
787 	0x021b08b8, 0x00000800,
788 	0x021b48b8, 0x00000800,
789 	0x021b0004, 0x00020036,
790 	0x021b0008, 0x09444040,
791 	0x021b000c, 0x555A7975,
792 	0x021b0010, 0xFF538F64,
793 	0x021b0014, 0x01FF00DB,
794 	0x021b0018, 0x00001740,
795 	0x021b001c, 0x00008000,
796 	0x021b002c, 0x000026d2,
797 	0x021b0030, 0x005A1023,
798 	0x021b0040, 0x00000027,
799 	0x021b0000, 0x831A0000,
800 	0x021b001c, 0x04088032,
801 	0x021b001c, 0x00008033,
802 	0x021b001c, 0x00048031,
803 	0x021b001c, 0x09408030,
804 	0x021b001c, 0x04008040,
805 	0x021b0020, 0x00005800,
806 	0x021b0818, 0x00011117,
807 	0x021b4818, 0x00011117,
808 	0x021b0004, 0x00025576,
809 	0x021b0404, 0x00011006,
810 	0x021b001c, 0x00000000,
811 };
812 
813 static int mx6qp_dcd_table[] = {
814 	0x020e0798, 0x000c0000,
815 	0x020e0758, 0x00000000,
816 	0x020e0588, 0x00000030,
817 	0x020e0594, 0x00000030,
818 	0x020e056c, 0x00000030,
819 	0x020e0578, 0x00000030,
820 	0x020e074c, 0x00000030,
821 	0x020e057c, 0x00000030,
822 	0x020e058c, 0x00000000,
823 	0x020e059c, 0x00000030,
824 	0x020e05a0, 0x00000030,
825 	0x020e078c, 0x00000030,
826 	0x020e0750, 0x00020000,
827 	0x020e05a8, 0x00000030,
828 	0x020e05b0, 0x00000030,
829 	0x020e0524, 0x00000030,
830 	0x020e051c, 0x00000030,
831 	0x020e0518, 0x00000030,
832 	0x020e050c, 0x00000030,
833 	0x020e05b8, 0x00000030,
834 	0x020e05c0, 0x00000030,
835 	0x020e0774, 0x00020000,
836 	0x020e0784, 0x00000030,
837 	0x020e0788, 0x00000030,
838 	0x020e0794, 0x00000030,
839 	0x020e079c, 0x00000030,
840 	0x020e07a0, 0x00000030,
841 	0x020e07a4, 0x00000030,
842 	0x020e07a8, 0x00000030,
843 	0x020e0748, 0x00000030,
844 	0x020e05ac, 0x00000030,
845 	0x020e05b4, 0x00000030,
846 	0x020e0528, 0x00000030,
847 	0x020e0520, 0x00000030,
848 	0x020e0514, 0x00000030,
849 	0x020e0510, 0x00000030,
850 	0x020e05bc, 0x00000030,
851 	0x020e05c4, 0x00000030,
852 	0x021b0800, 0xa1390003,
853 	0x021b080c, 0x001b001e,
854 	0x021b0810, 0x002e0029,
855 	0x021b480c, 0x001b002a,
856 	0x021b4810, 0x0019002c,
857 	0x021b083c, 0x43240334,
858 	0x021b0840, 0x0324031a,
859 	0x021b483c, 0x43340344,
860 	0x021b4840, 0x03280276,
861 	0x021b0848, 0x44383A3E,
862 	0x021b4848, 0x3C3C3846,
863 	0x021b0850, 0x2e303230,
864 	0x021b4850, 0x38283E34,
865 	0x021b081c, 0x33333333,
866 	0x021b0820, 0x33333333,
867 	0x021b0824, 0x33333333,
868 	0x021b0828, 0x33333333,
869 	0x021b481c, 0x33333333,
870 	0x021b4820, 0x33333333,
871 	0x021b4824, 0x33333333,
872 	0x021b4828, 0x33333333,
873 	0x021b08c0, 0x24912249,
874 	0x021b48c0, 0x24914289,
875 	0x021b08b8, 0x00000800,
876 	0x021b48b8, 0x00000800,
877 	0x021b0004, 0x00020036,
878 	0x021b0008, 0x24444040,
879 	0x021b000c, 0x555A7955,
880 	0x021b0010, 0xFF320F64,
881 	0x021b0014, 0x01ff00db,
882 	0x021b0018, 0x00001740,
883 	0x021b001c, 0x00008000,
884 	0x021b002c, 0x000026d2,
885 	0x021b0030, 0x005A1023,
886 	0x021b0040, 0x00000027,
887 	0x021b0400, 0x14420000,
888 	0x021b0000, 0x831A0000,
889 	0x021b0890, 0x00400C58,
890 	0x00bb0008, 0x00000000,
891 	0x00bb000c, 0x2891E41A,
892 	0x00bb0038, 0x00000564,
893 	0x00bb0014, 0x00000040,
894 	0x00bb0028, 0x00000020,
895 	0x00bb002c, 0x00000020,
896 	0x021b001c, 0x04088032,
897 	0x021b001c, 0x00008033,
898 	0x021b001c, 0x00048031,
899 	0x021b001c, 0x09408030,
900 	0x021b001c, 0x04008040,
901 	0x021b0020, 0x00005800,
902 	0x021b0818, 0x00011117,
903 	0x021b4818, 0x00011117,
904 	0x021b0004, 0x00025576,
905 	0x021b0404, 0x00011006,
906 	0x021b001c, 0x00000000,
907 };
908 
909 static void ddr_init(int *table, int size)
910 {
911 	int i;
912 
913 	for (i = 0; i < size / 2 ; i++)
914 		writel(table[2 * i + 1], table[2 * i]);
915 }
916 
917 static void spl_dram_init(void)
918 {
919 	if (is_mx6dq())
920 		ddr_init(mx6q_dcd_table, ARRAY_SIZE(mx6q_dcd_table));
921 	else if (is_mx6dqp())
922 		ddr_init(mx6qp_dcd_table, ARRAY_SIZE(mx6qp_dcd_table));
923 }
924 
925 void board_init_f(ulong dummy)
926 {
927 	/* DDR initialization */
928 	spl_dram_init();
929 
930 	/* setup AIPS and disable watchdog */
931 	arch_cpu_init();
932 
933 	ccgr_init();
934 	gpr_init();
935 
936 	/* iomux and setup of i2c */
937 	board_early_init_f();
938 
939 	/* setup GP timer */
940 	timer_init();
941 
942 	/* UART clocks enabled and gd valid - init serial console */
943 	preloader_console_init();
944 
945 	/* Clear the BSS. */
946 	memset(__bss_start, 0, __bss_end - __bss_start);
947 
948 	/* load/boot image from boot device */
949 	board_init_r(NULL, 0);
950 }
951 #endif
952