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