uboot/board/solidrun/mx6cuboxi/mx6cuboxi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2015 Freescale Semiconductor, Inc.
   4 *
   5 * Author: Fabio Estevam <fabio.estevam@freescale.com>
   6 *
   7 * Copyright (C) 2013 Jon Nettleton <jon.nettleton@gmail.com>
   8 *
   9 * Based on SPL code from Solidrun tree, which is:
  10 * Author: Tungyi Lin <tungyilin1127@gmail.com>
  11 *
  12 * Derived from EDM_CF_IMX6 code by TechNexion,Inc
  13 * Ported to SolidRun microSOM by Rabeeh Khoury <rabeeh@solid-run.com>
  14 */
  15
  16#include <common.h>
  17#include <image.h>
  18#include <init.h>
  19#include <log.h>
  20#include <asm/arch/clock.h>
  21#include <asm/arch/imx-regs.h>
  22#include <asm/arch/iomux.h>
  23#include <asm/arch/mx6-pins.h>
  24#include <asm/arch/mxc_hdmi.h>
  25#include <env.h>
  26#include <linux/delay.h>
  27#include <linux/errno.h>
  28#include <asm/gpio.h>
  29#include <asm/mach-imx/iomux-v3.h>
  30#include <asm/mach-imx/sata.h>
  31#include <asm/mach-imx/video.h>
  32#include <mmc.h>
  33#include <fsl_esdhc_imx.h>
  34#include <malloc.h>
  35#include <asm/arch/crm_regs.h>
  36#include <asm/io.h>
  37#include <asm/arch/sys_proto.h>
  38#include <spl.h>
  39#include <usb.h>
  40#include <usb/ehci-ci.h>
  41
  42DECLARE_GLOBAL_DATA_PTR;
  43
  44#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |                   \
  45        PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |                 \
  46        PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
  47
  48#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |                    \
  49        PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |                 \
  50        PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
  51
  52#define USB_H1_VBUS     IMX_GPIO_NR(1, 0)
  53
  54enum board_type {
  55        CUBOXI          = 0x00,
  56        HUMMINGBOARD    = 0x01,
  57        HUMMINGBOARD2   = 0x02,
  58        UNKNOWN         = 0x03,
  59};
  60
  61static struct gpio_desc board_detect_desc[5];
  62
  63#define MEM_STRIDE 0x4000000
  64static u32 get_ram_size_stride_test(u32 *base, u32 maxsize)
  65{
  66        volatile u32 *addr;
  67        u32          save[64];
  68        u32          cnt;
  69        u32          size;
  70        int          i = 0;
  71
  72        /* First save the data */
  73        for (cnt = 0; cnt < maxsize; cnt += MEM_STRIDE) {
  74                addr = (volatile u32 *)((u32)base + cnt);       /* pointer arith! */
  75                sync ();
  76                save[i++] = *addr;
  77                sync ();
  78        }
  79
  80        /* First write a signature */
  81        * (volatile u32 *)base = 0x12345678;
  82        for (size = MEM_STRIDE; size < maxsize; size += MEM_STRIDE) {
  83                * (volatile u32 *)((u32)base + size) = size;
  84                sync ();
  85                if (* (volatile u32 *)((u32)base) == size) {    /* We reached the overlapping address */
  86                        break;
  87                }
  88        }
  89
  90        /* Restore the data */
  91        for (cnt = (maxsize - MEM_STRIDE); i > 0; cnt -= MEM_STRIDE) {
  92                addr = (volatile u32 *)((u32)base + cnt);       /* pointer arith! */
  93                sync ();
  94                *addr = save[i--];
  95                sync ();
  96        }
  97
  98        return (size);
  99}
 100
 101int dram_init(void)
 102{
 103        u32 max_size = imx_ddr_size();
 104
 105        gd->ram_size = get_ram_size_stride_test((u32 *) CONFIG_SYS_SDRAM_BASE,
 106                                                (u32)max_size);
 107
 108        return 0;
 109}
 110
 111static iomux_v3_cfg_t const uart1_pads[] = {
 112        IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
 113        IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
 114};
 115
 116static iomux_v3_cfg_t const usdhc2_pads[] = {
 117        IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 118        IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 119        IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 120        IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 121        IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 122        IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 123};
 124
 125static iomux_v3_cfg_t const usdhc3_pads[] = {
 126        IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 127        IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 128        IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 129        IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 130        IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 131        IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 132        IOMUX_PADS(PAD_SD3_DAT4__SD3_DATA4      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 133        IOMUX_PADS(PAD_SD3_DAT5__SD3_DATA5      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 134        IOMUX_PADS(PAD_SD3_DAT6__SD3_DATA6      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 135        IOMUX_PADS(PAD_SD3_DAT7__SD3_DATA7      | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 136        IOMUX_PADS(PAD_SD3_RST__SD3_RESET       | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
 137};
 138
 139static iomux_v3_cfg_t const board_detect[] = {
 140        /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
 141        IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09  | MUX_PAD_CTRL(UART_PAD_CTRL)),
 142        IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04   | MUX_PAD_CTRL(UART_PAD_CTRL)),
 143        IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08  | MUX_PAD_CTRL(UART_PAD_CTRL)),
 144};
 145
 146static iomux_v3_cfg_t const som_rev_detect[] = {
 147        /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
 148        IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00  | MUX_PAD_CTRL(UART_PAD_CTRL)),
 149        IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04  | MUX_PAD_CTRL(UART_PAD_CTRL)),
 150};
 151
 152static void setup_iomux_uart(void)
 153{
 154        SETUP_IOMUX_PADS(uart1_pads);
 155}
 156
 157int board_mmc_get_env_dev(int devno)
 158{
 159        return devno;
 160}
 161
 162#ifdef CONFIG_VIDEO_IPUV3
 163static void do_enable_hdmi(struct display_info_t const *dev)
 164{
 165        imx_enable_hdmi_phy();
 166}
 167
 168struct display_info_t const displays[] = {
 169        {
 170                .bus    = -1,
 171                .addr   = 0,
 172                .pixfmt = IPU_PIX_FMT_RGB24,
 173                .detect = detect_hdmi,
 174                .enable = do_enable_hdmi,
 175                .mode   = {
 176                        .name           = "HDMI",
 177                        /* 1024x768@60Hz (VESA)*/
 178                        .refresh        = 60,
 179                        .xres           = 1024,
 180                        .yres           = 768,
 181                        .pixclock       = 15384,
 182                        .left_margin    = 160,
 183                        .right_margin   = 24,
 184                        .upper_margin   = 29,
 185                        .lower_margin   = 3,
 186                        .hsync_len      = 136,
 187                        .vsync_len      = 6,
 188                        .sync           = FB_SYNC_EXT,
 189                        .vmode          = FB_VMODE_NONINTERLACED
 190                }
 191        }
 192};
 193
 194size_t display_count = ARRAY_SIZE(displays);
 195
 196static int setup_display(void)
 197{
 198        struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 199        int reg;
 200        int timeout = 100000;
 201
 202        enable_ipu_clock();
 203        imx_setup_hdmi();
 204
 205        /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */
 206        setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
 207
 208        reg = readl(&ccm->analog_pll_video);
 209        reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT;
 210        reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37);
 211        reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT;
 212        reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1);
 213        writel(reg, &ccm->analog_pll_video);
 214
 215        writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
 216        writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
 217
 218        reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN;
 219        writel(reg, &ccm->analog_pll_video);
 220
 221        while (timeout--)
 222                if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
 223                        break;
 224        if (timeout < 0) {
 225                printf("Warning: video pll lock timeout!\n");
 226                return -ETIMEDOUT;
 227        }
 228
 229        reg = readl(&ccm->analog_pll_video);
 230        reg |= BM_ANADIG_PLL_VIDEO_ENABLE;
 231        reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS;
 232        writel(reg, &ccm->analog_pll_video);
 233
 234        /* gate ipu1_di0_clk */
 235        clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
 236
 237        /* select video_pll clock / 7  for ipu1_di0_clk -> 65MHz pixclock */
 238        reg = readl(&ccm->chsccdr);
 239        reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK |
 240                 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK |
 241                 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
 242        reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) |
 243               (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) |
 244               (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
 245        writel(reg, &ccm->chsccdr);
 246
 247        /* enable ipu1_di0_clk */
 248        setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
 249
 250        return 0;
 251}
 252#endif /* CONFIG_VIDEO_IPUV3 */
 253
 254static int setup_fec(void)
 255{
 256        struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
 257        int ret;
 258
 259        ret = enable_fec_anatop_clock(0, ENET_25MHZ);
 260        if (ret)
 261                return ret;
 262
 263        /* set gpr1[ENET_CLK_SEL] */
 264        setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
 265
 266        return 0;
 267}
 268
 269int board_early_init_f(void)
 270{
 271        setup_iomux_uart();
 272
 273#ifdef CONFIG_CMD_SATA
 274        setup_sata();
 275#endif
 276        setup_fec();
 277
 278        return 0;
 279}
 280
 281int board_init(void)
 282{
 283        int ret = 0;
 284
 285        /* address of boot parameters */
 286        gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
 287
 288#ifdef CONFIG_VIDEO_IPUV3
 289        ret = setup_display();
 290#endif
 291
 292        return ret;
 293}
 294
 295static int request_detect_gpios(void)
 296{
 297        int node;
 298        int ret;
 299
 300        node = fdt_node_offset_by_compatible(gd->fdt_blob, 0,
 301                "solidrun,hummingboard-detect");
 302        if (node < 0)
 303                return -ENODEV;
 304
 305        ret = gpio_request_list_by_name_nodev(offset_to_ofnode(node),
 306                "detect-gpios", board_detect_desc,
 307                ARRAY_SIZE(board_detect_desc), GPIOD_IS_IN);
 308
 309        return ret;
 310}
 311
 312static int free_detect_gpios(void)
 313{
 314        return gpio_free_list_nodev(board_detect_desc,
 315                ARRAY_SIZE(board_detect_desc));
 316}
 317
 318static enum board_type board_type(void)
 319{
 320        int val1, val2, val3;
 321
 322        SETUP_IOMUX_PADS(board_detect);
 323
 324        /*
 325         * Machine selection -
 326         * Machine      val1, val2, val3
 327         * ----------------------------
 328         * HB2            x     x    0
 329         * HB rev 3.x     x     0    x
 330         * CBi            0     1    x
 331         * HB             1     1    x
 332         */
 333
 334        gpio_direction_input(IMX_GPIO_NR(2, 8));
 335        val3 = gpio_get_value(IMX_GPIO_NR(2, 8));
 336
 337        if (val3 == 0)
 338                return HUMMINGBOARD2;
 339
 340        gpio_direction_input(IMX_GPIO_NR(3, 4));
 341        val2 = gpio_get_value(IMX_GPIO_NR(3, 4));
 342
 343        if (val2 == 0)
 344                return HUMMINGBOARD;
 345
 346        gpio_direction_input(IMX_GPIO_NR(4, 9));
 347        val1 = gpio_get_value(IMX_GPIO_NR(4, 9));
 348
 349        if (val1 == 0) {
 350                return CUBOXI;
 351        } else {
 352                return HUMMINGBOARD;
 353        }
 354}
 355
 356static bool is_rev_15_som(void)
 357{
 358        int val1, val2;
 359        SETUP_IOMUX_PADS(som_rev_detect);
 360
 361        val1 = gpio_get_value(IMX_GPIO_NR(6, 0));
 362        val2 = gpio_get_value(IMX_GPIO_NR(6, 4));
 363
 364        if (val1 == 1 && val2 == 0)
 365                return true;
 366
 367        return false;
 368}
 369
 370static bool has_emmc(void)
 371{
 372        struct mmc *mmc;
 373        mmc = find_mmc_device(2);
 374        if (!mmc)
 375                return 0;
 376        return (mmc_get_op_cond(mmc) < 0) ? 0 : 1;
 377}
 378
 379int checkboard(void)
 380{
 381        request_detect_gpios();
 382
 383        switch (board_type()) {
 384        case CUBOXI:
 385                puts("Board: MX6 Cubox-i");
 386                break;
 387        case HUMMINGBOARD:
 388                puts("Board: MX6 HummingBoard");
 389                break;
 390        case HUMMINGBOARD2:
 391                puts("Board: MX6 HummingBoard2");
 392                break;
 393        case UNKNOWN:
 394        default:
 395                puts("Board: Unknown\n");
 396                goto out;
 397        }
 398
 399        if (is_rev_15_som())
 400                puts(" (som rev 1.5)\n");
 401        else
 402                puts("\n");
 403
 404        free_detect_gpios();
 405out:
 406        return 0;
 407}
 408
 409/* Override the default implementation, DT model is not accurate */
 410int show_board_info(void)
 411{
 412        return checkboard();
 413}
 414
 415int board_late_init(void)
 416{
 417#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 418        request_detect_gpios();
 419
 420        switch (board_type()) {
 421        case CUBOXI:
 422                env_set("board_name", "CUBOXI");
 423                break;
 424        case HUMMINGBOARD:
 425                env_set("board_name", "HUMMINGBOARD");
 426                break;
 427        case HUMMINGBOARD2:
 428                env_set("board_name", "HUMMINGBOARD2");
 429                break;
 430        case UNKNOWN:
 431        default:
 432                env_set("board_name", "CUBOXI");
 433        }
 434
 435        if (is_mx6dq())
 436                env_set("board_rev", "MX6Q");
 437        else
 438                env_set("board_rev", "MX6DL");
 439
 440        if (is_rev_15_som())
 441                env_set("som_rev", "V15");
 442
 443        if (has_emmc())
 444                env_set("has_emmc", "yes");
 445
 446        free_detect_gpios();
 447#endif
 448
 449        return 0;
 450}
 451
 452/*
 453 * This is not a perfect match. Avoid dependency on the DM GPIO driver needed
 454 * for accurate board detection. Hummingboard2 DT is good enough for U-Boot on
 455 * all Hummingboard/Cubox-i platforms.
 456 */
 457int board_fit_config_name_match(const char *name)
 458{
 459        char tmp_name[36];
 460
 461        snprintf(tmp_name, sizeof(tmp_name), "%s-hummingboard2-emmc-som-v15",
 462                        is_mx6dq() ? "imx6q" : "imx6dl");
 463
 464        return strcmp(name, tmp_name);
 465}
 466
 467void board_boot_order(u32 *spl_boot_list)
 468{
 469        struct src *psrc = (struct src *)SRC_BASE_ADDR;
 470        unsigned int reg = readl(&psrc->sbmr1) >> 11;
 471        u32 boot_mode = imx6_src_get_boot_mode() & IMX6_BMODE_MASK;
 472        unsigned int bmode = readl(&src_base->sbmr2);
 473
 474        /* If bmode is serial or USB phy is active, return serial */
 475        if (((bmode >> 24) & 0x03) == 0x01 || is_usbotg_phy_active()) {
 476                spl_boot_list[0] = BOOT_DEVICE_BOARD;
 477                return;
 478        }
 479
 480        switch (boot_mode >> IMX6_BMODE_SHIFT) {
 481        case IMX6_BMODE_SD:
 482        case IMX6_BMODE_ESD:
 483        case IMX6_BMODE_MMC:
 484        case IMX6_BMODE_EMMC:
 485                /*
 486                 * Upon reading BOOT_CFG register the following map is done:
 487                 * Bit 11 and 12 of BOOT_CFG register can determine the current
 488                 * mmc port
 489                 * 0x1                  SD2
 490                 * 0x2                  SD3
 491                 */
 492
 493                reg &= 0x3; /* Only care about bottom 2 bits */
 494                switch (reg) {
 495                case 1:
 496                        SETUP_IOMUX_PADS(usdhc2_pads);
 497                        spl_boot_list[0] = BOOT_DEVICE_MMC1;
 498                        break;
 499                case 2:
 500                        SETUP_IOMUX_PADS(usdhc3_pads);
 501                        spl_boot_list[0] = BOOT_DEVICE_MMC2;
 502                        break;
 503                }
 504                break;
 505        default:
 506                /* By default use USB downloader */
 507                spl_boot_list[0] = BOOT_DEVICE_BOARD;
 508                break;
 509        }
 510
 511        /* As a last resort, use serial downloader */
 512        spl_boot_list[1] = BOOT_DEVICE_BOARD;
 513}
 514
 515#ifdef CONFIG_SPL_BUILD
 516#include <asm/arch/mx6-ddr.h>
 517static const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = {
 518        .dram_sdclk_0 =  0x00020030,
 519        .dram_sdclk_1 =  0x00020030,
 520        .dram_cas =  0x00020030,
 521        .dram_ras =  0x00020030,
 522        .dram_reset =  0x000c0030,
 523        .dram_sdcke0 =  0x00003000,
 524        .dram_sdcke1 =  0x00003000,
 525        .dram_sdba2 =  0x00000000,
 526        .dram_sdodt0 =  0x00003030,
 527        .dram_sdodt1 =  0x00003030,
 528        .dram_sdqs0 =  0x00000030,
 529        .dram_sdqs1 =  0x00000030,
 530        .dram_sdqs2 =  0x00000030,
 531        .dram_sdqs3 =  0x00000030,
 532        .dram_sdqs4 =  0x00000030,
 533        .dram_sdqs5 =  0x00000030,
 534        .dram_sdqs6 =  0x00000030,
 535        .dram_sdqs7 =  0x00000030,
 536        .dram_dqm0 =  0x00020030,
 537        .dram_dqm1 =  0x00020030,
 538        .dram_dqm2 =  0x00020030,
 539        .dram_dqm3 =  0x00020030,
 540        .dram_dqm4 =  0x00020030,
 541        .dram_dqm5 =  0x00020030,
 542        .dram_dqm6 =  0x00020030,
 543        .dram_dqm7 =  0x00020030,
 544};
 545
 546static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = {
 547        .dram_sdclk_0 = 0x00000028,
 548        .dram_sdclk_1 = 0x00000028,
 549        .dram_cas =     0x00000028,
 550        .dram_ras =     0x00000028,
 551        .dram_reset =   0x000c0028,
 552        .dram_sdcke0 =  0x00003000,
 553        .dram_sdcke1 =  0x00003000,
 554        .dram_sdba2 =   0x00000000,
 555        .dram_sdodt0 =  0x00003030,
 556        .dram_sdodt1 =  0x00003030,
 557        .dram_sdqs0 =   0x00000028,
 558        .dram_sdqs1 =   0x00000028,
 559        .dram_sdqs2 =   0x00000028,
 560        .dram_sdqs3 =   0x00000028,
 561        .dram_sdqs4 =   0x00000028,
 562        .dram_sdqs5 =   0x00000028,
 563        .dram_sdqs6 =   0x00000028,
 564        .dram_sdqs7 =   0x00000028,
 565        .dram_dqm0 =    0x00000028,
 566        .dram_dqm1 =    0x00000028,
 567        .dram_dqm2 =    0x00000028,
 568        .dram_dqm3 =    0x00000028,
 569        .dram_dqm4 =    0x00000028,
 570        .dram_dqm5 =    0x00000028,
 571        .dram_dqm6 =    0x00000028,
 572        .dram_dqm7 =    0x00000028,
 573};
 574
 575static const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = {
 576        .grp_ddr_type =  0x000C0000,
 577        .grp_ddrmode_ctl =  0x00020000,
 578        .grp_ddrpke =  0x00000000,
 579        .grp_addds =  0x00000030,
 580        .grp_ctlds =  0x00000030,
 581        .grp_ddrmode =  0x00020000,
 582        .grp_b0ds =  0x00000030,
 583        .grp_b1ds =  0x00000030,
 584        .grp_b2ds =  0x00000030,
 585        .grp_b3ds =  0x00000030,
 586        .grp_b4ds =  0x00000030,
 587        .grp_b5ds =  0x00000030,
 588        .grp_b6ds =  0x00000030,
 589        .grp_b7ds =  0x00000030,
 590};
 591
 592static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
 593        .grp_ddr_type = 0x000c0000,
 594        .grp_ddrmode_ctl = 0x00020000,
 595        .grp_ddrpke = 0x00000000,
 596        .grp_addds = 0x00000028,
 597        .grp_ctlds = 0x00000028,
 598        .grp_ddrmode = 0x00020000,
 599        .grp_b0ds = 0x00000028,
 600        .grp_b1ds = 0x00000028,
 601        .grp_b2ds = 0x00000028,
 602        .grp_b3ds = 0x00000028,
 603        .grp_b4ds = 0x00000028,
 604        .grp_b5ds = 0x00000028,
 605        .grp_b6ds = 0x00000028,
 606        .grp_b7ds = 0x00000028,
 607};
 608
 609/* microSOM with Dual processor and 1GB memory */
 610static const struct mx6_mmdc_calibration mx6q_1g_mmcd_calib = {
 611        .p0_mpwldectrl0 =  0x00000000,
 612        .p0_mpwldectrl1 =  0x00000000,
 613        .p1_mpwldectrl0 =  0x00000000,
 614        .p1_mpwldectrl1 =  0x00000000,
 615        .p0_mpdgctrl0 =    0x0314031c,
 616        .p0_mpdgctrl1 =    0x023e0304,
 617        .p1_mpdgctrl0 =    0x03240330,
 618        .p1_mpdgctrl1 =    0x03180260,
 619        .p0_mprddlctl =    0x3630323c,
 620        .p1_mprddlctl =    0x3436283a,
 621        .p0_mpwrdlctl =    0x36344038,
 622        .p1_mpwrdlctl =    0x422a423c,
 623};
 624
 625/* microSOM with Quad processor and 2GB memory */
 626static const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = {
 627        .p0_mpwldectrl0 =  0x00000000,
 628        .p0_mpwldectrl1 =  0x00000000,
 629        .p1_mpwldectrl0 =  0x00000000,
 630        .p1_mpwldectrl1 =  0x00000000,
 631        .p0_mpdgctrl0 =    0x0314031c,
 632        .p0_mpdgctrl1 =    0x023e0304,
 633        .p1_mpdgctrl0 =    0x03240330,
 634        .p1_mpdgctrl1 =    0x03180260,
 635        .p0_mprddlctl =    0x3630323c,
 636        .p1_mprddlctl =    0x3436283a,
 637        .p0_mpwrdlctl =    0x36344038,
 638        .p1_mpwrdlctl =    0x422a423c,
 639};
 640
 641/* microSOM with Solo processor and 512MB memory */
 642static const struct mx6_mmdc_calibration mx6dl_512m_mmcd_calib = {
 643        .p0_mpwldectrl0 = 0x0045004D,
 644        .p0_mpwldectrl1 = 0x003A0047,
 645        .p0_mpdgctrl0 =   0x023C0224,
 646        .p0_mpdgctrl1 =   0x02000220,
 647        .p0_mprddlctl =   0x44444846,
 648        .p0_mpwrdlctl =   0x32343032,
 649};
 650
 651/* microSOM with Dual lite processor and 1GB memory */
 652static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib = {
 653        .p0_mpwldectrl0 =  0x0045004D,
 654        .p0_mpwldectrl1 =  0x003A0047,
 655        .p1_mpwldectrl0 =  0x001F001F,
 656        .p1_mpwldectrl1 =  0x00210035,
 657        .p0_mpdgctrl0 =    0x023C0224,
 658        .p0_mpdgctrl1 =    0x02000220,
 659        .p1_mpdgctrl0 =    0x02200220,
 660        .p1_mpdgctrl1 =    0x02040208,
 661        .p0_mprddlctl =    0x44444846,
 662        .p1_mprddlctl =    0x4042463C,
 663        .p0_mpwrdlctl =    0x32343032,
 664        .p1_mpwrdlctl =    0x36363430,
 665};
 666
 667static struct mx6_ddr3_cfg mem_ddr_2g = {
 668        .mem_speed = 1600,
 669        .density   = 2,
 670        .width     = 16,
 671        .banks     = 8,
 672        .rowaddr   = 14,
 673        .coladdr   = 10,
 674        .pagesz    = 2,
 675        .trcd      = 1375,
 676        .trcmin    = 4875,
 677        .trasmin   = 3500,
 678};
 679
 680static struct mx6_ddr3_cfg mem_ddr_4g = {
 681        .mem_speed = 1600,
 682        .density = 4,
 683        .width = 16,
 684        .banks = 8,
 685        .rowaddr = 16,
 686        .coladdr = 10,
 687        .pagesz = 2,
 688        .trcd = 1375,
 689        .trcmin = 4875,
 690        .trasmin = 3500,
 691};
 692
 693static void ccgr_init(void)
 694{
 695        struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 696
 697        writel(0x00C03F3F, &ccm->CCGR0);
 698        writel(0x0030FC03, &ccm->CCGR1);
 699        writel(0x0FFFC000, &ccm->CCGR2);
 700        writel(0x3FF00000, &ccm->CCGR3);
 701        writel(0x00FFF300, &ccm->CCGR4);
 702        writel(0x0F0000C3, &ccm->CCGR5);
 703        writel(0x000003FF, &ccm->CCGR6);
 704}
 705
 706static void spl_dram_init(int width)
 707{
 708        struct mx6_ddr_sysinfo sysinfo = {
 709                /* width of data bus: 0=16, 1=32, 2=64 */
 710                .dsize = width / 32,
 711                /* config for full 4GB range so that get_mem_size() works */
 712                .cs_density = 32,       /* 32Gb per CS */
 713                .ncs = 1,               /* single chip select */
 714                .cs1_mirror = 0,
 715                .rtt_wr = 1 /*DDR3_RTT_60_OHM*/,        /* RTT_Wr = RZQ/4 */
 716                .rtt_nom = 1 /*DDR3_RTT_60_OHM*/,       /* RTT_Nom = RZQ/4 */
 717                .walat = 1,     /* Write additional latency */
 718                .ralat = 5,     /* Read additional latency */
 719                .mif3_mode = 3, /* Command prediction working mode */
 720                .bi_on = 1,     /* Bank interleaving enabled */
 721                .sde_to_rst = 0x10,     /* 14 cycles, 200us (JEDEC default) */
 722                .rst_to_cke = 0x23,     /* 33 cycles, 500us (JEDEC default) */
 723                .ddr_type = DDR_TYPE_DDR3,
 724                .refsel = 1,    /* Refresh cycles at 32KHz */
 725                .refr = 7,      /* 8 refresh commands per refresh cycle */
 726        };
 727
 728        if (is_mx6dq())
 729                mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
 730        else
 731                mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
 732
 733        if (is_cpu_type(MXC_CPU_MX6D))
 734                mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g);
 735        else if (is_cpu_type(MXC_CPU_MX6Q))
 736                mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g);
 737        else if (is_cpu_type(MXC_CPU_MX6DL))
 738                mx6_dram_cfg(&sysinfo, &mx6dl_1g_mmcd_calib, &mem_ddr_2g);
 739        else if (is_cpu_type(MXC_CPU_MX6SOLO))
 740                mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g);
 741}
 742
 743void board_init_f(ulong dummy)
 744{
 745        /* setup AIPS and disable watchdog */
 746        arch_cpu_init();
 747
 748        ccgr_init();
 749        gpr_init();
 750
 751        /* iomux and setup of i2c */
 752        board_early_init_f();
 753
 754        /* setup GP timer */
 755        timer_init();
 756
 757        /* UART clocks enabled and gd valid - init serial console */
 758        preloader_console_init();
 759
 760        /* DDR initialization */
 761        if (is_cpu_type(MXC_CPU_MX6SOLO))
 762                spl_dram_init(32);
 763        else
 764                spl_dram_init(64);
 765
 766        /* Clear the BSS. */
 767        memset(__bss_start, 0, __bss_end - __bss_start);
 768
 769        /* load/boot image from boot device */
 770        board_init_r(NULL, 0);
 771}
 772#endif
 773