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>
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 0e65aa6..bee00ca 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -29,7 +29,7 @@
 		[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 @@
 	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 @@
 	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 6810de3..5f58733 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -416,7 +416,7 @@
 /* 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 @@
 		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 e1260aa..4bccd7c0 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 bdd4727..b7cba4e 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -54,14 +54,15 @@
 };
 
 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;