Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / board / boundary / nitrogen6x / nitrogen6x.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
4  * Copyright (C) 2013, Boundary Devices <info@boundarydevices.com>
5  */
6
7 #include <common.h>
8 #include <command.h>
9 #include <env.h>
10 #include <init.h>
11 #include <net.h>
12 #include <asm/io.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/imx-regs.h>
15 #include <asm/arch/iomux.h>
16 #include <asm/arch/sys_proto.h>
17 #include <malloc.h>
18 #include <asm/arch/mx6-pins.h>
19 #include <linux/delay.h>
20 #include <linux/errno.h>
21 #include <asm/gpio.h>
22 #include <asm/mach-imx/iomux-v3.h>
23 #include <asm/mach-imx/mxc_i2c.h>
24 #include <asm/mach-imx/sata.h>
25 #include <asm/mach-imx/spi.h>
26 #include <asm/mach-imx/boot_mode.h>
27 #include <asm/mach-imx/video.h>
28 #include <mmc.h>
29 #include <fsl_esdhc_imx.h>
30 #include <micrel.h>
31 #include <miiphy.h>
32 #include <netdev.h>
33 #include <asm/arch/crm_regs.h>
34 #include <asm/arch/mxc_hdmi.h>
35 #include <i2c.h>
36 #include <input.h>
37 #include <netdev.h>
38 #include <usb/ehci-ci.h>
39
40 DECLARE_GLOBAL_DATA_PTR;
41 #define GP_USB_OTG_PWR  IMX_GPIO_NR(3, 22)
42
43 #define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                   \
44         PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |                 \
45         PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
46
47 #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |                    \
48         PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |                 \
49         PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
50
51 #define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                   \
52         PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
53
54 #define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED |         \
55         PAD_CTL_DSE_40ohm     | PAD_CTL_SRE_FAST)
56
57 #define BUTTON_PAD_CTRL (PAD_CTL_PUS_100K_UP |                  \
58         PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
59
60 #define I2C_PAD_CTRL    (PAD_CTL_PUS_100K_UP |                  \
61         PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS |   \
62         PAD_CTL_ODE | PAD_CTL_SRE_FAST)
63
64 #define RGB_PAD_CTRL    PAD_CTL_DSE_120ohm
65
66 #define WEAK_PULLUP     (PAD_CTL_PUS_100K_UP |                  \
67         PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS |   \
68         PAD_CTL_SRE_SLOW)
69
70 #define WEAK_PULLDOWN   (PAD_CTL_PUS_100K_DOWN |                \
71         PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |                 \
72         PAD_CTL_HYS | PAD_CTL_SRE_SLOW)
73
74 #define OUTPUT_40OHM (PAD_CTL_SPEED_MED|PAD_CTL_DSE_40ohm)
75
76 /* Prevent compiler error if gpio number 08 or 09 is used */
77 #define not_octal(gp) ((((0x##gp >> 4) & 0xf) * 10) + ((0x##gp & 0xf)))
78
79 #define _I2C_PADS_INFO_CPU(cpu, i2cnum, scl_pad, scl_bank, scl_gp,             \
80                 sda_pad, sda_bank, sda_gp, pad_ctrl, join_io) {                \
81         .scl = {                                                               \
82                 .i2c_mode = NEW_PAD_CTRL(cpu##_PAD_##scl_pad##__##i2cnum##_SCL,\
83                                          pad_ctrl),                            \
84                 .gpio_mode = NEW_PAD_CTRL(                                     \
85                         cpu##_PAD_##scl_pad##__GPIO##scl_bank##join_io##scl_gp,\
86                         pad_ctrl),                                             \
87                 .gp = IMX_GPIO_NR(scl_bank, not_octal(scl_gp))                 \
88         },                                                                     \
89         .sda = {                                                               \
90                 .i2c_mode = NEW_PAD_CTRL(cpu##_PAD_##sda_pad##__##i2cnum##_SDA,\
91                                          pad_ctrl),                            \
92                 .gpio_mode = NEW_PAD_CTRL(                                     \
93                         cpu##_PAD_##sda_pad##__GPIO##sda_bank##join_io##sda_gp,\
94                         pad_ctrl),                                             \
95                         .gp = IMX_GPIO_NR(sda_bank, not_octal(sda_gp))         \
96         }                                                                      \
97 }
98
99 #define I2C_PADS_INFO_CPU(cpu, i2cnum, scl_pad, scl_bank, scl_gp,              \
100                 sda_pad, sda_bank, sda_gp, pad_ctrl)                           \
101                 _I2C_PADS_INFO_CPU(cpu, i2cnum, scl_pad, scl_bank, scl_gp,     \
102                                 sda_pad, sda_bank, sda_gp, pad_ctrl, _IO)
103
104 #if defined(CONFIG_MX6QDL)
105 #define I2C_PADS_INFO_ENTRY(i2cnum, scl_pad, scl_bank, scl_gp,          \
106                 sda_pad, sda_bank, sda_gp, pad_ctrl)                    \
107         I2C_PADS_INFO_CPU(MX6Q, i2cnum, scl_pad, scl_bank, scl_gp,      \
108                 sda_pad, sda_bank, sda_gp, pad_ctrl),                   \
109         I2C_PADS_INFO_CPU(MX6DL, i2cnum, scl_pad, scl_bank, scl_gp,     \
110                 sda_pad, sda_bank, sda_gp, pad_ctrl)
111 #define I2C_PADS_INFO_ENTRY_SPACING 2
112
113 #define IOMUX_PAD_CTRL(name, pad_ctrl) \
114                 NEW_PAD_CTRL(MX6Q_PAD_##name, pad_ctrl),        \
115                 NEW_PAD_CTRL(MX6DL_PAD_##name, pad_ctrl)
116 #else
117 #define I2C_PADS_INFO_ENTRY(i2cnum, scl_pad, scl_bank, scl_gp,          \
118                 sda_pad, sda_bank, sda_gp, pad_ctrl)                    \
119         I2C_PADS_INFO_CPU(MX6, i2cnum, scl_pad, scl_bank, scl_gp,       \
120                 sda_pad, sda_bank, sda_gp, pad_ctrl)
121 #define I2C_PADS_INFO_ENTRY_SPACING 1
122
123 #define IOMUX_PAD_CTRL(name, pad_ctrl) NEW_PAD_CTRL(MX6_PAD_##name, pad_ctrl)
124 #endif
125
126 int dram_init(void)
127 {
128         gd->ram_size = ((ulong)CONFIG_DDR_MB * 1024 * 1024);
129
130         return 0;
131 }
132
133 static iomux_v3_cfg_t const uart1_pads[] = {
134         IOMUX_PAD_CTRL(SD3_DAT6__UART1_RX_DATA, UART_PAD_CTRL),
135         IOMUX_PAD_CTRL(SD3_DAT7__UART1_TX_DATA, UART_PAD_CTRL),
136 };
137
138 static iomux_v3_cfg_t const uart2_pads[] = {
139         IOMUX_PAD_CTRL(EIM_D26__UART2_TX_DATA, UART_PAD_CTRL),
140         IOMUX_PAD_CTRL(EIM_D27__UART2_RX_DATA, UART_PAD_CTRL),
141 };
142
143 static struct i2c_pads_info i2c_pads[] = {
144         /* I2C1, SGTL5000 */
145         I2C_PADS_INFO_ENTRY(I2C1, EIM_D21, 3, 21, EIM_D28, 3, 28, I2C_PAD_CTRL),
146         /* I2C2 Camera, MIPI */
147         I2C_PADS_INFO_ENTRY(I2C2, KEY_COL3, 4, 12, KEY_ROW3, 4, 13,
148                             I2C_PAD_CTRL),
149         /* I2C3, J15 - RGB connector */
150         I2C_PADS_INFO_ENTRY(I2C3, GPIO_5, 1, 05, GPIO_16, 7, 11, I2C_PAD_CTRL),
151 };
152
153 #define I2C_BUS_CNT    3
154
155 static iomux_v3_cfg_t const usdhc2_pads[] = {
156         IOMUX_PAD_CTRL(SD2_CLK__SD2_CLK, USDHC_PAD_CTRL),
157         IOMUX_PAD_CTRL(SD2_CMD__SD2_CMD, USDHC_PAD_CTRL),
158         IOMUX_PAD_CTRL(SD2_DAT0__SD2_DATA0, USDHC_PAD_CTRL),
159         IOMUX_PAD_CTRL(SD2_DAT1__SD2_DATA1, USDHC_PAD_CTRL),
160         IOMUX_PAD_CTRL(SD2_DAT2__SD2_DATA2, USDHC_PAD_CTRL),
161         IOMUX_PAD_CTRL(SD2_DAT3__SD2_DATA3, USDHC_PAD_CTRL),
162 };
163
164 static iomux_v3_cfg_t const usdhc3_pads[] = {
165         IOMUX_PAD_CTRL(SD3_CLK__SD3_CLK, USDHC_PAD_CTRL),
166         IOMUX_PAD_CTRL(SD3_CMD__SD3_CMD, USDHC_PAD_CTRL),
167         IOMUX_PAD_CTRL(SD3_DAT0__SD3_DATA0, USDHC_PAD_CTRL),
168         IOMUX_PAD_CTRL(SD3_DAT1__SD3_DATA1, USDHC_PAD_CTRL),
169         IOMUX_PAD_CTRL(SD3_DAT2__SD3_DATA2, USDHC_PAD_CTRL),
170         IOMUX_PAD_CTRL(SD3_DAT3__SD3_DATA3, USDHC_PAD_CTRL),
171         IOMUX_PAD_CTRL(SD3_DAT5__GPIO7_IO00, NO_PAD_CTRL), /* CD */
172 };
173
174 static iomux_v3_cfg_t const usdhc4_pads[] = {
175         IOMUX_PAD_CTRL(SD4_CLK__SD4_CLK, USDHC_PAD_CTRL),
176         IOMUX_PAD_CTRL(SD4_CMD__SD4_CMD, USDHC_PAD_CTRL),
177         IOMUX_PAD_CTRL(SD4_DAT0__SD4_DATA0, USDHC_PAD_CTRL),
178         IOMUX_PAD_CTRL(SD4_DAT1__SD4_DATA1, USDHC_PAD_CTRL),
179         IOMUX_PAD_CTRL(SD4_DAT2__SD4_DATA2, USDHC_PAD_CTRL),
180         IOMUX_PAD_CTRL(SD4_DAT3__SD4_DATA3, USDHC_PAD_CTRL),
181         IOMUX_PAD_CTRL(NANDF_D6__GPIO2_IO06, NO_PAD_CTRL), /* CD */
182 };
183
184 static iomux_v3_cfg_t const enet_pads1[] = {
185         IOMUX_PAD_CTRL(ENET_MDIO__ENET_MDIO, ENET_PAD_CTRL),
186         IOMUX_PAD_CTRL(ENET_MDC__ENET_MDC, ENET_PAD_CTRL),
187         IOMUX_PAD_CTRL(RGMII_TXC__RGMII_TXC, ENET_PAD_CTRL),
188         IOMUX_PAD_CTRL(RGMII_TD0__RGMII_TD0, ENET_PAD_CTRL),
189         IOMUX_PAD_CTRL(RGMII_TD1__RGMII_TD1, ENET_PAD_CTRL),
190         IOMUX_PAD_CTRL(RGMII_TD2__RGMII_TD2, ENET_PAD_CTRL),
191         IOMUX_PAD_CTRL(RGMII_TD3__RGMII_TD3, ENET_PAD_CTRL),
192         IOMUX_PAD_CTRL(RGMII_TX_CTL__RGMII_TX_CTL, ENET_PAD_CTRL),
193         IOMUX_PAD_CTRL(ENET_REF_CLK__ENET_TX_CLK, ENET_PAD_CTRL),
194         /* pin 35 - 1 (PHY_AD2) on reset */
195         IOMUX_PAD_CTRL(RGMII_RXC__GPIO6_IO30, NO_PAD_CTRL),
196         /* pin 32 - 1 - (MODE0) all */
197         IOMUX_PAD_CTRL(RGMII_RD0__GPIO6_IO25, NO_PAD_CTRL),
198         /* pin 31 - 1 - (MODE1) all */
199         IOMUX_PAD_CTRL(RGMII_RD1__GPIO6_IO27, NO_PAD_CTRL),
200         /* pin 28 - 1 - (MODE2) all */
201         IOMUX_PAD_CTRL(RGMII_RD2__GPIO6_IO28, NO_PAD_CTRL),
202         /* pin 27 - 1 - (MODE3) all */
203         IOMUX_PAD_CTRL(RGMII_RD3__GPIO6_IO29, NO_PAD_CTRL),
204         /* pin 33 - 1 - (CLK125_EN) 125Mhz clockout enabled */
205         IOMUX_PAD_CTRL(RGMII_RX_CTL__GPIO6_IO24, NO_PAD_CTRL),
206         /* pin 42 PHY nRST */
207         IOMUX_PAD_CTRL(EIM_D23__GPIO3_IO23, NO_PAD_CTRL),
208         IOMUX_PAD_CTRL(ENET_RXD0__GPIO1_IO27, NO_PAD_CTRL),
209 };
210
211 static iomux_v3_cfg_t const enet_pads2[] = {
212         IOMUX_PAD_CTRL(RGMII_RXC__RGMII_RXC, ENET_PAD_CTRL),
213         IOMUX_PAD_CTRL(RGMII_RD0__RGMII_RD0, ENET_PAD_CTRL),
214         IOMUX_PAD_CTRL(RGMII_RD1__RGMII_RD1, ENET_PAD_CTRL),
215         IOMUX_PAD_CTRL(RGMII_RD2__RGMII_RD2, ENET_PAD_CTRL),
216         IOMUX_PAD_CTRL(RGMII_RD3__RGMII_RD3, ENET_PAD_CTRL),
217         IOMUX_PAD_CTRL(RGMII_RX_CTL__RGMII_RX_CTL, ENET_PAD_CTRL),
218 };
219
220 static iomux_v3_cfg_t const misc_pads[] = {
221         IOMUX_PAD_CTRL(GPIO_1__USB_OTG_ID, WEAK_PULLUP),
222         IOMUX_PAD_CTRL(KEY_COL4__USB_OTG_OC, WEAK_PULLUP),
223         IOMUX_PAD_CTRL(EIM_D30__USB_H1_OC, WEAK_PULLUP),
224         /* OTG Power enable */
225         IOMUX_PAD_CTRL(EIM_D22__GPIO3_IO22, OUTPUT_40OHM),
226 };
227
228 /* wl1271 pads on nitrogen6x */
229 static iomux_v3_cfg_t const wl12xx_pads[] = {
230         IOMUX_PAD_CTRL(NANDF_CS1__GPIO6_IO14, WEAK_PULLDOWN),
231         IOMUX_PAD_CTRL(NANDF_CS2__GPIO6_IO15, OUTPUT_40OHM),
232         IOMUX_PAD_CTRL(NANDF_CS3__GPIO6_IO16, OUTPUT_40OHM),
233 };
234 #define WL12XX_WL_IRQ_GP        IMX_GPIO_NR(6, 14)
235 #define WL12XX_WL_ENABLE_GP     IMX_GPIO_NR(6, 15)
236 #define WL12XX_BT_ENABLE_GP     IMX_GPIO_NR(6, 16)
237
238 /* Button assignments for J14 */
239 static iomux_v3_cfg_t const button_pads[] = {
240         /* Menu */
241         IOMUX_PAD_CTRL(NANDF_D1__GPIO2_IO01, BUTTON_PAD_CTRL),
242         /* Back */
243         IOMUX_PAD_CTRL(NANDF_D2__GPIO2_IO02, BUTTON_PAD_CTRL),
244         /* Labelled Search (mapped to Power under Android) */
245         IOMUX_PAD_CTRL(NANDF_D3__GPIO2_IO03, BUTTON_PAD_CTRL),
246         /* Home */
247         IOMUX_PAD_CTRL(NANDF_D4__GPIO2_IO04, BUTTON_PAD_CTRL),
248         /* Volume Down */
249         IOMUX_PAD_CTRL(GPIO_19__GPIO4_IO05, BUTTON_PAD_CTRL),
250         /* Volume Up */
251         IOMUX_PAD_CTRL(GPIO_18__GPIO7_IO13, BUTTON_PAD_CTRL),
252 };
253
254 static void setup_iomux_enet(void)
255 {
256         gpio_direction_output(IMX_GPIO_NR(3, 23), 0); /* SABRE Lite PHY rst */
257         gpio_direction_output(IMX_GPIO_NR(1, 27), 0); /* Nitrogen6X PHY rst */
258         gpio_direction_output(IMX_GPIO_NR(6, 30), 1);
259         gpio_direction_output(IMX_GPIO_NR(6, 25), 1);
260         gpio_direction_output(IMX_GPIO_NR(6, 27), 1);
261         gpio_direction_output(IMX_GPIO_NR(6, 28), 1);
262         gpio_direction_output(IMX_GPIO_NR(6, 29), 1);
263         SETUP_IOMUX_PADS(enet_pads1);
264         gpio_direction_output(IMX_GPIO_NR(6, 24), 1);
265
266         /* Need delay 10ms according to KSZ9021 spec */
267         udelay(1000 * 10);
268         gpio_set_value(IMX_GPIO_NR(3, 23), 1); /* SABRE Lite PHY reset */
269         gpio_set_value(IMX_GPIO_NR(1, 27), 1); /* Nitrogen6X PHY reset */
270
271         SETUP_IOMUX_PADS(enet_pads2);
272         udelay(100);    /* Wait 100 us before using mii interface */
273 }
274
275 static iomux_v3_cfg_t const usb_pads[] = {
276         IOMUX_PAD_CTRL(GPIO_17__GPIO7_IO12, NO_PAD_CTRL),
277 };
278
279 static void setup_iomux_uart(void)
280 {
281         SETUP_IOMUX_PADS(uart1_pads);
282         SETUP_IOMUX_PADS(uart2_pads);
283 }
284
285 #ifdef CONFIG_USB_EHCI_MX6
286 int board_ehci_hcd_init(int port)
287 {
288         SETUP_IOMUX_PADS(usb_pads);
289
290         /* Reset USB hub */
291         gpio_direction_output(IMX_GPIO_NR(7, 12), 0);
292         mdelay(2);
293         gpio_set_value(IMX_GPIO_NR(7, 12), 1);
294
295         return 0;
296 }
297
298 int board_ehci_power(int port, int on)
299 {
300         if (port)
301                 return 0;
302         gpio_set_value(GP_USB_OTG_PWR, on);
303         return 0;
304 }
305
306 #endif
307
308 #ifdef CONFIG_FSL_ESDHC_IMX
309 static struct fsl_esdhc_cfg usdhc_cfg[2] = {
310         {USDHC3_BASE_ADDR},
311         {USDHC4_BASE_ADDR},
312 };
313
314 int board_mmc_getcd(struct mmc *mmc)
315 {
316         struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
317         int gp_cd = (cfg->esdhc_base == USDHC3_BASE_ADDR) ? IMX_GPIO_NR(7, 0) :
318                         IMX_GPIO_NR(2, 6);
319
320         gpio_direction_input(gp_cd);
321         return !gpio_get_value(gp_cd);
322 }
323
324 int board_mmc_init(bd_t *bis)
325 {
326         int ret;
327         u32 index = 0;
328
329         usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
330         usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
331
332         usdhc_cfg[0].max_bus_width = 4;
333         usdhc_cfg[1].max_bus_width = 4;
334
335         for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
336                 switch (index) {
337                 case 0:
338                         SETUP_IOMUX_PADS(usdhc3_pads);
339                         break;
340                 case 1:
341                        SETUP_IOMUX_PADS(usdhc4_pads);
342                        break;
343                 default:
344                        printf("Warning: you configured more USDHC controllers"
345                                "(%d) then supported by the board (%d)\n",
346                                index + 1, CONFIG_SYS_FSL_USDHC_NUM);
347                        return -EINVAL;
348                 }
349
350                 ret = fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
351                 if (ret)
352                         return ret;
353         }
354
355         return 0;
356 }
357 #endif
358
359 #ifdef CONFIG_MXC_SPI
360 int board_spi_cs_gpio(unsigned bus, unsigned cs)
361 {
362         return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(3, 19)) : -1;
363 }
364
365 static iomux_v3_cfg_t const ecspi1_pads[] = {
366         /* SS1 */
367         IOMUX_PAD_CTRL(EIM_D19__GPIO3_IO19, NO_PAD_CTRL),
368         IOMUX_PAD_CTRL(EIM_D17__ECSPI1_MISO, SPI_PAD_CTRL),
369         IOMUX_PAD_CTRL(EIM_D18__ECSPI1_MOSI, SPI_PAD_CTRL),
370         IOMUX_PAD_CTRL(EIM_D16__ECSPI1_SCLK, SPI_PAD_CTRL),
371 };
372
373 static void setup_spi(void)
374 {
375         SETUP_IOMUX_PADS(ecspi1_pads);
376 }
377 #endif
378
379 int board_phy_config(struct phy_device *phydev)
380 {
381         /* min rx data delay */
382         ksz9021_phy_extended_write(phydev,
383                         MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0x0);
384         /* min tx data delay */
385         ksz9021_phy_extended_write(phydev,
386                         MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0x0);
387         /* max rx/tx clock delay, min rx/tx control */
388         ksz9021_phy_extended_write(phydev,
389                         MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0xf0f0);
390         if (phydev->drv->config)
391                 phydev->drv->config(phydev);
392
393         return 0;
394 }
395
396 int board_eth_init(bd_t *bis)
397 {
398         uint32_t base = IMX_FEC_BASE;
399         struct mii_dev *bus = NULL;
400         struct phy_device *phydev = NULL;
401         int ret;
402
403         gpio_request(WL12XX_WL_IRQ_GP, "wifi_irq");
404         gpio_request(IMX_GPIO_NR(6, 30), "rgmii_rxc");
405         gpio_request(IMX_GPIO_NR(6, 25), "rgmii_rd0");
406         gpio_request(IMX_GPIO_NR(6, 27), "rgmii_rd1");
407         gpio_request(IMX_GPIO_NR(6, 28), "rgmii_rd2");
408         gpio_request(IMX_GPIO_NR(6, 29), "rgmii_rd3");
409         gpio_request(IMX_GPIO_NR(6, 24), "rgmii_rx_ctl");
410         gpio_request(IMX_GPIO_NR(3, 23), "rgmii_reset_sabrelite");
411         gpio_request(IMX_GPIO_NR(1, 27), "rgmii_reset_nitrogen6x");
412         setup_iomux_enet();
413
414 #ifdef CONFIG_FEC_MXC
415         bus = fec_get_miibus(base, -1);
416         if (!bus)
417                 return -EINVAL;
418         /* scan phy 4,5,6,7 */
419         phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII);
420         if (!phydev) {
421                 ret = -EINVAL;
422                 goto free_bus;
423         }
424         printf("using phy at %d\n", phydev->addr);
425         ret  = fec_probe(bis, -1, base, bus, phydev);
426         if (ret)
427                 goto free_phydev;
428 #endif
429
430 #ifdef CONFIG_CI_UDC
431         /* For otg ethernet*/
432         usb_eth_initialize(bis);
433 #endif
434         return 0;
435
436 free_phydev:
437         free(phydev);
438 free_bus:
439         free(bus);
440         return ret;
441 }
442
443 static void setup_buttons(void)
444 {
445         SETUP_IOMUX_PADS(button_pads);
446 }
447
448 #if defined(CONFIG_VIDEO_IPUV3)
449
450 static iomux_v3_cfg_t const backlight_pads[] = {
451         /* Backlight on RGB connector: J15 */
452         IOMUX_PAD_CTRL(SD1_DAT3__GPIO1_IO21, NO_PAD_CTRL),
453 #define RGB_BACKLIGHT_GP IMX_GPIO_NR(1, 21)
454
455         /* Backlight on LVDS connector: J6 */
456         IOMUX_PAD_CTRL(SD1_CMD__GPIO1_IO18, NO_PAD_CTRL),
457 #define LVDS_BACKLIGHT_GP IMX_GPIO_NR(1, 18)
458 };
459
460 static iomux_v3_cfg_t const rgb_pads[] = {
461         IOMUX_PAD_CTRL(DI0_DISP_CLK__IPU1_DI0_DISP_CLK, RGB_PAD_CTRL),
462         IOMUX_PAD_CTRL(DI0_PIN15__IPU1_DI0_PIN15, RGB_PAD_CTRL),
463         IOMUX_PAD_CTRL(DI0_PIN2__IPU1_DI0_PIN02, RGB_PAD_CTRL),
464         IOMUX_PAD_CTRL(DI0_PIN3__IPU1_DI0_PIN03, RGB_PAD_CTRL),
465         IOMUX_PAD_CTRL(DI0_PIN4__GPIO4_IO20, RGB_PAD_CTRL),
466         IOMUX_PAD_CTRL(DISP0_DAT0__IPU1_DISP0_DATA00, RGB_PAD_CTRL),
467         IOMUX_PAD_CTRL(DISP0_DAT1__IPU1_DISP0_DATA01, RGB_PAD_CTRL),
468         IOMUX_PAD_CTRL(DISP0_DAT2__IPU1_DISP0_DATA02, RGB_PAD_CTRL),
469         IOMUX_PAD_CTRL(DISP0_DAT3__IPU1_DISP0_DATA03, RGB_PAD_CTRL),
470         IOMUX_PAD_CTRL(DISP0_DAT4__IPU1_DISP0_DATA04, RGB_PAD_CTRL),
471         IOMUX_PAD_CTRL(DISP0_DAT5__IPU1_DISP0_DATA05, RGB_PAD_CTRL),
472         IOMUX_PAD_CTRL(DISP0_DAT6__IPU1_DISP0_DATA06, RGB_PAD_CTRL),
473         IOMUX_PAD_CTRL(DISP0_DAT7__IPU1_DISP0_DATA07, RGB_PAD_CTRL),
474         IOMUX_PAD_CTRL(DISP0_DAT8__IPU1_DISP0_DATA08, RGB_PAD_CTRL),
475         IOMUX_PAD_CTRL(DISP0_DAT9__IPU1_DISP0_DATA09, RGB_PAD_CTRL),
476         IOMUX_PAD_CTRL(DISP0_DAT10__IPU1_DISP0_DATA10, RGB_PAD_CTRL),
477         IOMUX_PAD_CTRL(DISP0_DAT11__IPU1_DISP0_DATA11, RGB_PAD_CTRL),
478         IOMUX_PAD_CTRL(DISP0_DAT12__IPU1_DISP0_DATA12, RGB_PAD_CTRL),
479         IOMUX_PAD_CTRL(DISP0_DAT13__IPU1_DISP0_DATA13, RGB_PAD_CTRL),
480         IOMUX_PAD_CTRL(DISP0_DAT14__IPU1_DISP0_DATA14, RGB_PAD_CTRL),
481         IOMUX_PAD_CTRL(DISP0_DAT15__IPU1_DISP0_DATA15, RGB_PAD_CTRL),
482         IOMUX_PAD_CTRL(DISP0_DAT16__IPU1_DISP0_DATA16, RGB_PAD_CTRL),
483         IOMUX_PAD_CTRL(DISP0_DAT17__IPU1_DISP0_DATA17, RGB_PAD_CTRL),
484         IOMUX_PAD_CTRL(DISP0_DAT18__IPU1_DISP0_DATA18, RGB_PAD_CTRL),
485         IOMUX_PAD_CTRL(DISP0_DAT19__IPU1_DISP0_DATA19, RGB_PAD_CTRL),
486         IOMUX_PAD_CTRL(DISP0_DAT20__IPU1_DISP0_DATA20, RGB_PAD_CTRL),
487         IOMUX_PAD_CTRL(DISP0_DAT21__IPU1_DISP0_DATA21, RGB_PAD_CTRL),
488         IOMUX_PAD_CTRL(DISP0_DAT22__IPU1_DISP0_DATA22, RGB_PAD_CTRL),
489         IOMUX_PAD_CTRL(DISP0_DAT23__IPU1_DISP0_DATA23, RGB_PAD_CTRL),
490 };
491
492 static void do_enable_hdmi(struct display_info_t const *dev)
493 {
494         imx_enable_hdmi_phy();
495 }
496
497 static int detect_i2c(struct display_info_t const *dev)
498 {
499         return ((0 == i2c_set_bus_num(dev->bus))
500                 &&
501                 (0 == i2c_probe(dev->addr)));
502 }
503
504 static void enable_lvds(struct display_info_t const *dev)
505 {
506         struct iomuxc *iomux = (struct iomuxc *)
507                                 IOMUXC_BASE_ADDR;
508         u32 reg = readl(&iomux->gpr[2]);
509         reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT;
510         writel(reg, &iomux->gpr[2]);
511         gpio_direction_output(LVDS_BACKLIGHT_GP, 1);
512 }
513
514 static void enable_lvds_jeida(struct display_info_t const *dev)
515 {
516         struct iomuxc *iomux = (struct iomuxc *)
517                                 IOMUXC_BASE_ADDR;
518         u32 reg = readl(&iomux->gpr[2]);
519         reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT
520              |IOMUXC_GPR2_BIT_MAPPING_CH0_JEIDA;
521         writel(reg, &iomux->gpr[2]);
522         gpio_direction_output(LVDS_BACKLIGHT_GP, 1);
523 }
524
525 static void enable_rgb(struct display_info_t const *dev)
526 {
527         SETUP_IOMUX_PADS(rgb_pads);
528         gpio_direction_output(RGB_BACKLIGHT_GP, 1);
529 }
530
531 struct display_info_t const displays[] = {{
532         .bus    = 1,
533         .addr   = 0x50,
534         .pixfmt = IPU_PIX_FMT_RGB24,
535         .detect = detect_i2c,
536         .enable = do_enable_hdmi,
537         .mode   = {
538                 .name           = "HDMI",
539                 .refresh        = 60,
540                 .xres           = 1024,
541                 .yres           = 768,
542                 .pixclock       = 15385,
543                 .left_margin    = 220,
544                 .right_margin   = 40,
545                 .upper_margin   = 21,
546                 .lower_margin   = 7,
547                 .hsync_len      = 60,
548                 .vsync_len      = 10,
549                 .sync           = FB_SYNC_EXT,
550                 .vmode          = FB_VMODE_NONINTERLACED
551 } }, {
552         .bus    = 0,
553         .addr   = 0,
554         .pixfmt = IPU_PIX_FMT_RGB24,
555         .detect = NULL,
556         .enable = enable_lvds_jeida,
557         .mode   = {
558                 .name           = "LDB-WXGA",
559                 .refresh        = 60,
560                 .xres           = 1280,
561                 .yres           = 800,
562                 .pixclock       = 14065,
563                 .left_margin    = 40,
564                 .right_margin   = 40,
565                 .upper_margin   = 3,
566                 .lower_margin   = 80,
567                 .hsync_len      = 10,
568                 .vsync_len      = 10,
569                 .sync           = FB_SYNC_EXT,
570                 .vmode          = FB_VMODE_NONINTERLACED
571 } }, {
572         .bus    = 0,
573         .addr   = 0,
574         .pixfmt = IPU_PIX_FMT_RGB24,
575         .detect = NULL,
576         .enable = enable_lvds,
577         .mode   = {
578                 .name           = "LDB-WXGA-S",
579                 .refresh        = 60,
580                 .xres           = 1280,
581                 .yres           = 800,
582                 .pixclock       = 14065,
583                 .left_margin    = 40,
584                 .right_margin   = 40,
585                 .upper_margin   = 3,
586                 .lower_margin   = 80,
587                 .hsync_len      = 10,
588                 .vsync_len      = 10,
589                 .sync           = FB_SYNC_EXT,
590                 .vmode          = FB_VMODE_NONINTERLACED
591 } }, {
592         .bus    = 2,
593         .addr   = 0x4,
594         .pixfmt = IPU_PIX_FMT_LVDS666,
595         .detect = detect_i2c,
596         .enable = enable_lvds,
597         .mode   = {
598                 .name           = "Hannstar-XGA",
599                 .refresh        = 60,
600                 .xres           = 1024,
601                 .yres           = 768,
602                 .pixclock       = 15385,
603                 .left_margin    = 220,
604                 .right_margin   = 40,
605                 .upper_margin   = 21,
606                 .lower_margin   = 7,
607                 .hsync_len      = 60,
608                 .vsync_len      = 10,
609                 .sync           = FB_SYNC_EXT,
610                 .vmode          = FB_VMODE_NONINTERLACED
611 } }, {
612         .bus    = 0,
613         .addr   = 0,
614         .pixfmt = IPU_PIX_FMT_LVDS666,
615         .detect = NULL,
616         .enable = enable_lvds,
617         .mode   = {
618                 .name           = "LG-9.7",
619                 .refresh        = 60,
620                 .xres           = 1024,
621                 .yres           = 768,
622                 .pixclock       = 15385, /* ~65MHz */
623                 .left_margin    = 480,
624                 .right_margin   = 260,
625                 .upper_margin   = 16,
626                 .lower_margin   = 6,
627                 .hsync_len      = 250,
628                 .vsync_len      = 10,
629                 .sync           = FB_SYNC_EXT,
630                 .vmode          = FB_VMODE_NONINTERLACED
631 } }, {
632         .bus    = 2,
633         .addr   = 0x38,
634         .pixfmt = IPU_PIX_FMT_LVDS666,
635         .detect = detect_i2c,
636         .enable = enable_lvds,
637         .mode   = {
638                 .name           = "wsvga-lvds",
639                 .refresh        = 60,
640                 .xres           = 1024,
641                 .yres           = 600,
642                 .pixclock       = 15385,
643                 .left_margin    = 220,
644                 .right_margin   = 40,
645                 .upper_margin   = 21,
646                 .lower_margin   = 7,
647                 .hsync_len      = 60,
648                 .vsync_len      = 10,
649                 .sync           = FB_SYNC_EXT,
650                 .vmode          = FB_VMODE_NONINTERLACED
651 } }, {
652         .bus    = 2,
653         .addr   = 0x10,
654         .pixfmt = IPU_PIX_FMT_RGB666,
655         .detect = detect_i2c,
656         .enable = enable_rgb,
657         .mode   = {
658                 .name           = "fusion7",
659                 .refresh        = 60,
660                 .xres           = 800,
661                 .yres           = 480,
662                 .pixclock       = 33898,
663                 .left_margin    = 96,
664                 .right_margin   = 24,
665                 .upper_margin   = 3,
666                 .lower_margin   = 10,
667                 .hsync_len      = 72,
668                 .vsync_len      = 7,
669                 .sync           = 0x40000002,
670                 .vmode          = FB_VMODE_NONINTERLACED
671 } }, {
672         .bus    = 0,
673         .addr   = 0,
674         .pixfmt = IPU_PIX_FMT_RGB666,
675         .detect = NULL,
676         .enable = enable_rgb,
677         .mode   = {
678                 .name           = "svga",
679                 .refresh        = 60,
680                 .xres           = 800,
681                 .yres           = 600,
682                 .pixclock       = 15385,
683                 .left_margin    = 220,
684                 .right_margin   = 40,
685                 .upper_margin   = 21,
686                 .lower_margin   = 7,
687                 .hsync_len      = 60,
688                 .vsync_len      = 10,
689                 .sync           = 0,
690                 .vmode          = FB_VMODE_NONINTERLACED
691 } }, {
692         .bus    = 2,
693         .addr   = 0x41,
694         .pixfmt = IPU_PIX_FMT_LVDS666,
695         .detect = detect_i2c,
696         .enable = enable_lvds,
697         .mode   = {
698                 .name           = "amp1024x600",
699                 .refresh        = 60,
700                 .xres           = 1024,
701                 .yres           = 600,
702                 .pixclock       = 15385,
703                 .left_margin    = 220,
704                 .right_margin   = 40,
705                 .upper_margin   = 21,
706                 .lower_margin   = 7,
707                 .hsync_len      = 60,
708                 .vsync_len      = 10,
709                 .sync           = FB_SYNC_EXT,
710                 .vmode          = FB_VMODE_NONINTERLACED
711 } }, {
712         .bus    = 0,
713         .addr   = 0,
714         .pixfmt = IPU_PIX_FMT_LVDS666,
715         .detect = 0,
716         .enable = enable_lvds,
717         .mode   = {
718                 .name           = "wvga-lvds",
719                 .refresh        = 57,
720                 .xres           = 800,
721                 .yres           = 480,
722                 .pixclock       = 15385,
723                 .left_margin    = 220,
724                 .right_margin   = 40,
725                 .upper_margin   = 21,
726                 .lower_margin   = 7,
727                 .hsync_len      = 60,
728                 .vsync_len      = 10,
729                 .sync           = FB_SYNC_EXT,
730                 .vmode          = FB_VMODE_NONINTERLACED
731 } }, {
732         .bus    = 2,
733         .addr   = 0x48,
734         .pixfmt = IPU_PIX_FMT_RGB666,
735         .detect = detect_i2c,
736         .enable = enable_rgb,
737         .mode   = {
738                 .name           = "wvga-rgb",
739                 .refresh        = 57,
740                 .xres           = 800,
741                 .yres           = 480,
742                 .pixclock       = 37037,
743                 .left_margin    = 40,
744                 .right_margin   = 60,
745                 .upper_margin   = 10,
746                 .lower_margin   = 10,
747                 .hsync_len      = 20,
748                 .vsync_len      = 10,
749                 .sync           = 0,
750                 .vmode          = FB_VMODE_NONINTERLACED
751 } }, {
752         .bus    = 0,
753         .addr   = 0,
754         .pixfmt = IPU_PIX_FMT_RGB24,
755         .detect = NULL,
756         .enable = enable_rgb,
757         .mode   = {
758                 .name           = "qvga",
759                 .refresh        = 60,
760                 .xres           = 320,
761                 .yres           = 240,
762                 .pixclock       = 37037,
763                 .left_margin    = 38,
764                 .right_margin   = 37,
765                 .upper_margin   = 16,
766                 .lower_margin   = 15,
767                 .hsync_len      = 30,
768                 .vsync_len      = 3,
769                 .sync           = 0,
770                 .vmode          = FB_VMODE_NONINTERLACED
771 } } };
772 size_t display_count = ARRAY_SIZE(displays);
773
774 int board_cfb_skip(void)
775 {
776         return NULL != env_get("novideo");
777 }
778
779 static void setup_display(void)
780 {
781         struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
782         struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
783         int reg;
784
785         enable_ipu_clock();
786         imx_setup_hdmi();
787         /* Turn on LDB0,IPU,IPU DI0 clocks */
788         reg = __raw_readl(&mxc_ccm->CCGR3);
789         reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK;
790         writel(reg, &mxc_ccm->CCGR3);
791
792         /* set LDB0, LDB1 clk select to 011/011 */
793         reg = readl(&mxc_ccm->cs2cdr);
794         reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
795                  |MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
796         reg |= (3<<MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
797               |(3<<MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
798         writel(reg, &mxc_ccm->cs2cdr);
799
800         reg = readl(&mxc_ccm->cscmr2);
801         reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
802         writel(reg, &mxc_ccm->cscmr2);
803
804         reg = readl(&mxc_ccm->chsccdr);
805         reg |= (CHSCCDR_CLK_SEL_LDB_DI0
806                 <<MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
807         writel(reg, &mxc_ccm->chsccdr);
808
809         reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
810              |IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH
811              |IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
812              |IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
813              |IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
814              |IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
815              |IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
816              |IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED
817              |IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
818         writel(reg, &iomux->gpr[2]);
819
820         reg = readl(&iomux->gpr[3]);
821         reg = (reg & ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK
822                         |IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
823             | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
824                <<IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
825         writel(reg, &iomux->gpr[3]);
826
827         /* backlights off until needed */
828         SETUP_IOMUX_PADS(backlight_pads);
829         gpio_direction_input(LVDS_BACKLIGHT_GP);
830         gpio_direction_input(RGB_BACKLIGHT_GP);
831 }
832 #endif
833
834 static iomux_v3_cfg_t const init_pads[] = {
835         /* SGTL5000 sys_mclk */
836         IOMUX_PAD_CTRL(GPIO_0__CCM_CLKO1, OUTPUT_40OHM),
837
838         /* J5 - Camera MCLK */
839         IOMUX_PAD_CTRL(GPIO_3__CCM_CLKO2, OUTPUT_40OHM),
840
841         /* wl1271 pads on nitrogen6x */
842         /* WL12XX_WL_IRQ_GP */
843         IOMUX_PAD_CTRL(NANDF_CS1__GPIO6_IO14, WEAK_PULLDOWN),
844         /* WL12XX_WL_ENABLE_GP */
845         IOMUX_PAD_CTRL(NANDF_CS2__GPIO6_IO15, OUTPUT_40OHM),
846         /* WL12XX_BT_ENABLE_GP */
847         IOMUX_PAD_CTRL(NANDF_CS3__GPIO6_IO16, OUTPUT_40OHM),
848         /* USB otg power */
849         IOMUX_PAD_CTRL(EIM_D22__GPIO3_IO22, OUTPUT_40OHM),
850         IOMUX_PAD_CTRL(NANDF_D5__GPIO2_IO05, OUTPUT_40OHM),
851         IOMUX_PAD_CTRL(NANDF_WP_B__GPIO6_IO09, OUTPUT_40OHM),
852         IOMUX_PAD_CTRL(GPIO_8__GPIO1_IO08, OUTPUT_40OHM),
853         IOMUX_PAD_CTRL(GPIO_6__GPIO1_IO06, OUTPUT_40OHM),
854 };
855
856 #define WL12XX_WL_IRQ_GP        IMX_GPIO_NR(6, 14)
857
858 static unsigned gpios_out_low[] = {
859         /* Disable wl1271 */
860         IMX_GPIO_NR(6, 15),     /* disable wireless */
861         IMX_GPIO_NR(6, 16),     /* disable bluetooth */
862         IMX_GPIO_NR(3, 22),     /* disable USB otg power */
863         IMX_GPIO_NR(2, 5),      /* ov5640 mipi camera reset */
864         IMX_GPIO_NR(1, 8),      /* ov5642 reset */
865 };
866
867 static unsigned gpios_out_high[] = {
868         IMX_GPIO_NR(1, 6),      /* ov5642 powerdown */
869         IMX_GPIO_NR(6, 9),      /* ov5640 mipi camera power down */
870 };
871
872 static void set_gpios(unsigned *p, int cnt, int val)
873 {
874         int i;
875
876         for (i = 0; i < cnt; i++)
877                 gpio_direction_output(*p++, val);
878 }
879
880 int board_early_init_f(void)
881 {
882         setup_iomux_uart();
883
884         set_gpios(gpios_out_high, ARRAY_SIZE(gpios_out_high), 1);
885         set_gpios(gpios_out_low, ARRAY_SIZE(gpios_out_low), 0);
886         gpio_direction_input(WL12XX_WL_IRQ_GP);
887
888         SETUP_IOMUX_PADS(wl12xx_pads);
889         SETUP_IOMUX_PADS(init_pads);
890         setup_buttons();
891
892 #if defined(CONFIG_VIDEO_IPUV3)
893         setup_display();
894 #endif
895         return 0;
896 }
897
898 /*
899  * Do not overwrite the console
900  * Use always serial for U-Boot console
901  */
902 int overwrite_console(void)
903 {
904         return 1;
905 }
906
907 int board_init(void)
908 {
909         struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
910         struct i2c_pads_info *p = i2c_pads;
911         int i;
912         int stride = 1;
913
914 #if defined(CONFIG_MX6QDL)
915         stride = 2;
916         if (!is_mx6dq() && !is_mx6dqp())
917                 p += 1;
918 #endif
919         clrsetbits_le32(&iomuxc_regs->gpr[1],
920                         IOMUXC_GPR1_OTG_ID_MASK,
921                         IOMUXC_GPR1_OTG_ID_GPIO1);
922
923         SETUP_IOMUX_PADS(misc_pads);
924
925         /* address of boot parameters */
926         gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
927
928 #ifdef CONFIG_MXC_SPI
929         setup_spi();
930 #endif
931         SETUP_IOMUX_PADS(usdhc2_pads);
932         for (i = 0; i < I2C_BUS_CNT; i++) {
933                 setup_i2c(i, CONFIG_SYS_I2C_SPEED, 0x7f, p);
934                 p += stride;
935         }
936
937 #ifdef CONFIG_SATA
938         setup_sata();
939 #endif
940
941         return 0;
942 }
943
944 int checkboard(void)
945 {
946         int ret = gpio_get_value(WL12XX_WL_IRQ_GP);
947
948         if (ret < 0) {
949                 /* The gpios have not been probed yet. Read it myself */
950                 struct gpio_regs *regs = (struct gpio_regs *)GPIO6_BASE_ADDR;
951                 int gpio = WL12XX_WL_IRQ_GP & 0x1f;
952
953                 ret = (readl(&regs->gpio_psr) >> gpio) & 0x01;
954         }
955         if (ret)
956                 puts("Board: Nitrogen6X\n");
957         else
958                 puts("Board: SABRE Lite\n");
959
960         return 0;
961 }
962
963 struct button_key {
964         char const      *name;
965         unsigned        gpnum;
966         char            ident;
967 };
968
969 static struct button_key const buttons[] = {
970         {"back",        IMX_GPIO_NR(2, 2),      'B'},
971         {"home",        IMX_GPIO_NR(2, 4),      'H'},
972         {"menu",        IMX_GPIO_NR(2, 1),      'M'},
973         {"search",      IMX_GPIO_NR(2, 3),      'S'},
974         {"volup",       IMX_GPIO_NR(7, 13),     'V'},
975         {"voldown",     IMX_GPIO_NR(4, 5),      'v'},
976 };
977
978 /*
979  * generate a null-terminated string containing the buttons pressed
980  * returns number of keys pressed
981  */
982 static int read_keys(char *buf)
983 {
984         int i, numpressed = 0;
985         for (i = 0; i < ARRAY_SIZE(buttons); i++) {
986                 if (!gpio_get_value(buttons[i].gpnum))
987                         buf[numpressed++] = buttons[i].ident;
988         }
989         buf[numpressed] = '\0';
990         return numpressed;
991 }
992
993 static int do_kbd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
994 {
995         char envvalue[ARRAY_SIZE(buttons)+1];
996         int numpressed = read_keys(envvalue);
997         env_set("keybd", envvalue);
998         return numpressed == 0;
999 }
1000
1001 U_BOOT_CMD(
1002         kbd, 1, 1, do_kbd,
1003         "Tests for keypresses, sets 'keybd' environment variable",
1004         "Returns 0 (true) to shell if key is pressed."
1005 );
1006
1007 #ifdef CONFIG_PREBOOT
1008 static char const kbd_magic_prefix[] = "key_magic";
1009 static char const kbd_command_prefix[] = "key_cmd";
1010
1011 static void preboot_keys(void)
1012 {
1013         int numpressed;
1014         char keypress[ARRAY_SIZE(buttons)+1];
1015         numpressed = read_keys(keypress);
1016         if (numpressed) {
1017                 char *kbd_magic_keys = env_get("magic_keys");
1018                 char *suffix;
1019                 /*
1020                  * loop over all magic keys
1021                  */
1022                 for (suffix = kbd_magic_keys; *suffix; ++suffix) {
1023                         char *keys;
1024                         char magic[sizeof(kbd_magic_prefix) + 1];
1025                         sprintf(magic, "%s%c", kbd_magic_prefix, *suffix);
1026                         keys = env_get(magic);
1027                         if (keys) {
1028                                 if (!strcmp(keys, keypress))
1029                                         break;
1030                         }
1031                 }
1032                 if (*suffix) {
1033                         char cmd_name[sizeof(kbd_command_prefix) + 1];
1034                         char *cmd;
1035                         sprintf(cmd_name, "%s%c", kbd_command_prefix, *suffix);
1036                         cmd = env_get(cmd_name);
1037                         if (cmd) {
1038                                 env_set("preboot", cmd);
1039                                 return;
1040                         }
1041                 }
1042         }
1043 }
1044 #endif
1045
1046 #ifdef CONFIG_CMD_BMODE
1047 static const struct boot_mode board_boot_modes[] = {
1048         /* 4 bit bus width */
1049         {"mmc0",        MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
1050         {"mmc1",        MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
1051         {NULL,          0},
1052 };
1053 #endif
1054
1055 int misc_init_r(void)
1056 {
1057         gpio_request(RGB_BACKLIGHT_GP, "lvds backlight");
1058         gpio_request(LVDS_BACKLIGHT_GP, "lvds backlight");
1059         gpio_request(GP_USB_OTG_PWR, "usbotg power");
1060         gpio_request(IMX_GPIO_NR(7, 12), "usbh1 hub reset");
1061         gpio_request(IMX_GPIO_NR(2, 2), "back");
1062         gpio_request(IMX_GPIO_NR(2, 4), "home");
1063         gpio_request(IMX_GPIO_NR(2, 1), "menu");
1064         gpio_request(IMX_GPIO_NR(2, 3), "search");
1065         gpio_request(IMX_GPIO_NR(7, 13), "volup");
1066         gpio_request(IMX_GPIO_NR(4, 5), "voldown");
1067 #ifdef CONFIG_PREBOOT
1068         preboot_keys();
1069 #endif
1070
1071 #ifdef CONFIG_CMD_BMODE
1072         add_board_boot_modes(board_boot_modes);
1073 #endif
1074         env_set_hex("reset_cause", get_imx_reset_cause());
1075         return 0;
1076 }