Merge tag 'for-linus-4.3-merge-window-part-1' of git://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / mips / kernel / cpu-probe.c
index dbe0792..571a8e6 100644 (file)
@@ -32,6 +32,9 @@
 #include <asm/spram.h>
 #include <asm/uaccess.h>
 
+/* Hardware capabilities */
+unsigned int elf_hwcap __read_mostly;
+
 /*
  * Get the FPU Implementation/Revision.
  */
@@ -188,7 +191,7 @@ __setup("nohtw", htw_disable);
 static int mips_ftlb_disabled;
 static int mips_has_ftlb_configured;
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable);
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable);
 
 static int __init ftlb_disable(char *s)
 {
@@ -202,7 +205,10 @@ static int __init ftlb_disable(char *s)
                return 1;
 
        /* Disable it in the boot cpu */
-       set_ftlb_enable(&cpu_data[0], 0);
+       if (set_ftlb_enable(&cpu_data[0], 0)) {
+               pr_warn("Can't turn FTLB off\n");
+               return 1;
+       }
 
        back_to_back_c0_hazard();
 
@@ -364,30 +370,41 @@ static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
                return 3;
 }
 
-static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
+static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
-       unsigned int config6;
+       unsigned int config;
 
        /* It's implementation dependent how the FTLB can be enabled */
        switch (c->cputype) {
        case CPU_PROAPTIV:
        case CPU_P5600:
                /* proAptiv & related cores use Config6 to enable the FTLB */
-               config6 = read_c0_config6();
+               config = read_c0_config6();
                /* Clear the old probability value */
-               config6 &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
+               config &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
                if (enable)
                        /* Enable FTLB */
-                       write_c0_config6(config6 |
+                       write_c0_config6(config |
                                         (calculate_ftlb_probability(c)
                                          << MIPS_CONF6_FTLBP_SHIFT)
                                         | MIPS_CONF6_FTLBEN);
                else
                        /* Disable FTLB */
-                       write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
-               back_to_back_c0_hazard();
+                       write_c0_config6(config &  ~MIPS_CONF6_FTLBEN);
                break;
+       case CPU_I6400:
+               /* I6400 & related cores use Config7 to configure FTLB */
+               config = read_c0_config7();
+               /* Clear the old probability value */
+               config &= ~(3 << MIPS_CONF7_FTLBP_SHIFT);
+               write_c0_config7(config | (calculate_ftlb_probability(c)
+                                          << MIPS_CONF7_FTLBP_SHIFT));
+               break;
+       default:
+               return 1;
        }
+
+       return 0;
 }
 
 static inline unsigned int decode_config0(struct cpuinfo_mips *c)
@@ -524,6 +541,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
        }
        if (config3 & MIPS_CONF3_CDMM)
                c->options |= MIPS_CPU_CDMM;
+       if (config3 & MIPS_CONF3_SP)
+               c->options |= MIPS_CPU_SP;
 
        return config3 & MIPS_CONF_M;
 }
@@ -540,7 +559,16 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
        if (cpu_has_tlb) {
                if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
                        c->options |= MIPS_CPU_TLBINV;
-               mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+               /*
+                * This is a bit ugly. R6 has dropped that field from
+                * config4 and the only valid configuration is VTLB+FTLB so
+                * set a good value for mmuextdef for that case.
+                */
+               if (cpu_has_mips_r6)
+                       mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
+               else
+                       mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+
                switch (mmuextdef) {
                case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
                        c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
@@ -1121,6 +1149,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_P5600;
                __cpu_name[cpu] = "MIPS P5600";
                break;
+       case PRID_IMP_I6400:
+               c->cputype = CPU_I6400;
+               __cpu_name[cpu] = "MIPS I6400";
+               break;
        case PRID_IMP_M5150:
                c->cputype = CPU_M5150;
                __cpu_name[cpu] = "MIPS M5150";
@@ -1492,10 +1524,14 @@ void cpu_probe(void)
        else
                c->srsets = 1;
 
+       if (cpu_has_mips_r6)
+               elf_hwcap |= HWCAP_MIPS_R6;
+
        if (cpu_has_msa) {
                c->msa_id = cpu_get_msa_id();
                WARN(c->msa_id & MSA_IR_WRPF,
                     "Vector register partitioning unimplemented!");
+               elf_hwcap |= HWCAP_MIPS_MSA;
        }
 
        cpu_probe_vmbits(c);