imx: mx6 correct get_cpu_rev
[oweals/u-boot.git] / arch / arm / cpu / armv7 / mx6 / soc.c
index ef029722b455d7c12012de2d6178d7a58e146dd6..29de6243dc98fb05eeddc7fde4772e08a94fa6a2 100644 (file)
@@ -21,7 +21,6 @@
 #include <stdbool.h>
 #include <asm/arch/mxc_hdmi.h>
 #include <asm/arch/crm_regs.h>
-#include <asm/bootm.h>
 #include <dm.h>
 #include <imx_thermal.h>
 
@@ -63,6 +62,7 @@ u32 get_cpu_rev(void)
        struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
        u32 reg = readl(&anatop->digprog_sololite);
        u32 type = ((reg >> 16) & 0xff);
+       u32 major;
 
        if (type != MXC_CPU_MX6SL) {
                reg = readl(&anatop->digprog);
@@ -80,8 +80,88 @@ u32 get_cpu_rev(void)
                }
 
        }
+       major = ((reg >> 8) & 0xff);
        reg &= 0xff;            /* mx6 silicon revision */
-       return (type << 12) | (reg + 0x10);
+       return (type << 12) | (reg + (0x10 * (major + 1)));
+}
+
+/*
+ * OCOTP_CFG3[17:16] (see Fusemap Description Table offset 0x440)
+ * defines a 2-bit SPEED_GRADING
+ */
+#define OCOTP_CFG3_SPEED_SHIFT 16
+#define OCOTP_CFG3_SPEED_800MHZ        0
+#define OCOTP_CFG3_SPEED_850MHZ        1
+#define OCOTP_CFG3_SPEED_1GHZ  2
+#define OCOTP_CFG3_SPEED_1P2GHZ        3
+
+u32 get_cpu_speed_grade_hz(void)
+{
+       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;
+       uint32_t val;
+
+       val = readl(&fuse->cfg3);
+       val >>= OCOTP_CFG3_SPEED_SHIFT;
+       val &= 0x3;
+
+       switch (val) {
+       /* Valid for IMX6DQ */
+       case OCOTP_CFG3_SPEED_1P2GHZ:
+               if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
+                       return 1200000000;
+       /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
+       case OCOTP_CFG3_SPEED_1GHZ:
+               return 996000000;
+       /* Valid for IMX6DQ */
+       case OCOTP_CFG3_SPEED_850MHZ:
+               if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
+                       return 852000000;
+       /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
+       case OCOTP_CFG3_SPEED_800MHZ:
+               return 792000000;
+       }
+       return 0;
+}
+
+/*
+ * OCOTP_MEM0[7:6] (see Fusemap Description Table offset 0x480)
+ * defines a 2-bit Temperature Grade
+ *
+ * return temperature grade and min/max temperature in celcius
+ */
+#define OCOTP_MEM0_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->mem0);
+       val >>= OCOTP_MEM0_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;
 }
 
 #ifdef CONFIG_REVISION_TAG
@@ -289,6 +369,22 @@ static void set_preclk_from_osc(void)
 }
 #endif
 
+#define SRC_SCR_WARM_RESET_ENABLE      0
+
+static void init_src(void)
+{
+       struct src *src_regs = (struct src *)SRC_BASE_ADDR;
+       u32 val;
+
+       /*
+        * force warm reset sources to generate cold reset
+        * for a more reliable restart
+        */
+       val = readl(&src_regs->scr);
+       val &= ~(1 << SRC_SCR_WARM_RESET_ENABLE);
+       writel(val, &src_regs->scr);
+}
+
 int arch_cpu_init(void)
 {
        init_aips();
@@ -323,6 +419,8 @@ int arch_cpu_init(void)
        mxs_dma_init();
 #endif
 
+       init_src();
+
        return 0;
 }
 
@@ -506,6 +604,14 @@ void v7_outer_cache_enable(void)
        struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE;
        unsigned int val;
 
+
+       /*
+        * Set bit 22 in the auxiliary control register. If this bit
+        * is cleared, PL310 treats Normal Shared Non-cacheable
+        * accesses as Cacheable no-allocate.
+        */
+       setbits_le32(&pl310->pl310_aux_ctrl, L310_SHARED_ATT_OVERRIDE_ENABLE);
+
 #if defined CONFIG_MX6SL
        struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
        val = readl(&iomux->gpr[11]);