sh: Support for L2 cache on newer SH-4A CPUs.
authorPaul Mundt <lethal@linux-sh.org>
Wed, 27 Sep 2006 09:27:43 +0000 (18:27 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 27 Sep 2006 09:27:43 +0000 (18:27 +0900)
This implements preliminary support for the L2 caches found
on newer SH-4A CPUs.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/setup.c
include/asm-sh/cpu-features.h
include/asm-sh/processor.h

index 0e65aa6ddcaace738d05600827a08c8a2d3ed002..bee00cac0b169cf5e3515a3e1ded4acdf4531dff 100644 (file)
@@ -29,7 +29,7 @@ int __init detect_cpu_and_cache_system(void)
                [9] = (1 << 16)
        };
 
-       pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff;
+       pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff;
        prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
        cvr = (ctrl_inl(CCN_CVR));
 
@@ -53,6 +53,26 @@ int __init detect_cpu_and_cache_system(void)
        cpu_data->dcache.ways           = 1;
        cpu_data->dcache.linesz         = L1_CACHE_BYTES;
 
+       /*
+        * Setup some generic flags we can probe
+        * (L2 and DSP detection only work on SH-4A)
+        */
+       if (((pvr >> 16) & 0xff) == 0x10) {
+               if ((cvr & 0x02000000) == 0)
+                       cpu_data->flags |= CPU_HAS_L2_CACHE;
+               if ((cvr & 0x10000000) == 0)
+                       cpu_data->flags |= CPU_HAS_DSP;
+
+               cpu_data->flags |= CPU_HAS_LLSC;
+       }
+
+       /* FPU detection works for everyone */
+       if ((cvr & 0x20000000) == 1)
+               cpu_data->flags |= CPU_HAS_FPU;
+
+       /* Mask off the upper chip ID */
+       pvr &= 0xffff;
+
        /*
         * Probe the underlying processor version/revision and
         * adjust cpu_data setup accordingly.
@@ -181,5 +201,30 @@ int __init detect_cpu_and_cache_system(void)
        cpu_data->dcache.way_size = cpu_data->dcache.sets *
                                    cpu_data->dcache.linesz;
 
+       /*
+        * Setup the L2 cache desc
+        *
+        * SH-4A's have an optional PIPT L2.
+        */
+       if (cpu_data->flags & CPU_HAS_L2_CACHE) {
+               /*
+                * Size calculation is much more sensible
+                * than it is for the L1.
+                *
+                * Sizes are 128KB, 258KB, 512KB, and 1MB.
+                */
+               size = (cvr & 0xf) << 17;
+
+               BUG_ON(!size);
+
+               cpu_data->scache.way_incr       = (1 << 16);
+               cpu_data->scache.entry_shift    = 5;
+               cpu_data->scache.entry_mask     = 0xffe0;
+               cpu_data->scache.ways           = 4;
+               cpu_data->scache.linesz         = L1_CACHE_BYTES;
+               cpu_data->scache.sets           = size /
+                       (cpu_data->scache.linesz * cpu_data->scache.ways);
+       }
+
        return 0;
 }
index 6810de3f8ed27a66fb61cba2171cb106bb571cfe..5f587332234a3e977cf1203477831dddfb446f50 100644 (file)
@@ -416,7 +416,7 @@ const char *get_cpu_subtype(void)
 /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
        "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
-       "ptea", "llsc", NULL
+       "ptea", "llsc", "l2", NULL
 };
 
 static void show_cpuflags(struct seq_file *m)
@@ -480,6 +480,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                show_cacheinfo(m, "dcache", boot_cpu_data.dcache);
        }
 
+       /* Optional secondary cache */
+       if (boot_cpu_data.flags & CPU_HAS_L2_CACHE)
+               show_cacheinfo(m, "scache", boot_cpu_data.scache);
+
        seq_printf(m, "bogomips\t: %lu.%02lu\n",
                     boot_cpu_data.loops_per_jiffy/(500000/HZ),
                     (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100);
index e1260aae3ee3978d879ea7000120232bbf1dbcba..4bccd7c032f9c3d2320c8c7735b7fb5a0d02937b 100644 (file)
@@ -19,5 +19,6 @@
 #define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
 #define CPU_HAS_PTEA           0x0020  /* PTEA register */
 #define CPU_HAS_LLSC           0x0040  /* movli.l/movco.l */
+#define CPU_HAS_L2_CACHE       0x0080  /* Secondary cache / URAM */
 
 #endif /* __ASM_SH_CPU_FEATURES_H */
index bdd472705546fd18e7de45888a2e48c9fa3db4fb..b7cba4e91a725d9f6447a5114ff164975b627ece 100644 (file)
@@ -54,14 +54,15 @@ enum cpu_type {
 };
 
 struct sh_cpuinfo {
-       enum cpu_type type;
+       unsigned int type;
        unsigned long loops_per_jiffy;
 
-       struct cache_info icache;
-       struct cache_info dcache;
+       struct cache_info icache;       /* Primary I-cache */
+       struct cache_info dcache;       /* Primary D-cache */
+       struct cache_info scache;       /* Secondary cache */
 
        unsigned long flags;
-};
+} __attribute__ ((aligned(SMP_CACHE_BYTES)));
 
 extern struct sh_cpuinfo boot_cpu_data;