]> git.sur5r.net Git - u-boot/blob - board/freescale/mx6sabresd/mx6sabresd.c
80a77892c9a1b3e1736f41abe81f9bf4c5e11e37
[u-boot] / 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 #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