#include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
+#include <asm/mips-cm.h>
 
 /*
  * MIPS32/MIPS64 L2 cache handling
        return 1;
 }
 
+static int __init mips_sc_probe_cm3(void)
+{
+       struct cpuinfo_mips *c = ¤t_cpu_data;
+       unsigned long cfg = read_gcr_l2_config();
+       unsigned long sets, line_sz, assoc;
+
+       if (cfg & CM_GCR_L2_CONFIG_BYPASS_MSK)
+               return 0;
+
+       sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
+       sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
+       c->scache.sets = 64 << sets;
+
+       line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
+       line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
+       c->scache.linesz = 2 << line_sz;
+
+       assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
+       assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
+       c->scache.ways = assoc + 1;
+       c->scache.waysize = c->scache.sets * c->scache.linesz;
+       c->scache.waybit = __ffs(c->scache.waysize);
+
+       c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+
+       return 1;
+}
+
 static inline int __init mips_sc_probe(void)
 {
        struct cpuinfo_mips *c = ¤t_cpu_data;
        /* Mark as not present until probe completed */
        c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
+       if (mips_cm_revision() >= CM_REV_CM3)
+               return mips_sc_probe_cm3();
+
        /* Ignore anything but MIPSxx processors */
        if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
                              MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R1 |