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