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