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 <linux/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() || is_mx6ull()) {
 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_mx6ull() || 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
 303#define OCOTP_MEM0_REFTOP_TRIM_SHIFT          8
 304
 305static void init_bandgap(void)
 306{
 307        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
 308        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 309        struct fuse_bank *bank = &ocotp->bank[1];
 310        struct fuse_bank1_regs *fuse =
 311                (struct fuse_bank1_regs *)bank->fuse_regs;
 312        uint32_t val;
 313
 314        /*
 315         * Ensure the bandgap has stabilized.
 316         */
 317        while (!(readl(&anatop->ana_misc0) & 0x80))
 318                ;
 319        /*
 320         * For best noise performance of the analog blocks using the
 321         * outputs of the bandgap, the reftop_selfbiasoff bit should
 322         * be set.
 323         */
 324        writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set);
 325        /*
 326         * On i.MX6ULL,we need to set VBGADJ bits according to the
 327         * REFTOP_TRIM[3:0] in fuse table
 328         *      000 - set REFTOP_VBGADJ[2:0] to 3b'110,
 329         *      110 - set REFTOP_VBGADJ[2:0] to 3b'000,
 330         *      001 - set REFTOP_VBGADJ[2:0] to 3b'001,
 331         *      010 - set REFTOP_VBGADJ[2:0] to 3b'010,
 332         *      011 - set REFTOP_VBGADJ[2:0] to 3b'011,
 333         *      100 - set REFTOP_VBGADJ[2:0] to 3b'100,
 334         *      101 - set REFTOP_VBGADJ[2:0] to 3b'101,
 335         *      111 - set REFTOP_VBGADJ[2:0] to 3b'111,
 336         */
 337        if (is_mx6ull()) {
 338                val = readl(&fuse->mem0);
 339                val >>= OCOTP_MEM0_REFTOP_TRIM_SHIFT;
 340                val &= 0x7;
 341
 342                writel(val << BM_ANADIG_ANA_MISC0_REFTOP_VBGADJ_SHIFT,
 343                       &anatop->ana_misc0_set);
 344        }
 345}
 346
 347#ifdef CONFIG_MX6SL
 348static void set_preclk_from_osc(void)
 349{
 350        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 351        u32 reg;
 352
 353        reg = readl(&mxc_ccm->cscmr1);
 354        reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK;
 355        writel(reg, &mxc_ccm->cscmr1);
 356}
 357#endif
 358
 359int arch_cpu_init(void)
 360{
 361        init_aips();
 362
 363        /* Need to clear MMDC_CHx_MASK to make warm reset work. */
 364        clear_mmdc_ch_mask();
 365
 366        /*
 367         * Disable self-bias circuit in the analog bandap.
 368         * The self-bias circuit is used by the bandgap during startup.
 369         * This bit should be set after the bandgap has initialized.
 370         */
 371        init_bandgap();
 372
 373        if (!is_mx6ul() && !is_mx6ull()) {
 374                /*
 375                 * When low freq boot is enabled, ROM will not set AHB
 376                 * freq, so we need to ensure AHB freq is 132MHz in such
 377                 * scenario.
 378                 *
 379                 * To i.MX6UL, when power up, default ARM core and
 380                 * AHB rate is 396M and 132M.
 381                 */
 382                if (mxc_get_clock(MXC_ARM_CLK) == 396000000)
 383                        set_ahb_rate(132000000);
 384        }
 385
 386        if (is_mx6ul()) {
 387                if (is_soc_rev(CHIP_REV_1_0) == 0) {
 388                        /*
 389                         * According to the design team's requirement on
 390                         * i.MX6UL,the PMIC_STBY_REQ PAD should be configured
 391                         * as open drain 100K (0x0000b8a0).
 392                         * Only exists on TO1.0
 393                         */
 394                        writel(0x0000b8a0, IOMUXC_BASE_ADDR + 0x29c);
 395                } else {
 396                        /*
 397                         * From TO1.1, SNVS adds internal pull up control
 398                         * for POR_B, the register filed is GPBIT[1:0],
 399                         * after system boot up, it can be set to 2b'01
 400                         * to disable internal pull up.It can save about
 401                         * 30uA power in SNVS mode.
 402                         */
 403                        writel((readl(MX6UL_SNVS_LP_BASE_ADDR + 0x10) &
 404                               (~0x1400)) | 0x400,
 405                               MX6UL_SNVS_LP_BASE_ADDR + 0x10);
 406                }
 407        }
 408
 409        if (is_mx6ull()) {
 410                /*
 411                 * GPBIT[1:0] is suggested to set to 2'b11:
 412                 * 2'b00 : always PUP100K
 413                 * 2'b01 : PUP100K when PMIC_ON_REQ or SOC_NOT_FAIL
 414                 * 2'b10 : always disable PUP100K
 415                 * 2'b11 : PDN100K when SOC_FAIL, PUP100K when SOC_NOT_FAIL
 416                 * register offset is different from i.MX6UL, since
 417                 * i.MX6UL is fixed by ECO.
 418                 */
 419                writel(readl(MX6UL_SNVS_LP_BASE_ADDR) |
 420                        0x3, MX6UL_SNVS_LP_BASE_ADDR);
 421        }
 422
 423        /* Set perclk to source from OSC 24MHz */
 424#if defined(CONFIG_MX6SL)
 425        set_preclk_from_osc();
 426#endif
 427
 428        imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */
 429
 430#ifdef CONFIG_APBH_DMA
 431        /* Start APBH DMA */
 432        mxs_dma_init();
 433#endif
 434
 435        init_src();
 436
 437        return 0;
 438}
 439
 440#ifdef CONFIG_ENV_IS_IN_MMC
 441__weak int board_mmc_get_env_dev(int devno)
 442{
 443        return CONFIG_SYS_MMC_ENV_DEV;
 444}
 445
 446static int mmc_get_boot_dev(void)
 447{
 448        struct src *src_regs = (struct src *)SRC_BASE_ADDR;
 449        u32 soc_sbmr = readl(&src_regs->sbmr1);
 450        u32 bootsel;
 451        int devno;
 452
 453        /*
 454         * Refer to
 455         * "i.MX 6Dual/6Quad Applications Processor Reference Manual"
 456         * Chapter "8.5.3.1 Expansion Device eFUSE Configuration"
 457         * i.MX6SL/SX/UL has same layout.
 458         */
 459        bootsel = (soc_sbmr & 0x000000FF) >> 6;
 460
 461        /* No boot from sd/mmc */
 462        if (bootsel != 1)
 463                return -1;
 464
 465        /* BOOT_CFG2[3] and BOOT_CFG2[4] */
 466        devno = (soc_sbmr & 0x00001800) >> 11;
 467
 468        return devno;
 469}
 470
 471int mmc_get_env_dev(void)
 472{
 473        int devno = mmc_get_boot_dev();
 474
 475        /* If not boot from sd/mmc, use default value */
 476        if (devno < 0)
 477                return CONFIG_SYS_MMC_ENV_DEV;
 478
 479        return board_mmc_get_env_dev(devno);
 480}
 481
 482#ifdef CONFIG_SYS_MMC_ENV_PART
 483__weak int board_mmc_get_env_part(int devno)
 484{
 485        return CONFIG_SYS_MMC_ENV_PART;
 486}
 487
 488uint mmc_get_env_part(struct mmc *mmc)
 489{
 490        int devno = mmc_get_boot_dev();
 491
 492        /* If not boot from sd/mmc, use default value */
 493        if (devno < 0)
 494                return CONFIG_SYS_MMC_ENV_PART;
 495
 496        return board_mmc_get_env_part(devno);
 497}
 498#endif
 499#endif
 500
 501int board_postclk_init(void)
 502{
 503        set_ldo_voltage(LDO_SOC, 1175); /* Set VDDSOC to 1.175V */
 504
 505        return 0;
 506}
 507
 508#if defined(CONFIG_FEC_MXC)
 509void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
 510{
 511        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 512        struct fuse_bank *bank = &ocotp->bank[4];
 513        struct fuse_bank4_regs *fuse =
 514                        (struct fuse_bank4_regs *)bank->fuse_regs;
 515
 516        if ((is_mx6sx() || is_mx6ul() || is_mx6ull()) && dev_id == 1) {
 517                u32 value = readl(&fuse->mac_addr2);
 518                mac[0] = value >> 24 ;
 519                mac[1] = value >> 16 ;
 520                mac[2] = value >> 8 ;
 521                mac[3] = value ;
 522
 523                value = readl(&fuse->mac_addr1);
 524                mac[4] = value >> 24 ;
 525                mac[5] = value >> 16 ;
 526                
 527        } else {
 528                u32 value = readl(&fuse->mac_addr1);
 529                mac[0] = (value >> 8);
 530                mac[1] = value ;
 531
 532                value = readl(&fuse->mac_addr0);
 533                mac[2] = value >> 24 ;
 534                mac[3] = value >> 16 ;
 535                mac[4] = value >> 8 ;
 536                mac[5] = value ;
 537        }
 538
 539}
 540#endif
 541
 542/*
 543 * cfg_val will be used for
 544 * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
 545 * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0]
 546 * instead of SBMR1 to determine the boot device.
 547 */
 548const struct boot_mode soc_boot_modes[] = {
 549        {"normal",      MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)},
 550        /* reserved value should start rom usb */
 551        {"usb",         MAKE_CFGVAL(0x10, 0x00, 0x00, 0x00)},
 552        {"sata",        MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)},
 553        {"ecspi1:0",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)},
 554        {"ecspi1:1",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)},
 555        {"ecspi1:2",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)},
 556        {"ecspi1:3",    MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)},
 557        /* 4 bit bus width */
 558        {"esdhc1",      MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
 559        {"esdhc2",      MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
 560        {"esdhc3",      MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
 561        {"esdhc4",      MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
 562        {NULL,          0},
 563};
 564
 565void reset_misc(void)
 566{
 567#ifdef CONFIG_VIDEO_MXS
 568        lcdif_power_down();
 569#endif
 570}
 571
 572void s_init(void)
 573{
 574        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
 575        struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 576        u32 mask480;
 577        u32 mask528;
 578        u32 reg, periph1, periph2;
 579
 580        if (is_mx6sx() || is_mx6ul() || is_mx6ull())
 581                return;
 582
 583        /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
 584         * to make sure PFD is working right, otherwise, PFDs may
 585         * not output clock after reset, MX6DL and MX6SL have added 396M pfd
 586         * workaround in ROM code, as bus clock need it
 587         */
 588
 589        mask480 = ANATOP_PFD_CLKGATE_MASK(0) |
 590                ANATOP_PFD_CLKGATE_MASK(1) |
 591                ANATOP_PFD_CLKGATE_MASK(2) |
 592                ANATOP_PFD_CLKGATE_MASK(3);
 593        mask528 = ANATOP_PFD_CLKGATE_MASK(1) |
 594                ANATOP_PFD_CLKGATE_MASK(3);
 595
 596        reg = readl(&ccm->cbcmr);
 597        periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK)
 598                >> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET);
 599        periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
 600                >> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET);
 601
 602        /* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */
 603        if ((periph2 != 0x2) && (periph1 != 0x2))
 604                mask528 |= ANATOP_PFD_CLKGATE_MASK(0);
 605
 606        if ((periph2 != 0x1) && (periph1 != 0x1) &&
 607                (periph2 != 0x3) && (periph1 != 0x3))
 608                mask528 |= ANATOP_PFD_CLKGATE_MASK(2);
 609
 610        writel(mask480, &anatop->pfd_480_set);
 611        writel(mask528, &anatop->pfd_528_set);
 612        writel(mask480, &anatop->pfd_480_clr);
 613        writel(mask528, &anatop->pfd_528_clr);
 614}
 615
 616#ifdef CONFIG_IMX_HDMI
 617void imx_enable_hdmi_phy(void)
 618{
 619        struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
 620        u8 reg;
 621        reg = readb(&hdmi->phy_conf0);
 622        reg |= HDMI_PHY_CONF0_PDZ_MASK;
 623        writeb(reg, &hdmi->phy_conf0);
 624        udelay(3000);
 625        reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
 626        writeb(reg, &hdmi->phy_conf0);
 627        udelay(3000);
 628        reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
 629        writeb(reg, &hdmi->phy_conf0);
 630        writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
 631}
 632
 633void imx_setup_hdmi(void)
 634{
 635        struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
 636        struct hdmi_regs *hdmi  = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
 637        int reg, count;
 638        u8 val;
 639
 640        /* Turn on HDMI PHY clock */
 641        reg = readl(&mxc_ccm->CCGR2);
 642        reg |=  MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK|
 643                 MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
 644        writel(reg, &mxc_ccm->CCGR2);
 645        writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
 646        reg = readl(&mxc_ccm->chsccdr);
 647        reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK|
 648                 MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK|
 649                 MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
 650        reg |= (CHSCCDR_PODF_DIVIDE_BY_3
 651                 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
 652                 |(CHSCCDR_IPU_PRE_CLK_540M_PFD
 653                 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
 654        writel(reg, &mxc_ccm->chsccdr);
 655
 656        /* Clear the overflow condition */
 657        if (readb(&hdmi->ih_fc_stat2) & HDMI_IH_FC_STAT2_OVERFLOW_MASK) {
 658                /* TMDS software reset */
 659                writeb((u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, &hdmi->mc_swrstz);
 660                val = readb(&hdmi->fc_invidconf);
 661                /* Need minimum 3 times to write to clear the register */
 662                for (count = 0 ; count < 5 ; count++)
 663                        writeb(val, &hdmi->fc_invidconf);
 664        }
 665}
 666#endif
 667
 668#ifdef CONFIG_IMX_BOOTAUX
 669int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
 670{
 671        struct src *src_reg;
 672        u32 stack, pc;
 673
 674        if (!boot_private_data)
 675                return -EINVAL;
 676
 677        stack = *(u32 *)boot_private_data;
 678        pc = *(u32 *)(boot_private_data + 4);
 679
 680        /* Set the stack and pc to M4 bootROM */
 681        writel(stack, M4_BOOTROM_BASE_ADDR);
 682        writel(pc, M4_BOOTROM_BASE_ADDR + 4);
 683
 684        /* Enable M4 */
 685        src_reg = (struct src *)SRC_BASE_ADDR;
 686        clrsetbits_le32(&src_reg->scr, SRC_SCR_M4C_NON_SCLR_RST_MASK,
 687                        SRC_SCR_M4_ENABLE_MASK);
 688
 689        return 0;
 690}
 691
 692int arch_auxiliary_core_check_up(u32 core_id)
 693{
 694        struct src *src_reg = (struct src *)SRC_BASE_ADDR;
 695        unsigned val;
 696
 697        val = readl(&src_reg->scr);
 698
 699        if (val & SRC_SCR_M4C_NON_SCLR_RST_MASK)
 700                return 0;  /* assert in reset */
 701
 702        return 1;
 703}
 704#endif
 705