]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/freescale/mx6sabresd/mx6sabresd.c
mx6sabresd: Make SPL DDR configuration to match the DCD table
[people/ms/u-boot.git] / board / freescale / mx6sabresd / mx6sabresd.c
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