uboot/board/freescale/mx6sabresd/mx6sabresd.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Freescale Semiconductor, Inc.
   3 *
   4 * Author: Fabio Estevam <fabio.estevam@freescale.com>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <asm/arch/clock.h>
  10#include <asm/arch/imx-regs.h>
  11#include <asm/arch/iomux.h>
  12#include <asm/arch/mx6-pins.h>
  13#include <asm/errno.h>
  14#include <asm/gpio.h>
  15#include <asm/imx-common/mxc_i2c.h>
  16#include <asm/imx-common/iomux-v3.h>
  17#include <asm/imx-common/boot_mode.h>
  18#include <asm/imx-common/video.h>
  19#include <mmc.h>
  20#include <fsl_esdhc.h>
  21#include <miiphy.h>
  22#include <netdev.h>
  23#include <asm/arch/mxc_hdmi.h>
  24#include <asm/arch/crm_regs.h>
  25#include <asm/io.h>
  26#include <asm/arch/sys_proto.h>
  27#include <i2c.h>
  28#include <power/pmic.h>
  29#include <power/pfuze100_pmic.h>
  30#include "../common/pfuze.h"
  31#include <asm/arch/mx6-ddr.h>
  32#include <usb.h>
  33
  34DECLARE_GLOBAL_DATA_PTR;
  35
  36#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                   \
  37        PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |                 \
  38        PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
  39
  40#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |                    \
  41        PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |                 \
  42        PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
  43
  44#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                   \
  45        PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
  46
  47#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
  48                      PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
  49
  50#define I2C_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                    \
  51        PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS |   \
  52        PAD_CTL_ODE | PAD_CTL_SRE_FAST)
  53
  54#define I2C_PMIC        1
  55
  56#define I2C_PAD MUX_PAD_CTRL(I2C_PAD_CTRL)
  57
  58#define DISP0_PWR_EN    IMX_GPIO_NR(1, 21)
  59
  60int dram_init(void)
  61{
  62        gd->ram_size = imx_ddr_size();
  63        return 0;
  64}
  65
  66static iomux_v3_cfg_t const uart1_pads[] = {
  67        MX6_PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
  68        MX6_PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
  69};
  70
  71static iomux_v3_cfg_t const enet_pads[] = {
  72        MX6_PAD_ENET_MDIO__ENET_MDIO            | MUX_PAD_CTRL(ENET_PAD_CTRL),
  73        MX6_PAD_ENET_MDC__ENET_MDC              | MUX_PAD_CTRL(ENET_PAD_CTRL),
  74        MX6_PAD_RGMII_TXC__RGMII_TXC    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  75        MX6_PAD_RGMII_TD0__RGMII_TD0    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  76        MX6_PAD_RGMII_TD1__RGMII_TD1    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  77        MX6_PAD_RGMII_TD2__RGMII_TD2    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  78        MX6_PAD_RGMII_TD3__RGMII_TD3    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  79        MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL      | MUX_PAD_CTRL(ENET_PAD_CTRL),
  80        MX6_PAD_ENET_REF_CLK__ENET_TX_CLK       | MUX_PAD_CTRL(ENET_PAD_CTRL),
  81        MX6_PAD_RGMII_RXC__RGMII_RXC    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  82        MX6_PAD_RGMII_RD0__RGMII_RD0    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  83        MX6_PAD_RGMII_RD1__RGMII_RD1    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  84        MX6_PAD_RGMII_RD2__RGMII_RD2    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  85        MX6_PAD_RGMII_RD3__RGMII_RD3    | MUX_PAD_CTRL(ENET_PAD_CTRL),
  86        MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL      | MUX_PAD_CTRL(ENET_PAD_CTRL),
  87        /* AR8031 PHY Reset */
  88        MX6_PAD_ENET_CRS_DV__GPIO1_IO25         | MUX_PAD_CTRL(NO_PAD_CTRL),
  89};
  90
  91static void setup_iomux_enet(void)
  92{
  93        imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
  94
  95        /* Reset AR8031 PHY */
  96        gpio_direction_output(IMX_GPIO_NR(1, 25) , 0);
  97        mdelay(10);
  98        gpio_set_value(IMX_GPIO_NR(1, 25), 1);
  99        udelay(100);
 100}
 101
 102static iomux_v3_cfg_t const usdhc2_pads[] = {
 103        MX6_PAD_SD2_CLK__SD2_CLK        | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 104        MX6_PAD_SD2_CMD__SD2_CMD        | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 105        MX6_PAD_SD2_DAT0__SD2_DATA0     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 106        MX6_PAD_SD2_DAT1__SD2_DATA1     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 107        MX6_PAD_SD2_DAT2__SD2_DATA2     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 108        MX6_PAD_SD2_DAT3__SD2_DATA3     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 109        MX6_PAD_NANDF_D4__SD2_DATA4     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 110        MX6_PAD_NANDF_D5__SD2_DATA5     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 111        MX6_PAD_NANDF_D6__SD2_DATA6     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 112        MX6_PAD_NANDF_D7__SD2_DATA7     | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 113        MX6_PAD_NANDF_D2__GPIO2_IO02    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
 114};
 115
 116static iomux_v3_cfg_t const usdhc3_pads[] = {
 117        MX6_PAD_SD3_CLK__SD3_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 118        MX6_PAD_SD3_CMD__SD3_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 119        MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 120        MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 121        MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 122        MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 123        MX6_PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 124        MX6_PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 125        MX6_PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 126        MX6_PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 127        MX6_PAD_NANDF_D0__GPIO2_IO00    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
 128};
 129
 130static iomux_v3_cfg_t const usdhc4_pads[] = {
 131        MX6_PAD_SD4_CLK__SD4_CLK   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 132        MX6_PAD_SD4_CMD__SD4_CMD   | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 133        MX6_PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 134        MX6_PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 135        MX6_PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 136        MX6_PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 137        MX6_PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 138        MX6_PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 139        MX6_PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 140        MX6_PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
 141};
 142
 143static iomux_v3_cfg_t const ecspi1_pads[] = {
 144        MX6_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
 145        MX6_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
 146        MX6_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
 147        MX6_PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(NO_PAD_CTRL),
 148};
 149
 150static iomux_v3_cfg_t const rgb_pads[] = {
 151        MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL),
 152        MX6_PAD_DI0_PIN15__IPU1_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL),
 153        MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02 | MUX_PAD_CTRL(NO_PAD_CTRL),
 154        MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03 | MUX_PAD_CTRL(NO_PAD_CTRL),
 155        MX6_PAD_DI0_PIN4__IPU1_DI0_PIN04 | MUX_PAD_CTRL(NO_PAD_CTRL),
 156        MX6_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 | MUX_PAD_CTRL(NO_PAD_CTRL),
 157        MX6_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 | MUX_PAD_CTRL(NO_PAD_CTRL),
 158        MX6_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 | MUX_PAD_CTRL(NO_PAD_CTRL),
 159        MX6_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 | MUX_PAD_CTRL(NO_PAD_CTRL),
 160        MX6_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 | MUX_PAD_CTRL(NO_PAD_CTRL),
 161        MX6_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 | MUX_PAD_CTRL(NO_PAD_CTRL),
 162        MX6_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 | MUX_PAD_CTRL(NO_PAD_CTRL),
 163        MX6_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 | MUX_PAD_CTRL(NO_PAD_CTRL),
 164        MX6_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 | MUX_PAD_CTRL(NO_PAD_CTRL),
 165        MX6_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 | MUX_PAD_CTRL(NO_PAD_CTRL),
 166        MX6_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 | MUX_PAD_CTRL(NO_PAD_CTRL),
 167        MX6_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 | MUX_PAD_CTRL(NO_PAD_CTRL),
 168        MX6_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 | MUX_PAD_CTRL(NO_PAD_CTRL),
 169        MX6_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 | MUX_PAD_CTRL(NO_PAD_CTRL),
 170        MX6_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 | MUX_PAD_CTRL(NO_PAD_CTRL),
 171        MX6_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 | MUX_PAD_CTRL(NO_PAD_CTRL),
 172        MX6_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 | MUX_PAD_CTRL(NO_PAD_CTRL),
 173        MX6_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 | MUX_PAD_CTRL(NO_PAD_CTRL),
 174        MX6_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 | MUX_PAD_CTRL(NO_PAD_CTRL),
 175        MX6_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 | MUX_PAD_CTRL(NO_PAD_CTRL),
 176        MX6_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 | MUX_PAD_CTRL(NO_PAD_CTRL),
 177        MX6_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 | MUX_PAD_CTRL(NO_PAD_CTRL),
 178        MX6_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 | MUX_PAD_CTRL(NO_PAD_CTRL),
 179        MX6_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 | MUX_PAD_CTRL(NO_PAD_CTRL),
 180};
 181
 182static iomux_v3_cfg_t const bl_pads[] = {
 183        MX6_PAD_SD1_DAT3__GPIO1_IO21 | MUX_PAD_CTRL(NO_PAD_CTRL),
 184};
 185
 186static void enable_backlight(void)
 187{
 188        imx_iomux_v3_setup_multiple_pads(bl_pads, ARRAY_SIZE(bl_pads));
 189        gpio_direction_output(DISP0_PWR_EN, 1);
 190}
 191
 192static void enable_rgb(struct display_info_t const *dev)
 193{
 194        imx_iomux_v3_setup_multiple_pads(rgb_pads, ARRAY_SIZE(rgb_pads));
 195        enable_backlight();
 196}
 197
 198static void enable_lvds(struct display_info_t const *dev)
 199{
 200        enable_backlight();
 201}
 202
 203static struct i2c_pads_info i2c_pad_info1 = {
 204        .scl = {
 205                .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL | I2C_PAD,
 206                .gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12 | I2C_PAD,
 207                .gp = IMX_GPIO_NR(4, 12)
 208        },
 209        .sda = {
 210                .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | I2C_PAD,
 211                .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | I2C_PAD,
 212                .gp = IMX_GPIO_NR(4, 13)
 213        }
 214};
 215
 216static void setup_spi(void)
 217{
 218        imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
 219}
 220
 221iomux_v3_cfg_t const pcie_pads[] = {
 222        MX6_PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL),        /* POWER */
 223        MX6_PAD_GPIO_17__GPIO7_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),        /* RESET */
 224};
 225
 226static void setup_pcie(void)
 227{
 228        imx_iomux_v3_setup_multiple_pads(pcie_pads, ARRAY_SIZE(pcie_pads));
 229}
 230
 231iomux_v3_cfg_t const di0_pads[] = {
 232        MX6_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK,        /* DISP0_CLK */
 233        MX6_PAD_DI0_PIN2__IPU1_DI0_PIN02,               /* DISP0_HSYNC */
 234        MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03,               /* DISP0_VSYNC */
 235};
 236
 237static void setup_iomux_uart(void)
 238{
 239        imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
 240}
 241
 242#ifdef CONFIG_FSL_ESDHC
 243struct fsl_esdhc_cfg usdhc_cfg[3] = {
 244        {USDHC2_BASE_ADDR},
 245        {USDHC3_BASE_ADDR},
 246        {USDHC4_BASE_ADDR},
 247};
 248
 249#define USDHC2_CD_GPIO  IMX_GPIO_NR(2, 2)
 250#define USDHC3_CD_GPIO  IMX_GPIO_NR(2, 0)
 251
 252int board_mmc_get_env_dev(int devno)
 253{
 254        return devno - 1;
 255}
 256
 257int board_mmc_getcd(struct mmc *mmc)
 258{
 259        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 260        int ret = 0;
 261
 262        switch (cfg->esdhc_base) {
 263        case USDHC2_BASE_ADDR:
 264                ret = !gpio_get_value(USDHC2_CD_GPIO);
 265                break;
 266        case USDHC3_BASE_ADDR:
 267                ret = !gpio_get_value(USDHC3_CD_GPIO);
 268                break;
 269        case USDHC4_BASE_ADDR:
 270                ret = 1; /* eMMC/uSDHC4 is always present */
 271                break;
 272        }
 273
 274        return ret;
 275}
 276
 277int board_mmc_init(bd_t *bis)
 278{
 279#ifndef CONFIG_SPL_BUILD
 280        int ret;
 281        int i;
 282
 283        /*
 284         * According to the board_mmc_init() the following map is done:
 285         * (U-Boot device node)    (Physical Port)
 286         * mmc0                    SD2
 287         * mmc1                    SD3
 288         * mmc2                    eMMC
 289         */
 290        for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
 291                switch (i) {
 292                case 0:
 293                        imx_iomux_v3_setup_multiple_pads(
 294                                usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
 295                        gpio_direction_input(USDHC2_CD_GPIO);
 296                        usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
 297                        break;
 298                case 1:
 299                        imx_iomux_v3_setup_multiple_pads(
 300                                usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
 301                        gpio_direction_input(USDHC3_CD_GPIO);
 302                        usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
 303                        break;
 304                case 2:
 305                        imx_iomux_v3_setup_multiple_pads(
 306                                usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
 307                        usdhc_cfg[2].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
 308                        break;
 309                default:
 310                        printf("Warning: you configured more USDHC controllers"
 311                               "(%d) then supported by the board (%d)\n",
 312                               i + 1, CONFIG_SYS_FSL_USDHC_NUM);
 313                        return -EINVAL;
 314                }
 315
 316                ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
 317                if (ret)
 318                        return ret;
 319        }
 320
 321        return 0;
 322#else
 323        struct src *psrc = (struct src *)SRC_BASE_ADDR;
 324        unsigned reg = readl(&psrc->sbmr1) >> 11;
 325        /*
 326         * Upon reading BOOT_CFG register the following map is done:
 327         * Bit 11 and 12 of BOOT_CFG register can determine the current
 328         * mmc port
 329         * 0x1                  SD1
 330         * 0x2                  SD2
 331         * 0x3                  SD4
 332         */
 333
 334        switch (reg & 0x3) {
 335        case 0x1:
 336                imx_iomux_v3_setup_multiple_pads(
 337                        usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
 338                usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR;
 339                usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
 340                gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
 341                break;
 342        case 0x2:
 343                imx_iomux_v3_setup_multiple_pads(
 344                        usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
 345                usdhc_cfg[0].esdhc_base = USDHC3_BASE_ADDR;
 346                usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
 347                gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
 348                break;
 349        case 0x3:
 350                imx_iomux_v3_setup_multiple_pads(
 351                        usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
 352                usdhc_cfg[0].esdhc_base = USDHC4_BASE_ADDR;
 353                usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
 354                gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
 355                break;
 356        }
 357
 358        return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
 359#endif
 360}
 361#endif
 362
 363#if defined(CONFIG_VIDEO_IPUV3)
 364static void disable_lvds(struct display_info_t const *dev)
 365{
 366        struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
 367
 368        int reg = readl(&iomux->gpr[2]);
 369
 370        reg &= ~(IOMUXC_GPR2_LVDS_CH0_MODE_MASK |
 371                 IOMUXC_GPR2_LVDS_CH1_MODE_MASK);
 372
 373        writel(reg, &iomux->gpr[2]);
 374}
 375
 376static void do_enable_hdmi(struct display_info_t const *dev)
 377{
 378        disable_lvds(dev);
 379        imx_enable_hdmi_phy();
 380}
 381
 382struct display_info_t const displays[] = {{
 383        .bus    = -1,
 384        .addr   = 0,
 385        .pixfmt = IPU_PIX_FMT_RGB666,
 386        .detect = NULL,
 387        .enable = enable_lvds,
 388        .mode   = {
 389                .name           = "Hannstar-XGA",
 390                .refresh        = 60,
 391                .xres           = 1024,
 392                .yres           = 768,
 393                .pixclock       = 15384,
 394                .left_margin    = 160,
 395                .right_margin   = 24,
 396                .upper_margin   = 29,
 397                .lower_margin   = 3,
 398                .hsync_len      = 136,
 399                .vsync_len      = 6,
 400                .sync           = FB_SYNC_EXT,
 401                .vmode          = FB_VMODE_NONINTERLACED
 402} }, {
 403        .bus    = -1,
 404        .addr   = 0,
 405        .pixfmt = IPU_PIX_FMT_RGB24,
 406        .detect = detect_hdmi,
 407        .enable = do_enable_hdmi,
 408        .mode   = {
 409                .name           = "HDMI",
 410                .refresh        = 60,
 411                .xres           = 1024,
 412                .yres           = 768,
 413                .pixclock       = 15384,
 414                .left_margin    = 160,
 415                .right_margin   = 24,
 416                .upper_margin   = 29,
 417                .lower_margin   = 3,
 418                .hsync_len      = 136,
 419                .vsync_len      = 6,
 420                .sync           = FB_SYNC_EXT,
 421                .vmode          = FB_VMODE_NONINTERLACED
 422} }, {
 423        .bus    = 0,
 424        .addr   = 0,
 425        .pixfmt = IPU_PIX_FMT_RGB24,
 426        .detect = NULL,
 427        .enable = enable_rgb,
 428        .mode   = {
 429                .name           = "SEIKO-WVGA",
 430                .refresh        = 60,
 431                .xres           = 800,
 432                .yres           = 480,
 433                .pixclock       = 29850,
 434                .left_margin    = 89,
 435                .right_margin   = 164,
 436                .upper_margin   = 23,
 437                .lower_margin   = 10,
 438                .hsync_len      = 10,
 439                .vsync_len      = 10,
 440                .sync           = 0,
 441                .vmode          = FB_VMODE_NONINTERLACED
 442} } };
 443size_t display_count = ARRAY_SIZE(displays);
 444
 445static void setup_display(void)
 446{
 447        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 448        struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
 449        int reg;
 450
 451        /* Setup HSYNC, VSYNC, DISP_CLK for debugging purposes */
 452        imx_iomux_v3_setup_multiple_pads(di0_pads, ARRAY_SIZE(di0_pads));
 453
 454        enable_ipu_clock();
 455        imx_setup_hdmi();
 456
 457        /* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */
 458        reg = readl(&mxc_ccm->CCGR3);
 459        reg |=  MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK;
 460        writel(reg, &mxc_ccm->CCGR3);
 461
 462        /* set LDB0, LDB1 clk select to 011/011 */
 463        reg = readl(&mxc_ccm->cs2cdr);
 464        reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
 465                 | MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
 466        reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
 467              | (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
 468        writel(reg, &mxc_ccm->cs2cdr);
 469
 470        reg = readl(&mxc_ccm->cscmr2);
 471        reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
 472        writel(reg, &mxc_ccm->cscmr2);
 473
 474        reg = readl(&mxc_ccm->chsccdr);
 475        reg |= (CHSCCDR_CLK_SEL_LDB_DI0
 476                << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
 477        reg |= (CHSCCDR_CLK_SEL_LDB_DI0
 478                << MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET);
 479        writel(reg, &mxc_ccm->chsccdr);
 480
 481        reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
 482             | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW
 483             | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
 484             | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
 485             | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
 486             | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
 487             | IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
 488             | IOMUXC_GPR2_LVDS_CH0_MODE_DISABLED
 489             | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0;
 490        writel(reg, &iomux->gpr[2]);
 491
 492        reg = readl(&iomux->gpr[3]);
 493        reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK
 494                        | IOMUXC_GPR3_HDMI_MUX_CTL_MASK))
 495            | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
 496               << IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
 497        writel(reg, &iomux->gpr[3]);
 498}
 499#endif /* CONFIG_VIDEO_IPUV3 */
 500
 501/*
 502 * Do not overwrite the console
 503 * Use always serial for U-Boot console
 504 */
 505int overwrite_console(void)
 506{
 507        return 1;
 508}
 509
 510int board_eth_init(bd_t *bis)
 511{
 512        setup_iomux_enet();
 513        setup_pcie();
 514
 515        return cpu_eth_init(bis);
 516}
 517
 518#ifdef CONFIG_USB_EHCI_MX6
 519#define USB_OTHERREGS_OFFSET    0x800
 520#define UCTRL_PWR_POL           (1 << 9)
 521
 522static iomux_v3_cfg_t const usb_otg_pads[] = {
 523        MX6_PAD_EIM_D22__USB_OTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
 524        MX6_PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
 525};
 526
 527static iomux_v3_cfg_t const usb_hc1_pads[] = {
 528        MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
 529};
 530
 531static void setup_usb(void)
 532{
 533        imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
 534                                         ARRAY_SIZE(usb_otg_pads));
 535
 536        /*
 537         * set daisy chain for otg_pin_id on 6q.
 538         * for 6dl, this bit is reserved
 539         */
 540        imx_iomux_set_gpr_register(1, 13, 1, 0);
 541
 542        imx_iomux_v3_setup_multiple_pads(usb_hc1_pads,
 543                                         ARRAY_SIZE(usb_hc1_pads));
 544}
 545
 546int board_ehci_hcd_init(int port)
 547{
 548        u32 *usbnc_usb_ctrl;
 549
 550        if (port > 1)
 551                return -EINVAL;
 552
 553        usbnc_usb_ctrl = (u32 *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET +
 554                                 port * 4);
 555
 556        setbits_le32(usbnc_usb_ctrl, UCTRL_PWR_POL);
 557
 558        return 0;
 559}
 560
 561int board_ehci_power(int port, int on)
 562{
 563        switch (port) {
 564        case 0:
 565                break;
 566        case 1:
 567                if (on)
 568                        gpio_direction_output(IMX_GPIO_NR(1, 29), 1);
 569                else
 570                        gpio_direction_output(IMX_GPIO_NR(1, 29), 0);
 571                break;
 572        default:
 573                printf("MXC USB port %d not yet supported\n", port);
 574                return -EINVAL;
 575        }
 576
 577        return 0;
 578}
 579#endif
 580
 581int board_early_init_f(void)
 582{
 583        setup_iomux_uart();
 584#if defined(CONFIG_VIDEO_IPUV3)
 585        setup_display();
 586#endif
 587
 588        return 0;
 589}
 590
 591int board_init(void)
 592{
 593        /* address of boot parameters */
 594        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 595
 596#ifdef CONFIG_MXC_SPI
 597        setup_spi();
 598#endif
 599        setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
 600
 601#ifdef CONFIG_USB_EHCI_MX6
 602        setup_usb();
 603#endif
 604
 605        return 0;
 606}
 607
 608int power_init_board(void)
 609{
 610        struct pmic *p;
 611        unsigned int reg;
 612        int ret;
 613
 614        p = pfuze_common_init(I2C_PMIC);
 615        if (!p)
 616                return -ENODEV;
 617
 618        ret = pfuze_mode_init(p, APS_PFM);
 619        if (ret < 0)
 620                return ret;
 621
 622        /* Increase VGEN3 from 2.5 to 2.8V */
 623        pmic_reg_read(p, PFUZE100_VGEN3VOL, &reg);
 624        reg &= ~LDO_VOL_MASK;
 625        reg |= LDOB_2_80V;
 626        pmic_reg_write(p, PFUZE100_VGEN3VOL, reg);
 627
 628        /* Increase VGEN5 from 2.8 to 3V */
 629        pmic_reg_read(p, PFUZE100_VGEN5VOL, &reg);
 630        reg &= ~LDO_VOL_MASK;
 631        reg |= LDOB_3_00V;
 632        pmic_reg_write(p, PFUZE100_VGEN5VOL, reg);
 633
 634        return 0;
 635}
 636
 637#ifdef CONFIG_MXC_SPI
 638int board_spi_cs_gpio(unsigned bus, unsigned cs)
 639{
 640        return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(4, 9)) : -1;
 641}
 642#endif
 643
 644#ifdef CONFIG_CMD_BMODE
 645static const struct boot_mode board_boot_modes[] = {
 646        /* 4 bit bus width */
 647        {"sd2",  MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
 648        {"sd3",  MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
 649        /* 8 bit bus width */
 650        {"emmc", MAKE_CFGVAL(0x60, 0x58, 0x00, 0x00)},
 651        {NULL,   0},
 652};
 653#endif
 654
 655int board_late_init(void)
 656{
 657#ifdef CONFIG_CMD_BMODE
 658        add_board_boot_modes(board_boot_modes);
 659#endif
 660
 661#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 662        setenv("board_name", "SABRESD");
 663
 664        if (is_mx6dqp())
 665                setenv("board_rev", "MX6QP");
 666        else if (is_mx6dq())
 667                setenv("board_rev", "MX6Q");
 668        else if (is_mx6sdl())
 669                setenv("board_rev", "MX6DL");
 670#endif
 671
 672        return 0;
 673}
 674
 675int checkboard(void)
 676{
 677        puts("Board: MX6-SabreSD\n");
 678        return 0;
 679}
 680
 681#ifdef CONFIG_SPL_BUILD
 682#include <spl.h>
 683#include <libfdt.h>
 684
 685const struct mx6dq_iomux_ddr_regs mx6_ddr_ioregs = {
 686        .dram_sdclk_0 =  0x00020030,
 687        .dram_sdclk_1 =  0x00020030,
 688        .dram_cas =  0x00020030,
 689        .dram_ras =  0x00020030,
 690        .dram_reset =  0x00020030,
 691        .dram_sdcke0 =  0x00003000,
 692        .dram_sdcke1 =  0x00003000,
 693        .dram_sdba2 =  0x00000000,
 694        .dram_sdodt0 =  0x00003030,
 695        .dram_sdodt1 =  0x00003030,
 696        .dram_sdqs0 =  0x00000030,
 697        .dram_sdqs1 =  0x00000030,
 698        .dram_sdqs2 =  0x00000030,
 699        .dram_sdqs3 =  0x00000030,
 700        .dram_sdqs4 =  0x00000030,
 701        .dram_sdqs5 =  0x00000030,
 702        .dram_sdqs6 =  0x00000030,
 703        .dram_sdqs7 =  0x00000030,
 704        .dram_dqm0 =  0x00020030,
 705        .dram_dqm1 =  0x00020030,
 706        .dram_dqm2 =  0x00020030,
 707        .dram_dqm3 =  0x00020030,
 708        .dram_dqm4 =  0x00020030,
 709        .dram_dqm5 =  0x00020030,
 710        .dram_dqm6 =  0x00020030,
 711        .dram_dqm7 =  0x00020030,
 712};
 713
 714const struct mx6dq_iomux_ddr_regs mx6dqp_ddr_ioregs = {
 715        .dram_sdclk_0 =  0x00000030,
 716        .dram_sdclk_1 =  0x00000030,
 717        .dram_cas =  0x00000030,
 718        .dram_ras =  0x00000030,
 719        .dram_reset =  0x00000030,
 720        .dram_sdcke0 =  0x00003000,
 721        .dram_sdcke1 =  0x00003000,
 722        .dram_sdba2 =  0x00000000,
 723        .dram_sdodt0 =  0x00003030,
 724        .dram_sdodt1 =  0x00003030,
 725        .dram_sdqs0 =  0x00000030,
 726        .dram_sdqs1 =  0x00000030,
 727        .dram_sdqs2 =  0x00000030,
 728        .dram_sdqs3 =  0x00000030,
 729        .dram_sdqs4 =  0x00000030,
 730        .dram_sdqs5 =  0x00000030,
 731        .dram_sdqs6 =  0x00000030,
 732        .dram_sdqs7 =  0x00000030,
 733        .dram_dqm0 =  0x00000030,
 734        .dram_dqm1 =  0x00000030,
 735        .dram_dqm2 =  0x00000030,
 736        .dram_dqm3 =  0x00000030,
 737        .dram_dqm4 =  0x00000030,
 738        .dram_dqm5 =  0x00000030,
 739        .dram_dqm6 =  0x00000030,
 740        .dram_dqm7 =  0x00000030,
 741};
 742
 743const struct mx6dq_iomux_grp_regs mx6_grp_ioregs = {
 744        .grp_ddr_type =  0x000C0000,
 745        .grp_ddrmode_ctl =  0x00020000,
 746        .grp_ddrpke =  0x00000000,
 747        .grp_addds =  0x00000030,
 748        .grp_ctlds =  0x00000030,
 749        .grp_ddrmode =  0x00020000,
 750        .grp_b0ds =  0x00000030,
 751        .grp_b1ds =  0x00000030,
 752        .grp_b2ds =  0x00000030,
 753        .grp_b3ds =  0x00000030,
 754        .grp_b4ds =  0x00000030,
 755        .grp_b5ds =  0x00000030,
 756        .grp_b6ds =  0x00000030,
 757        .grp_b7ds =  0x00000030,
 758};
 759
 760const struct mx6_mmdc_calibration mx6_mmcd_calib = {
 761        .p0_mpwldectrl0 =  0x001F001F,
 762        .p0_mpwldectrl1 =  0x001F001F,
 763        .p1_mpwldectrl0 =  0x00440044,
 764        .p1_mpwldectrl1 =  0x00440044,
 765        .p0_mpdgctrl0 =  0x434B0350,
 766        .p0_mpdgctrl1 =  0x034C0359,
 767        .p1_mpdgctrl0 =  0x434B0350,
 768        .p1_mpdgctrl1 =  0x03650348,
 769        .p0_mprddlctl =  0x4436383B,
 770        .p1_mprddlctl =  0x39393341,
 771        .p0_mpwrdlctl =  0x35373933,
 772        .p1_mpwrdlctl =  0x48254A36,
 773};
 774
 775const struct mx6_mmdc_calibration mx6dqp_mmcd_calib = {
 776        .p0_mpwldectrl0 =  0x001B001E,
 777        .p0_mpwldectrl1 =  0x002E0029,
 778        .p1_mpwldectrl0 =  0x001B002A,
 779        .p1_mpwldectrl1 =  0x0019002C,
 780        .p0_mpdgctrl0 =  0x43240334,
 781        .p0_mpdgctrl1 =  0x0324031A,
 782        .p1_mpdgctrl0 =  0x43340344,
 783        .p1_mpdgctrl1 =  0x03280276,
 784        .p0_mprddlctl =  0x44383A3E,
 785        .p1_mprddlctl =  0x3C3C3846,
 786        .p0_mpwrdlctl =  0x2E303230,
 787        .p1_mpwrdlctl =  0x38283E34,
 788};
 789
 790/* MT41K128M16JT-125 */
 791static struct mx6_ddr3_cfg mem_ddr = {
 792        .mem_speed = 1600,
 793        .density = 2,
 794        .width = 16,
 795        .banks = 8,
 796        .rowaddr = 14,
 797        .coladdr = 10,
 798        .pagesz = 2,
 799        .trcd = 1375,
 800        .trcmin = 4875,
 801        .trasmin = 3500,
 802};
 803
 804static void ccgr_init(void)
 805{
 806        struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 807
 808        writel(0x00C03F3F, &ccm->CCGR0);
 809        writel(0x0030FC03, &ccm->CCGR1);
 810        writel(0x0FFFC000, &ccm->CCGR2);
 811        writel(0x3FF00000, &ccm->CCGR3);
 812        writel(0x00FFF300, &ccm->CCGR4);
 813        writel(0x0F0000C3, &ccm->CCGR5);
 814        writel(0x000003FF, &ccm->CCGR6);
 815}
 816
 817static void gpr_init(void)
 818{
 819        struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
 820
 821        /* enable AXI cache for VDOA/VPU/IPU */
 822        writel(0xF00000CF, &iomux->gpr[4]);
 823        if (is_mx6dqp()) {
 824                /* set IPU AXI-id1 Qos=0x1 AXI-id0/2/3 Qos=0x7 */
 825                writel(0x007F007F, &iomux->gpr[6]);
 826                writel(0x007F007F, &iomux->gpr[7]);
 827        } else {
 828                /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */
 829                writel(0x007F007F, &iomux->gpr[6]);
 830                writel(0x007F007F, &iomux->gpr[7]);
 831        }
 832}
 833
 834/*
 835 * This section requires the differentiation between iMX6 Sabre boards, but
 836 * for now, it will configure only for the mx6q variant.
 837 */
 838static void spl_dram_init(void)
 839{
 840        struct mx6_ddr_sysinfo sysinfo = {
 841                /* width of data bus:0=16,1=32,2=64 */
 842                .dsize = 2,
 843                /* config for full 4GB range so that get_mem_size() works */
 844                .cs_density = 32, /* 32Gb per CS */
 845                /* single chip select */
 846                .ncs = 1,
 847                .cs1_mirror = 0,
 848                .rtt_wr = 1 /*DDR3_RTT_60_OHM*/,        /* RTT_Wr = RZQ/4 */
 849                .rtt_nom = 1 /*DDR3_RTT_60_OHM*/,       /* RTT_Nom = RZQ/4 */
 850                .walat = 1,     /* Write additional latency */
 851                .ralat = 5,     /* Read additional latency */
 852                .mif3_mode = 3, /* Command prediction working mode */
 853                .bi_on = 1,     /* Bank interleaving enabled */
 854                .sde_to_rst = 0x10,     /* 14 cycles, 200us (JEDEC default) */
 855                .rst_to_cke = 0x23,     /* 33 cycles, 500us (JEDEC default) */
 856                .ddr_type = DDR_TYPE_DDR3,
 857        };
 858
 859        if (is_mx6dqp()) {
 860                mx6dq_dram_iocfg(64, &mx6dqp_ddr_ioregs, &mx6_grp_ioregs);
 861                mx6_dram_cfg(&sysinfo, &mx6dqp_mmcd_calib, &mem_ddr);
 862        } else {
 863                mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs);
 864                mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, &mem_ddr);
 865        }
 866}
 867
 868void board_init_f(ulong dummy)
 869{
 870        /* setup AIPS and disable watchdog */
 871        arch_cpu_init();
 872
 873        ccgr_init();
 874        gpr_init();
 875
 876        /* iomux and setup of i2c */
 877        board_early_init_f();
 878
 879        /* setup GP timer */
 880        timer_init();
 881
 882        /* UART clocks enabled and gd valid - init serial console */
 883        preloader_console_init();
 884
 885        /* DDR initialization */
 886        spl_dram_init();
 887
 888        /* Clear the BSS. */
 889        memset(__bss_start, 0, __bss_end - __bss_start);
 890
 891        /* load/boot image from boot device */
 892        board_init_r(NULL, 0);
 893}
 894#endif
 895