imx: imx7d: Add SoC system support
authorAdrian Alonso <aalonso@freescale.com>
Wed, 2 Sep 2015 18:54:19 +0000 (13:54 -0500)
committerStefano Babic <sbabic@denx.de>
Sun, 13 Sep 2015 08:11:53 +0000 (10:11 +0200)
Add imx7d basic SoC system support
Misc arch dependent functions for system bring up

Signed-off-by: Adrian Alonso <aalonso@freescale.com>
Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Signed-off-by: Ye.Li <B37916@freescale.com>
arch/arm/cpu/armv7/mx7/soc.c [new file with mode: 0644]
arch/arm/include/asm/arch-imx/cpu.h
arch/arm/include/asm/imx-common/boot_mode.h

diff --git a/arch/arm/cpu/armv7/mx7/soc.c b/arch/arm/cpu/armv7/mx7/soc.c
new file mode 100644 (file)
index 0000000..8d50149
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/imx-common/boot_mode.h>
+#include <asm/imx-common/dma.h>
+#include <asm/arch/crm_regs.h>
+#include <dm.h>
+#include <imx_thermal.h>
+
+struct src *src_reg = (struct src *)SRC_BASE_ADDR;
+
+#if defined(CONFIG_IMX_THERMAL)
+static const struct imx_thermal_plat imx7_thermal_plat = {
+       .regs = (void *)ANATOP_BASE_ADDR,
+       .fuse_bank = 3,
+       .fuse_word = 3,
+};
+
+U_BOOT_DEVICE(imx7_thermal) = {
+       .name = "imx_thermal",
+       .platdata = &imx7_thermal_plat,
+};
+#endif
+
+/*
+ * OCOTP_TESTER3[9:8] (see Fusemap Description Table offset 0x440)
+ * defines a 2-bit SPEED_GRADING
+ */
+#define OCOTP_TESTER3_SPEED_SHIFT      8
+#define OCOTP_TESTER3_SPEED_800MHZ     0
+#define OCOTP_TESTER3_SPEED_850MHZ     1
+#define OCOTP_TESTER3_SPEED_1GHZ       2
+
+u32 get_cpu_speed_grade_hz(void)
+{
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[1];
+       struct fuse_bank1_regs *fuse =
+               (struct fuse_bank1_regs *)bank->fuse_regs;
+       uint32_t val;
+
+       val = readl(&fuse->tester3);
+       val >>= OCOTP_TESTER3_SPEED_SHIFT;
+       val &= 0x3;
+
+       switch(val) {
+       case OCOTP_TESTER3_SPEED_800MHZ:
+               return 792000000;
+       case OCOTP_TESTER3_SPEED_850MHZ:
+               return 852000000;
+       case OCOTP_TESTER3_SPEED_1GHZ:
+               return 996000000;
+       }
+       return 0;
+}
+
+/*
+ * OCOTP_TESTER3[7:6] (see Fusemap Description Table offset 0x440)
+ * defines a 2-bit SPEED_GRADING
+ */
+#define OCOTP_TESTER3_TEMP_SHIFT       6
+
+u32 get_cpu_temp_grade(int *minc, int *maxc)
+{
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[1];
+       struct fuse_bank1_regs *fuse =
+               (struct fuse_bank1_regs *)bank->fuse_regs;
+       uint32_t val;
+
+       val = readl(&fuse->tester3);
+       val >>= OCOTP_TESTER3_TEMP_SHIFT;
+       val &= 0x3;
+
+       if (minc && maxc) {
+               if ( val == TEMP_AUTOMOTIVE) {
+                       *minc = -40;
+                       *maxc = 125;
+               } else if (val == TEMP_INDUSTRIAL) {
+                       *minc = -40;
+                       *maxc = 105;
+               } else if (val == TEMP_EXTCOMMERCIAL) {
+                       *minc = -20;
+                       *maxc = 105;
+               } else {
+                       *minc = 0;
+                       *maxc = 95;
+               }
+       }
+       return val;
+}
+
+u32 get_cpu_rev(void)
+{
+       struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *)
+                                                ANATOP_BASE_ADDR;
+       u32 reg = readl(&ccm_anatop->digprog);
+       u32 type = (reg >> 16) & 0xff;
+
+       reg &= 0xff;
+       return (type << 12) | reg;
+}
+
+#ifdef CONFIG_REVISION_TAG
+u32 __weak get_board_rev(void)
+{
+       return get_cpu_rev();
+}
+#endif
+
+int arch_cpu_init(void)
+{
+       init_aips();
+
+       /* Disable PDE bit of WMCR register */
+       imx_set_wdog_powerdown(false);
+
+#ifdef CONFIG_APBH_DMA
+       /* Start APBH DMA */
+       mxs_dma_init();
+#endif
+
+       return 0;
+}
+
+#ifdef CONFIG_SERIAL_TAG
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[0];
+       struct fuse_bank0_regs *fuse =
+               (struct fuse_bank0_regs *)bank->fuse_regs;
+
+       serialnr->low = fuse->tester0;
+       serialnr->high = fuse->tester1;
+}
+#endif
+
+#if defined(CONFIG_FEC_MXC)
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[9];
+       struct fuse_bank9_regs *fuse =
+               (struct fuse_bank9_regs *)bank->fuse_regs;
+
+       if (0 == dev_id) {
+               u32 value = readl(&fuse->mac_addr1);
+               mac[0] = (value >> 8);
+               mac[1] = value;
+
+               value = readl(&fuse->mac_addr0);
+               mac[2] = value >> 24;
+               mac[3] = value >> 16;
+               mac[4] = value >> 8;
+               mac[5] = value;
+       } else {
+               u32 value = readl(&fuse->mac_addr2);
+               mac[0] = value >> 24;
+               mac[1] = value >> 16;
+               mac[2] = value >> 8;
+               mac[3] = value;
+
+               value = readl(&fuse->mac_addr1);
+               mac[4] = value >> 24;
+               mac[5] = value >> 16;
+       }
+}
+#endif
+
+void set_wdog_reset(struct wdog_regs *wdog)
+{
+       u32 reg = readw(&wdog->wcr);
+       /*
+        * Output WDOG_B signal to reset external pmic or POR_B decided by
+        * the board desgin. Without external reset, the peripherals/DDR/
+        * PMIC are not reset, that may cause system working abnormal.
+        */
+       reg = readw(&wdog->wcr);
+       reg |= 1 << 3;
+       /*
+        * WDZST bit is write-once only bit. Align this bit in kernel,
+        * otherwise kernel code will have no chance to set this bit.
+        */
+       reg |= 1 << 0;
+       writew(reg, &wdog->wcr);
+}
+
+/*
+ * cfg_val will be used for
+ * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0]
+ * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0]
+ * to SBMR1, which will determine the boot device.
+ */
+const struct boot_mode soc_boot_modes[] = {
+       {"ecspi1:0",    MAKE_CFGVAL(0x00, 0x60, 0x00, 0x00)},
+       {"ecspi1:1",    MAKE_CFGVAL(0x40, 0x62, 0x00, 0x00)},
+       {"ecspi1:2",    MAKE_CFGVAL(0x80, 0x64, 0x00, 0x00)},
+       {"ecspi1:3",    MAKE_CFGVAL(0xc0, 0x66, 0x00, 0x00)},
+
+       {"weim",        MAKE_CFGVAL(0x00, 0x50, 0x00, 0x00)},
+       {"qspi1",       MAKE_CFGVAL(0x10, 0x40, 0x00, 0x00)},
+       /* 4 bit bus width */
+       {"usdhc1",      MAKE_CFGVAL(0x10, 0x10, 0x00, 0x00)},
+       {"usdhc2",      MAKE_CFGVAL(0x10, 0x14, 0x00, 0x00)},
+       {"usdhc3",      MAKE_CFGVAL(0x10, 0x18, 0x00, 0x00)},
+       {"mmc1",        MAKE_CFGVAL(0x10, 0x20, 0x00, 0x00)},
+       {"mmc2",        MAKE_CFGVAL(0x10, 0x24, 0x00, 0x00)},
+       {"mmc3",        MAKE_CFGVAL(0x10, 0x28, 0x00, 0x00)},
+       {NULL,          0},
+};
+
+enum boot_device get_boot_device(void)
+{
+       struct bootrom_sw_info **p =
+               (struct bootrom_sw_info **)ROM_SW_INFO_ADDR;
+
+       enum boot_device boot_dev = SD1_BOOT;
+       u8 boot_type = (*p)->boot_dev_type;
+       u8 boot_instance = (*p)->boot_dev_instance;
+
+       switch (boot_type) {
+       case BOOT_TYPE_SD:
+               boot_dev = boot_instance + SD1_BOOT;
+               break;
+       case BOOT_TYPE_MMC:
+               boot_dev = boot_instance + MMC1_BOOT;
+               break;
+       case BOOT_TYPE_NAND:
+               boot_dev = NAND_BOOT;
+               break;
+       case BOOT_TYPE_QSPI:
+               boot_dev = QSPI_BOOT;
+               break;
+       case BOOT_TYPE_WEIM:
+               boot_dev = WEIM_NOR_BOOT;
+               break;
+       case BOOT_TYPE_SPINOR:
+               boot_dev = SPI_NOR_BOOT;
+               break;
+       default:
+               break;
+       }
+
+       return boot_dev;
+}
+
+void s_init(void)
+{
+#if !defined CONFIG_SPL_BUILD
+       /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
+       asm volatile(
+                       "mrc p15, 0, r0, c1, c0, 1\n"
+                       "orr r0, r0, #1 << 6\n"
+                       "mcr p15, 0, r0, c1, c0, 1\n");
+#endif
+       /* clock configuration. */
+       clock_init();
+
+       return;
+}
index 416905ad06f46db3749927da4f0456b34575ca14..7e681e94d742588d4f32df4d39b8e9e0f520fde8 100644 (file)
 #define MXC_CPU_MX6D           0x67
 #define MXC_CPU_MX6DP          0x68
 #define MXC_CPU_MX6QP          0x69
