summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-09-27 18:27:43 +0900
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 18:27:43 +0900
commit72c35543f8cf1316773ffbd9619575bb84ac44fb (patch)
tree5dc8ba51079cbc65be0ee0e881da03e6ac0b0b5b
parent9d549a7d8ef71f684a35cf1e438543957cf81d12 (diff)
sh: Support for L2 cache on newer SH-4A CPUs.
This implements preliminary support for the L2 caches found on newer SH-4A CPUs. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c47
-rw-r--r--arch/sh/kernel/setup.c6
-rw-r--r--include/asm-sh/cpu-features.h1
-rw-r--r--include/asm-sh/processor.h9
4 files changed, 57 insertions, 6 deletions
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 0e65aa6ddcaa..bee00cac0b16 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -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));
@@ -54,6 +54,26 @@ int __init detect_cpu_and_cache_system(void)
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;
}
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 6810de3f8ed2..5f587332234a 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -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);
diff --git a/include/asm-sh/cpu-features.h b/include/asm-sh/cpu-features.h
index e1260aae3ee3..4bccd7c032f9 100644
--- a/include/asm-sh/cpu-features.h
+++ b/include/asm-sh/cpu-features.h
@@ -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 */
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index bdd472705546..b7cba4e91a72 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -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;