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