+#define MXC_CPU_MX7D           0x72
 #define MXC_CPU_VF610          0xF6 /* dummy ID */
 
 #define MXC_SOC_MX6            0x60
+#define MXC_SOC_MX7            0x70
 
 #define CS0_128                                        0
 #define CS0_64M_CS1_64M                                1
index de0205c115554a8015547a94745a8bf6fded0248..a8239f2f7a51c78ca8240d6883fca04b61c807d1 100644 (file)
@@ -9,6 +9,27 @@
 #define MAKE_CFGVAL(cfg1, cfg2, cfg3, cfg4) \
        ((cfg4) << 24) | ((cfg3) << 16) | ((cfg2) << 8) | (cfg1)
 
+enum boot_device {
+       WEIM_NOR_BOOT,
+       ONE_NAND_BOOT,
+       PATA_BOOT,
+       SATA_BOOT,
+       I2C_BOOT,
+       SPI_NOR_BOOT,
+       SD1_BOOT,
+       SD2_BOOT,
+       SD3_BOOT,
+       SD4_BOOT,
+       MMC1_BOOT,
+       MMC2_BOOT,
+       MMC3_BOOT,
+       MMC4_BOOT,
+       NAND_BOOT,
+       QSPI_BOOT,
+       UNKNOWN_BOOT,
+       BOOT_DEV_NUM = UNKNOWN_BOOT,
+};
+
 struct boot_mode {
        const char *name;
        unsigned cfg_val;