uboot/arch/arm/mach-imx/mx7/soc.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <asm/io.h>
   9#include <asm/arch/imx-regs.h>
  10#include <asm/arch/clock.h>
  11#include <asm/arch/sys_proto.h>
  12#include <asm/mach-imx/boot_mode.h>
  13#include <asm/mach-imx/dma.h>
  14#include <asm/mach-imx/hab.h>
  15#include <asm/mach-imx/rdc-sema.h>
  16#include <asm/arch/imx-rdc.h>
  17#include <asm/arch/crm_regs.h>
  18#include <dm.h>
  19#include <imx_thermal.h>
  20#include <fsl_sec.h>
  21
  22#if defined(CONFIG_IMX_THERMAL)
  23static const struct imx_thermal_plat imx7_thermal_plat = {
  24        .regs = (void *)ANATOP_BASE_ADDR,
  25        .fuse_bank = 3,
  26        .fuse_word = 3,
  27};
  28
  29U_BOOT_DEVICE(imx7_thermal) = {
  30        .name = "imx_thermal",
  31        .platdata = &imx7_thermal_plat,
  32};
  33#endif
  34
  35#if CONFIG_IS_ENABLED(IMX_RDC)
  36/*
  37 * In current design, if any peripheral was assigned to both A7 and M4,
  38 * it will receive ipg_stop or ipg_wait when any of the 2 platforms enter
  39 * low power mode. So M4 sleep will cause some peripherals fail to work
  40 * at A7 core side. At default, all resources are in domain 0 - 3.
  41 *
  42 * There are 26 peripherals impacted by this IC issue:
  43 * SIM2(sim2/emvsim2)
  44 * SIM1(sim1/emvsim1)
  45 * UART1/UART2/UART3/UART4/UART5/UART6/UART7
  46 * SAI1/SAI2/SAI3
  47 * WDOG1/WDOG2/WDOG3/WDOG4
  48 * GPT1/GPT2/GPT3/GPT4
  49 * PWM1/PWM2/PWM3/PWM4
  50 * ENET1/ENET2
  51 * Software Workaround:
  52 * Here we setup some resources to domain 0 where M4 codes will move
  53 * the M4 out of this domain. Then M4 is not able to access them any longer.
  54 * This is a workaround for ic issue. So the peripherals are not shared
  55 * by them. This way requires the uboot implemented the RDC driver and
  56 * set the 26 IPs above to domain 0 only. M4 code will assign resource
  57 * to its own domain, if it want to use the resource.
  58 */
  59static rdc_peri_cfg_t const resources[] = {
  60        (RDC_PER_SIM1 | RDC_DOMAIN(0)),
  61        (RDC_PER_SIM2 | RDC_DOMAIN(0)),
  62        (RDC_PER_UART1 | RDC_DOMAIN(0)),
  63        (RDC_PER_UART2 | RDC_DOMAIN(0)),
  64        (RDC_PER_UART3 | RDC_DOMAIN(0)),
  65        (RDC_PER_UART4 | RDC_DOMAIN(0)),
  66        (RDC_PER_UART5 | RDC_DOMAIN(0)),
  67        (RDC_PER_UART6 | RDC_DOMAIN(0)),
  68        (RDC_PER_UART7 | RDC_DOMAIN(0)),
  69        (RDC_PER_SAI1 | RDC_DOMAIN(0)),
  70        (RDC_PER_SAI2 | RDC_DOMAIN(0)),
  71        (RDC_PER_SAI3 | RDC_DOMAIN(0)),
  72        (RDC_PER_WDOG1 | RDC_DOMAIN(0)),
  73        (RDC_PER_WDOG2 | RDC_DOMAIN(0)),
  74        (RDC_PER_WDOG3 | RDC_DOMAIN(0)),
  75        (RDC_PER_WDOG4 | RDC_DOMAIN(0)),
  76        (RDC_PER_GPT1 | RDC_DOMAIN(0)),
  77        (RDC_PER_GPT2 | RDC_DOMAIN(0)),
  78        (RDC_PER_GPT3 | RDC_DOMAIN(0)),
  79        (RDC_PER_GPT4 | RDC_DOMAIN(0)),
  80        (RDC_PER_PWM1 | RDC_DOMAIN(0)),
  81        (RDC_PER_PWM2 | RDC_DOMAIN(0)),
  82        (RDC_PER_PWM3 | RDC_DOMAIN(0)),
  83        (RDC_PER_PWM4 | RDC_DOMAIN(0)),
  84        (RDC_PER_ENET1 | RDC_DOMAIN(0)),
  85        (RDC_PER_ENET2 | RDC_DOMAIN(0)),
  86};
  87
  88static void isolate_resource(void)
  89{
  90        imx_rdc_setup_peripherals(resources, ARRAY_SIZE(resources));
  91}
  92#endif
  93
  94#if defined(CONFIG_SECURE_BOOT)
  95struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
  96        .bank = 1,
  97        .word = 3,
  98};
  99#endif
 100
 101static bool is_mx7d(void)
 102{
 103        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 104        struct fuse_bank *bank = &ocotp->bank[1];
 105        struct fuse_bank1_regs *fuse =
 106                (struct fuse_bank1_regs *)bank->fuse_regs;
 107        int val;
 108
 109        val = readl(&fuse->tester4);
 110        if (val & 1)
 111                return false;
 112        else
 113                return true;
 114}
 115
 116u32 get_cpu_rev(void)
 117{
 118        struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *)
 119                                                 ANATOP_BASE_ADDR;
 120        u32 reg = readl(&ccm_anatop->digprog);
 121        u32 type = (reg >> 16) & 0xff;
 122
 123        if (!is_mx7d())
 124                type = MXC_CPU_MX7S;
 125
 126        reg &= 0xff;
 127        return (type << 12) | reg;
 128}
 129
 130#ifdef CONFIG_REVISION_TAG
 131u32 __weak get_board_rev(void)
 132{
 133        return get_cpu_rev();
 134}
 135#endif
 136
 137/* enable all periherial can be accessed in nosec mode */
 138static void init_csu(void)
 139{
 140        int i = 0;
 141        for (i = 0; i < CSU_NUM_REGS; i++)
 142                writel(CSU_INIT_SEC_LEVEL0, CSU_IPS_BASE_ADDR + i * 4);
 143}
 144
 145static void imx_enet_mdio_fixup(void)
 146{
 147        struct iomuxc_gpr_base_regs *gpr_regs =
 148                (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
 149
 150        /*
 151         * The management data input/output (MDIO) requires open-drain,
 152         * i.MX7D TO1.0 ENET MDIO pin has no open drain, but TO1.1 supports
 153         * this feature. So to TO1.1, need to enable open drain by setting
 154         * bits GPR0[8:7].
 155         */
 156
 157        if (soc_rev() >= CHIP_REV_1_1) {
 158                setbits_le32(&gpr_regs->gpr[0],
 159                             IOMUXC_GPR_GPR0_ENET_MDIO_OPEN_DRAIN_MASK);
 160        }
 161}
 162
 163int arch_cpu_init(void)
 164{
 165        init_aips();
 166
 167        init_csu();
 168        /* Disable PDE bit of WMCR register */
 169        imx_wdog_disable_powerdown();
 170
 171        imx_enet_mdio_fixup();
 172
 173#ifdef CONFIG_APBH_DMA
 174        /* Start APBH DMA */
 175        mxs_dma_init();
 176#endif
 177
 178#if CONFIG_IS_ENABLED(IMX_RDC)
 179        isolate_resource();
 180#endif
 181
 182        return 0;
 183}
 184
 185#ifdef CONFIG_ARCH_MISC_INIT
 186int arch_misc_init(void)
 187{
 188#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 189        if (is_mx7d())
 190                env_set("soc", "imx7d");
 191        else
 192                env_set("soc", "imx7s");
 193#endif
 194
 195#ifdef CONFIG_FSL_CAAM
 196        sec_init();
 197#endif
 198
 199        return 0;
 200}
 201#endif
 202
 203#ifdef CONFIG_SERIAL_TAG
 204void get_board_serial(struct tag_serialnr *serialnr)
 205{
 206        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 207        struct fuse_bank *bank = &ocotp->bank[0];
 208        struct fuse_bank0_regs *fuse =
 209                (struct fuse_bank0_regs *)bank->fuse_regs;
 210
 211        serialnr->low = fuse->tester0;
 212        serialnr->high = fuse->tester1;
 213}
 214#endif
 215
 216void set_wdog_reset(struct wdog_regs *wdog)
 217{
 218        u32 reg = readw(&wdog->wcr);
 219        /*
 220         * Output WDOG_B signal to reset external pmic or POR_B decided by
 221         * the board desgin. Without external reset, the peripherals/DDR/
 222         * PMIC are not reset, that may cause system working abnormal.
 223         */
 224        reg = readw(&wdog->wcr);
 225        reg |= 1 << 3;
 226        /*
 227         * WDZST bit is write-once only bit. Align this bit in kernel,
 228         * otherwise kernel code will have no chance to set this bit.
 229         */
 230        reg |= 1 << 0;
 231        writew(reg, &wdog->wcr);
 232}
 233
 234/*
 235 * cfg_val will be used for
 236 * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
 237 * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0]
 238 * to SBMR1, which will determine the boot device.
 239 */
 240const struct boot_mode soc_boot_modes[] = {
 241        {"ecspi1:0",    MAKE_CFGVAL(0x00, 0x60, 0x00, 0x00)},
 242        {"ecspi1:1",    MAKE_CFGVAL(0x40, 0x62, 0x00, 0x00)},
 243        {"ecspi1:2",    MAKE_CFGVAL(0x80, 0x64, 0x00, 0x00)},
 244        {"ecspi1:3",    MAKE_CFGVAL(0xc0, 0x66, 0x00, 0x00)},
 245
 246        {"weim",        MAKE_CFGVAL(0x00, 0x50, 0x00, 0x00)},
 247        {"qspi1",       MAKE_CFGVAL(0x10, 0x40, 0x00, 0x00)},
 248        /* 4 bit bus width */
 249        {"usdhc1",      MAKE_CFGVAL(0x10, 0x10, 0x00, 0x00)},
 250        {"usdhc2",      MAKE_CFGVAL(0x10, 0x14, 0x00, 0x00)},
 251        {"usdhc3",      MAKE_CFGVAL(0x10, 0x18, 0x00, 0x00)},
 252        {"mmc1",        MAKE_CFGVAL(0x10, 0x20, 0x00, 0x00)},
 253        {"mmc2",        MAKE_CFGVAL(0x10, 0x24, 0x00, 0x00)},
 254        {"mmc3",        MAKE_CFGVAL(0x10, 0x28, 0x00, 0x00)},
 255        {NULL,          0},
 256};
 257
 258void s_init(void)
 259{
 260#if !defined CONFIG_SPL_BUILD
 261        /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
 262        asm volatile(
 263                        "mrc p15, 0, r0, c1, c0, 1\n"
 264                        "orr r0, r0, #1 << 6\n"
 265                        "mcr p15, 0, r0, c1, c0, 1\n");
 266#endif
 267        /* clock configuration. */
 268        clock_init();
 269
 270        return;
 271}
 272
 273void reset_misc(void)
 274{
 275#ifdef CONFIG_VIDEO_MXS
 276        lcdif_power_down();
 277#endif
 278}
 279
 280