uboot/arch/arm/cpu/armv7/mx6/soc.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007
   3 * Sascha Hauer, Pengutronix
   4 *
   5 * (C) Copyright 2009 Freescale Semiconductor, Inc.
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#include <common.h>
  11#include <asm/errno.h>
  12#include <asm/io.h>
  13#include <asm/arch/imx-regs.h>
  14#include <asm/arch/clock.h>
  15#include <asm/arch/sys_proto.h>
  16#include <asm/imx-common/boot_mode.h>
  17#include <asm/imx-common/dma.h>
  18#include <asm/imx-common/hab.h>
  19#include <stdbool.h>
  20#include <asm/arch/mxc_hdmi.h>
  21#include <asm/arch/crm_regs.h>
  22#include <dm.h>
  23#include <imx_thermal.h>
  24#include <mmc.h>
  25
  26enum ldo_reg {
  27        LDO_ARM,
  28        LDO_SOC,
  29        LDO_PU,
  30};
  31
  32struct scu_regs {
  33        u32     ctrl;
  34        u32     config;
  35        u32     status;
  36        u32     invalidate;
  37        u32     fpga_rev;
  38};
  39
  40#if defined(CONFIG_IMX_THERMAL)
  41static const struct imx_thermal_plat imx6_thermal_plat = {
  42        .regs = (void *)ANATOP_BASE_ADDR,
  43        .fuse_bank = 1,
  44        .fuse_word = 6,
  45};
  46
  47U_BOOT_DEVICE(imx6_thermal) = {
  48        .name = "imx_thermal",
  49        .platdata = &imx6_thermal_plat,
  50};
  51#endif
  52
  53#if defined(CONFIG_SECURE_BOOT)
  54struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
  55        .bank = 0,
  56        .word = 6,
  57};
  58#endif
  59
  60u32 get_nr_cpus(void)
  61{
  62        struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
  63        return readl(&scu->config) & 3;
  64}
  65
  66u32 get_cpu_rev(void)
  67{
  68        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
  69        u32 reg = readl(&anatop->digprog_sololite);
  70        u32 type = ((reg >> 16) & 0xff);
  71        u32 major, cfg = 0;
  72
  73        if (type != MXC_CPU_MX6SL) {
  74                reg = readl(&anatop->digprog);
  75                struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR;
  76                cfg = readl(&scu->config) & 3;
  77                type = ((reg >> 16) & 0xff);
  78                if (type == MXC_CPU_MX6DL) {
  79                        if (!cfg)
  80                                type = MXC_CPU_MX6SOLO;
  81                }
  82
  83                if (type == MXC_CPU_MX6Q) {
  84                        if (cfg == 1)
  85                                type = MXC_CPU_MX6D;
  86                }
  87
  88        }
  89        major = ((reg >> 8) & 0xff);
  90        if ((major >= 1) &&
  91            ((type == MXC_CPU_MX6Q) || (type == MXC_CPU_MX6D))) {
  92                major--;
  93                type = MXC_CPU_MX6QP;
  94                if (cfg == 1)
  95                        type = MXC_CPU_MX6DP;
  96        }
  97        reg &= 0xff;            /* mx6 silicon revision */
  98        return (type << 12) | (reg + (0x10 * (major + 1)));
  99}
 100
 101/*
 102 * OCOTP_CFG3[17:16] (see Fusemap Description Table offset 0x440)
 103 * defines a 2-bit SPEED_GRADING
 104 */
 105#define OCOTP_CFG3_SPEED_SHIFT  16
 106#define OCOTP_CFG3_SPEED_800MHZ 0
 107#define OCOTP_CFG3_SPEED_850MHZ 1
 108#define OCOTP_CFG3_SPEED_1GHZ   2
 109#define OCOTP_CFG3_SPEED_1P2GHZ 3
 110
 111/*
 112 * For i.MX6UL
 113 */
 114#define OCOTP_CFG3_SPEED_528MHZ 1
 115#define OCOTP_CFG3_SPEED_696MHZ 2
 116
 117u32 get_cpu_speed_grade_hz(void)
 118{
 119        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 120        struct fuse_bank *bank = &ocotp->bank[0];
 121        struct fuse_bank0_regs *fuse =
 122                (struct fuse_bank0_regs *)bank->fuse_regs;
 123        uint32_t val;
 124
 125        val = readl(&fuse->cfg3);
 126        val >>= OCOTP_CFG3_SPEED_SHIFT;
 127        val &= 0x3;
 128
 129        if (is_mx6ul()) {
 130                if (val == OCOTP_CFG3_SPEED_528MHZ)
 131                        return 528000000;
 132                else if (val == OCOTP_CFG3_SPEED_696MHZ)
 133                        return 69600000;
 134                else
 135                        return 0;
 136        }
 137
 138        switch (val) {
 139        /* Valid for IMX6DQ */
 140        case OCOTP_CFG3_SPEED_1P2GHZ:
 141                if (is_mx6dq() || is_mx6dqp())
 142                        return 1200000000;
 143        /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
 144        case OCOTP_CFG3_SPEED_1GHZ:
 145                return 996000000;
 146        /* Valid for IMX6DQ */
 147        case OCOTP_CFG3_SPEED_850MHZ:
 148                if (is_mx6dq() || is_mx6dqp())
 149                        return 852000000;
 150        /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
 151        case OCOTP_CFG3_SPEED_800MHZ:
 152                return 792000000;
 153        }
 154        return 0;
 155}
 156
 157/*
 158 * OCOTP_MEM0[7:6] (see Fusemap Description Table offset 0x480)
 159 * defines a 2-bit Temperature Grade
 160 *
 161 * return temperature grade and min/max temperature in celcius
 162 */
 163#define OCOTP_MEM0_TEMP_SHIFT          6
 164
 165u32 get_cpu_temp_grade(int *minc, int *maxc)
 166{
 167        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 168        struct fuse_bank *bank = &ocotp->bank[1];
 169        struct fuse_bank1_regs *fuse =
 170                (struct fuse_bank1_regs *)bank->fuse_regs;
 171        uint32_t val;
 172
 173        val = readl(&fuse->mem0);
 174        val >>= OCOTP_MEM0_TEMP_SHIFT;
 175        val &= 0x3;
 176
 177        if (minc && maxc) {
 178                if (val == TEMP_AUTOMOTIVE) {
 179                        *minc = -40;
 180                        *maxc = 125;
 181                } else if (val == TEMP_INDUSTRIAL) {
 182                        *minc = -40;
 183                        *maxc = 105;
 184                } else if (val == TEMP_EXTCOMMERCIAL) {
 185                        *minc = -20;
 186                        *maxc = 105;
 187                } else {
 188                        *minc = 0;
 189                        *maxc = 95;
 190                }
 191        }
 192        return val;
 193}
 194
 195#ifdef CONFIG_REVISION_TAG
 196u32 __weak get_board_rev(void)
 197{
 198        u32 cpurev = get_cpu_rev();
 199        u32 type = ((cpurev >> 12) & 0xff);
 200        if (type == MXC_CPU_MX6SOLO)
 201                cpurev = (MXC_CPU_MX6DL) << 12 | (cpurev & 0xFFF);
 202
 203        if (type == MXC_CPU_MX6D)
 204                cpurev = (MXC_CPU_MX6Q) << 12 | (cpurev & 0xFFF);
 205
 206        return cpurev;
 207}
 208#endif
 209
 210static void clear_ldo_ramp(void)
 211{
 212        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
 213        int reg;
 214
 215        /* ROM may modify LDO ramp up time according to fuse setting, so in
 216         * order to be in the safe side we neeed to reset these settings to
 217         * match the reset value: 0'b00
 218         */
 219        reg = readl(&anatop->ana_misc2);
 220        reg &= ~(0x3f << 24);
 221        writel(reg, &anatop->ana_misc2);
 222}
 223
 224/*
 225 * Set the PMU_REG_CORE register
 226 *
 227 * Set LDO_SOC/PU/ARM regulators to the specified millivolt level.
 228 * Possible values are from 0.725V to 1.450V in steps of
 229 * 0.025V (25mV).
 230 */
 231static int set_ldo_voltage(enum ldo_reg ldo, u32 mv)
 232{
 233        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
 234        u32 val, step, old, reg = readl(&anatop->reg_core);
 235        u8 shift;
 236
 237        if (mv < 725)
 238                val = 0x00;     /* Power gated off */
 239        else if (mv > 1450)
 240                val = 0x1F;     /* Power FET switched full on. No regulation */
 241        else
 242                val = (mv - 700) / 25;
 243
 244        clear_ldo_ramp();
 245
 246        switch (ldo) {
 247        case LDO_SOC:
 248                shift = 18;
 249                break;
 250        case LDO_PU:
 251                shift = 9;
 252                break;
 253        case LDO_ARM:
 254                shift = 0;
 255                break;
 256        default:
 257                return -EINVAL;
 258        }
 259
 260        old = (reg & (0x1F << shift)) >> shift;
 261        step = abs(val - old);
 262        if (step == 0)
 263                return 0;
 264
 265        reg = (reg & ~(0x1F << shift)) | (val << shift);
 266        writel(reg, &anatop->reg_core);
 267
 268        /*
 269         * The LDO ramp-up is based on 64 clock cycles of 24 MHz = 2.6 us per
 270         * step
 271         */
 272        udelay(3 * step);
 273
 274        return 0;
 275}
 276
 277static void set_ahb_rate(u32 val)
 278{
 279        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 280        u32 reg, div;
 281
 282        div = get_periph_clk() / val - 1;
 283        reg = readl(&mxc_ccm->cbcdr);
 284
 285        writel((reg & (~MXC_CCM_CBCDR_AHB_PODF_MASK)) |
 286                (div << MXC_CCM_CBCDR_AHB_PODF_OFFSET), &mxc_ccm->cbcdr);
 287}
 288
 289static void clear_mmdc_ch_mask(void)
 290{
 291        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 292        u32 reg;
 293        reg = readl(&mxc_ccm->ccdr);
 294
 295        /* Clear MMDC channel mask */
 296        if (is_mx6sx() || is_mx6ul() || is_mx6sl())
 297                reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK);
 298        else
 299                reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK | MXC_CCM_CCDR_MMDC_CH0_HS_MASK);
 300        writel(reg, &mxc_ccm->ccdr);
 301}
 302
 303static void init_bandgap(void)
 304{
 305        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
 306        /*
 307         * Ensure the bandgap has stabilized.
 308         */
 309        while (!(readl(&anatop->ana_misc0) & 0x80))
 310                ;
 311        /*
 312         * For best noise performance of the analog blocks using the
 313         * outputs of the bandgap, the reftop_selfbiasoff bit should
 314         * be set.
 315         */
 316        writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
 317}
 318
 319
 320#ifdef CONFIG_MX6SL
 321static void set_preclk_from_osc(void)
 322{
 323        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 324        u32 reg;
 325
 326        reg = readl(&mxc_ccm->cscmr1);
 327        reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK;
 328        writel(reg, &mxc_ccm->cscmr1);
 329}
 330#endif
 331
 332int arch_cpu_init(void)
 333{
 334        init_aips();
 335
 336        /* Need to clear MMDC_CHx_MASK to make warm reset work. */
 337        clear_mmdc_ch_mask();
 338
 339        /*
 340         * Disable self-bias circuit in the analog bandap.
 341         * The self-bias circuit is used by the bandgap during startup.
 342         * This bit should be set after the bandgap has initialized.
 343         */
 344        init_bandgap();
 345
 346        if (!IS_ENABLED(CONFIG_MX6UL)) {
 347                /*
 348                 * When low freq boot is enabled, ROM will not set AHB
 349                 * freq, so we need to ensure AHB freq is 132MHz in such
 350                 * scenario.
 351                 *
 352                 * To i.MX6UL, when power up, default ARM core and
 353                 * AHB rate is 396M and 132M.
 354                 */
 355                if (mxc_get_clock(MXC_ARM_CLK) == 396000000)
 356                        set_ahb_rate(132000000);
 357        }
 358
 359        if (IS_ENABLED(CONFIG_MX6UL) && is_soc_rev(CHIP_REV_1_0) == 0) {
 360                /*
 361                 * According to the design team's requirement on i.MX6UL,
 362                 * the PMIC_STBY_REQ PAD should be configured as open
 363                 * drain 100K (0x0000b8a0).
 364                 * Only exists on TO1.0
 365                 */
 366                writel(0x0000b8a0, IOMUXC_BASE_ADDR + 0x29c);
 367        }
 368
 369        /* Set perclk to source from OSC 24MHz */
 370#if defined(CONFIG_MX6SL)
 371        set_preclk_from_osc();
 372#endif
 373
 374        imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
 375
 376#ifdef CONFIG_APBH_DMA
 377        /* Start APBH DMA */
 378        mxs_dma_init();
 379#endif
 380
 381        init_src();
 382
 383        return 0;
 384}
 385
 386#ifdef CONFIG_ENV_IS_IN_MMC
 387__weak int board_mmc_get_env_dev(int devno)
 388{
 389        return CONFIG_SYS_MMC_ENV_DEV;
 390}
 391
 392static int mmc_get_boot_dev(void)
 393{
 394        struct src *src_regs = (struct src *)SRC_BASE_ADDR;
 395        u32 soc_sbmr = readl(&src_regs->sbmr1);
 396        u32 bootsel;
 397        int devno;
 398
 399        /*
 400         * Refer to
 401         * "i.MX 6Dual/6Quad Applications Processor Reference Manual"
 402         * Chapter "8.5.3.1 Expansion Device eFUSE Configuration"
 403         * i.MX6SL/SX/UL has same layout.
 404         */
 405        bootsel = (soc_sbmr & 0x000000FF) >> 6;
 406
 407        /* No boot from sd/mmc */
 408        if (bootsel != 1)
 409                return -1;
 410
 411        /* BOOT_CFG2[3] and BOOT_CFG2[4] */
 412        devno = (soc_sbmr & 0x00001800) >> 11;
 413
 414        return devno;
 415}
 416
 417int mmc_get_env_dev(void)
 418{
 419        int devno = mmc_get_boot_dev();
 420
 421        /* If not boot from sd/mmc, use default value */
 422        if (devno < 0)
 423                return CONFIG_SYS_MMC_ENV_DEV;
 424
 425        return board_mmc_get_env_dev(devno);
 426}
 427
 428#ifdef CONFIG_SYS_MMC_ENV_PART
 429__weak int board_mmc_get_env_part(int devno)
 430{
 431        return CONFIG_SYS_MMC_ENV_PART;
 432}
 433
 434uint mmc_get_env_part(struct mmc *mmc)
 435{
 436        int devno = mmc_get_boot_dev();
 437
 438        /* If not boot from sd/mmc, use default value */
 439        if (devno < 0)
 440                return CONFIG_SYS_MMC_ENV_PART;
 441
 442        return board_mmc_get_env_part(devno);
 443}
 444#endif
 445#endif
 446
 447int board_postclk_init(void)
 448{
 449        set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */
 450
 451        return 0;
 452}
 453
 454#if defined(CONFIG_FEC_MXC)
 455void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 456{
 457        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 458        struct fuse_bank *bank = &ocotp->bank[4];
 459        struct fuse_bank4_regs *fuse =
 460                        (struct fuse_bank4_regs *)bank->fuse_regs;
 461
 462        if ((is_mx6sx() || is_mx6ul()) && dev_id == 1) {
 463                u32 value = readl(&fuse->mac_addr2);
 464                mac[0] = value >> 24 ;
 465                mac[1] = value >> 16 ;
 466                mac[2] = value >> 8 ;
 467                mac[3] = value ;
 468
 469                value = readl(&fuse->mac_addr1);
 470                mac[4] = value >> 24 ;
 471                mac[5] = value >> 16 ;
 472                
 473        } else {
 474                u32 value = readl(&fuse->mac_addr1);
 475                mac[0] = (value >> 8);
 476                mac[1] = value ;
 477
 478                value = readl(&fuse->mac_addr0);
 479                mac[2] = value >> 24 ;
 480                mac[3] = value >> 16 ;
 481                mac[4] = value >> 8 ;
 482                mac[5] = value ;
 483        }
 484
 485}
 486#endif
 487
 488/*
 489 * cfg_val will be used for
 490 * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
 491 * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0]
 492 * instead of SBMR1 to determine the boot device.
 493 */
 494const struct boot_mode soc_boot_modes[] = {
 495        {"normal",      MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
 496        /* reserved value should start rom usb */
 497        {"usb",         MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)},
 498        {"sata",        MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)},
 499        {"ecspi1:0",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
 500        {"ecspi1:1",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
 501        {"ecspi1:2",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
 502        {"ecspi1:3",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
 503        /* 4 bit bus width */
 504        {"esdhc1",      MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
 505        {"esdhc2",      MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
 506        {"esdhc3",      MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
 507        {"esdhc4",      MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
 508        {NULL,          0},
 509};
 510
 511void reset_misc(void)
 512{
 513#ifdef CONFIG_VIDEO_MXS
 514        lcdif_power_down();
 515#endif
 516}
 517
 518void s_init(void)
 519{
 520        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
 521        struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 522        u32 mask480;
 523        u32 mask528;
 524        u32 reg, periph1, periph2;
 525
 526        if (is_mx6sx() || is_mx6ul())
 527                return;
 528
 529        /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
 530         * to make sure PFD is working right, otherwise, PFDs may
 531         * not output clock after reset, MX6DL and MX6SL have added 396M pfd
 532         * workaround in ROM code, as bus clock need it
 533         */
 534
 535        mask480 = ANATOP_PFD_CLKGATE_MASK(0) |
 536                ANATOP_PFD_CLKGATE_MASK(1) |
 537                ANATOP_PFD_CLKGATE_MASK(2) |
 538                ANATOP_PFD_CLKGATE_MASK(3);
 539        mask528 = ANATOP_PFD_CLKGATE_MASK(1) |
 540                ANATOP_PFD_CLKGATE_MASK(3);
 541
 542        reg = readl(&ccm->cbcmr);
 543        periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
 544                >> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET);
 545        periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
 546                >> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
 547
 548        /* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */
 549        if ((periph2 != 0x2) && (periph1 != 0x2))
 550                mask528 |= ANATOP_PFD_CLKGATE_MASK(0);
 551
 552        if ((periph2 != 0x1) && (periph1 != 0x1) &&
 553                (periph2 != 0x3) && (periph1 != 0x3))
 554                mask528 |= ANATOP_PFD_CLKGATE_MASK(2);
 555
 556        writel(mask480, &anatop->pfd_480_set);
 557        writel(mask528, &anatop->pfd_528_set);
 558        writel(mask480, &anatop->pfd_480_clr);
 559        writel(mask528, &anatop->pfd_528_clr);
 560}
 561
 562#ifdef CONFIG_IMX_HDMI
 563void imx_enable_hdmi_phy(void)
 564{
 565        struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
 566        u8 reg;
 567        reg = readb(&hdmi->phy_conf0);
 568        reg |= HDMI_PHY_CONF0_PDZ_MASK;
 569        writeb(reg, &hdmi->phy_conf0);
 570        udelay(3000);
 571        reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
 572        writeb(reg, &hdmi->phy_conf0);
 573        udelay(3000);
 574        reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
 575        writeb(reg, &hdmi->phy_conf0);
 576        writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
 577}
 578
 579void imx_setup_hdmi(void)
 580{
 581        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 582        struct hdmi_regs *hdmi  = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
 583        int reg, count;
 584        u8 val;
 585
 586        /* Turn on HDMI PHY clock */
 587        reg = readl(&mxc_ccm->CCGR2);
 588        reg |=  MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK|
 589                 MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
 590        writel(reg, &mxc_ccm->CCGR2);
 591        writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
 592        reg = readl(&mxc_ccm->chsccdr);
 593        reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK|
 594                 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK|
 595                 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
 596        reg |= (CHSCCDR_PODF_DIVIDE_BY_3
 597                 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
 598                 |(CHSCCDR_IPU_PRE_CLK_540M_PFD
 599                 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
 600        writel(reg, &mxc_ccm->chsccdr);
 601
 602        /* Clear the overflow condition */
 603        if (readb(&hdmi->ih_fc_stat2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK) {
 604                /* TMDS software reset */
 605                writeb((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &hdmi->mc_swrstz);
 606                val = readb(&hdmi->fc_invidconf);
 607                /* Need minimum 3 times to write to clear the register */
 608                for (count = 0 ; count < 5 ; count++)
 609                        writeb(val, &hdmi->fc_invidconf);
 610        }
 611}
 612#endif
 613
 614#ifdef CONFIG_IMX_BOOTAUX
 615int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
 616{
 617        struct src *src_reg;
 618        u32 stack, pc;
 619
 620        if (!boot_private_data)
 621                return -EINVAL;
 622
 623        stack = *(u32 *)boot_private_data;
 624        pc = *(u32 *)(boot_private_data + 4);
 625
 626        /* Set the stack and pc to M4 bootROM */
 627        writel(stack, M4_BOOTROM_BASE_ADDR);
 628        writel(pc, M4_BOOTROM_BASE_ADDR + 4);
 629
 630        /* Enable M4 */
 631        src_reg = (struct src *)SRC_BASE_ADDR;
 632        clrsetbits_le32(&src_reg->scr, SRC_SCR_M4C_NON_SCLR_RST_MASK,
 633                        SRC_SCR_M4_ENABLE_MASK);
 634
 635        return 0;
 636}
 637
 638int arch_auxiliary_core_check_up(u32 core_id)
 639{
 640        struct src *src_reg = (struct src *)SRC_BASE_ADDR;
 641        unsigned val;
 642
 643        val = readl(&src_reg->scr);
 644
 645        if (val & SRC_SCR_M4C_NON_SCLR_RST_MASK)
 646                return 0;  /* assert in reset */
 647
 648        return 1;
 649}
 650#endif
 651