sh: SH-MobileR SH7722 CPU support.

This adds CPU support for the SH7722.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index 0582e67..d055a3e 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_CPU_SH2A)		= sh2a/
 obj-$(CONFIG_CPU_SH3)		= sh3/
 obj-$(CONFIG_CPU_SH4)		= sh4/
+obj-$(CONFIG_CPU_SH4A)		+= sh4a/
 
 obj-$(CONFIG_UBC_WAKEUP)	+= ubc.o
 obj-$(CONFIG_SH_ADC)		+= adc.o
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 6e415ba..19ca68c7 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -12,17 +12,12 @@
 obj-$(CONFIG_CPU_SUBTYPE_SH7750)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)	+= setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7760)	+= setup-sh7760.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7770)	+= setup-sh7770.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= setup-sh7780.o
-obj-$(CONFIG_CPU_SUBTYPE_SH73180)	+= setup-sh73180.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH4_202)	+= setup-sh4-202.o
 
 # Primary on-chip clocks (common)
+ifndef CONFIG_CPU_SH4A
 clock-$(CONFIG_CPU_SH4)			:= clock-sh4.o
-clock-$(CONFIG_CPU_SUBTYPE_SH73180)	:= clock-sh73180.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7770)	:= clock-sh7770.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
+endif
 
 # Additional clocks by subtype
 clock-$(CONFIG_CPU_SUBTYPE_SH4_202)	+= clock-sh4-202.o
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index afe0f1b..9031a22 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -119,11 +119,20 @@
 		break;
 	case 0x3000:
 	case 0x3003:
+	case 0x3009:
 		cpu_data->type = CPU_SH7343;
 		cpu_data->icache.ways = 4;
 		cpu_data->dcache.ways = 4;
 		cpu_data->flags |= CPU_HAS_LLSC;
 		break;
+	case 0x3008:
+		if (prr == 0xa0) {
+			cpu_data->type = CPU_SH7722;
+			cpu_data->icache.ways = 4;
+			cpu_data->dcache.ways = 4;
+			cpu_data->flags |= CPU_HAS_LLSC;
+		}
+		break;
 	case 0x8000:
 		cpu_data->type = CPU_ST40RA;
 		cpu_data->flags |= CPU_HAS_FPU;
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
new file mode 100644
index 0000000..a8f493f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the Linux/SuperH SH-4 backends.
+#
+
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7770)	+= setup-sh7770.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)	+= setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH73180)	+= setup-sh73180.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7343)	+= setup-sh7343.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7722)	+= setup-sh7722.o
+
+# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SUBTYPE_SH73180)	:= clock-sh73180.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7770)	:= clock-sh7770.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7780)	:= clock-sh7780.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7343)	:= clock-sh7343.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722)	:= clock-sh7343.o
+
+obj-y	+= $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/clock-sh73180.c
rename to arch/sh/kernel/cpu/sh4a/clock-sh73180.c
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
new file mode 100644
index 0000000..1707a21
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7343.c
+ *
+ * SH7343/SH7722 support for the clock framework
+ *
+ *  Copyright (C) 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+/*
+ * SH7343/SH7722 uses a common set of multipliers and divisors, so this
+ * is quite simple..
+ */
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
+
+static void master_clk_init(struct clk *clk)
+{
+	clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void master_clk_recalc(struct clk *clk)
+{
+	int idx = (ctrl_inl(FRQCR) & 0x000f);
+	clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_master_clk_ops = {
+	.init		= master_clk_init,
+	.recalc		= master_clk_recalc,
+};
+
+static void module_clk_init(struct clk *clk)
+{
+	clk->parent = NULL;
+	clk->rate = CONFIG_SH_PCLK_FREQ;
+}
+
+static struct clk_ops sh7343_module_clk_ops = {
+	.init		= module_clk_init,
+};
+
+static void bus_clk_init(struct clk *clk)
+{
+	clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void bus_clk_recalc(struct clk *clk)
+{
+	int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
+	clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_bus_clk_ops = {
+	.init		= bus_clk_init,
+	.recalc		= bus_clk_recalc,
+};
+
+static void cpu_clk_init(struct clk *clk)
+{
+	clk->parent = clk_get(NULL, "module_clk");
+	clk->flags |= CLK_RATE_PROPAGATES;
+	clk_set_rate(clk, clk_get_rate(clk));
+}
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+	int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
+	clk->rate = clk->parent->rate * pll_calc() *
+		multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_cpu_clk_ops = {
+	.init		= cpu_clk_init,
+	.recalc		= cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7343_clk_ops[] = {
+	&sh7343_master_clk_ops,
+	&sh7343_module_clk_ops,
+	&sh7343_bus_clk_ops,
+	&sh7343_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+	if (idx < ARRAY_SIZE(sh7343_clk_ops))
+		*ops = sh7343_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/clock-sh7770.c
rename to arch/sh/kernel/cpu/sh4a/clock-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/clock-sh7780.c
rename to arch/sh/kernel/cpu/sh4a/clock-sh7780.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh73180.c b/arch/sh/kernel/cpu/sh4a/setup-sh73180.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh73180.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh73180.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh7343.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh7343.c
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
new file mode 100644
index 0000000..7528fc6
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -0,0 +1,76 @@
+/*
+ * SH7722 Setup
+ *
+ *  Copyright (C) 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+	{
+		.mapbase	= 0xffe00000,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.type		= PORT_SCIF,
+		.irqs		= { 80, 81, 83, 82 },
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct platform_device sci_device = {
+	.name		= "sh-sci",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= sci_platform_data,
+	},
+};
+
+static struct platform_device *sh7722_devices[] __initdata = {
+	&sci_device,
+};
+
+static int __init sh7722_devices_setup(void)
+{
+	return platform_add_devices(sh7722_devices,
+				    ARRAY_SIZE(sh7722_devices));
+}
+__initcall(sh7722_devices_setup);
+
+static struct ipr_data sh7722_ipr_map[] = {
+	/* IRQ, IPR-idx, shift, prio */
+	{ 16, 0, 12, 2 }, /* TMU0 */
+	{ 17, 0,  8, 2 }, /* TMU1 */
+};
+
+static unsigned long ipr_offsets[] = {
+	0xa4080000, /*  0: IPRA */
+	0xa4080004, /*  1: IPRB */
+	0xa4080008, /*  2: IPRC */
+	0xa408000c, /*  3: IPRD */
+	0xa4080010, /*  4: IPRE */
+	0xa4080014, /*  5: IPRF */
+	0xa4080018, /*  6: IPRG */
+	0xa408001c, /*  7: IPRH */
+	0xa4080020, /*  8: IPRI */
+	0xa4080024, /*  9: IPRJ */
+	0xa4080028, /* 10: IPRK */
+	0xa408002c, /* 11: IPRL */
+};
+
+unsigned int map_ipridx_to_addr(int idx)
+{
+	if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
+		return 0;
+	return ipr_offsets[idx];
+}
+
+void __init init_IRQ_ipr(void)
+{
+	make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
+}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh7770.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
similarity index 100%
rename from arch/sh/kernel/cpu/sh4/setup-sh7780.c
rename to arch/sh/kernel/cpu/sh4a/setup-sh7780.c
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index f8dd6b7..fe545bb 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -325,14 +325,18 @@
 	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
 	if (&__rd_start != &__rd_end) {
 		LOADER_TYPE = 1;
-		INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START;
-		INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start;
+		INITRD_START = PHYSADDR((unsigned long)&__rd_start) -
+					__MEMORY_START;
+		INITRD_SIZE = (unsigned long)&__rd_end -
+			      (unsigned long)&__rd_start;
 	}
 
 	if (LOADER_TYPE && INITRD_START) {
 		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
-			reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
-			initrd_start = INITRD_START + PAGE_OFFSET + __MEMORY_START;
+			reserve_bootmem_node(NODE_DATA(0), INITRD_START +
+						__MEMORY_START, INITRD_SIZE);
+			initrd_start = INITRD_START + PAGE_OFFSET +
+					__MEMORY_START;
 			initrd_end = initrd_start + INITRD_SIZE;
 		} else {
 			printk("initrd extends beyond end of memory "
@@ -404,7 +408,7 @@
 	[CPU_SH4_202]	= "SH4-202",	[CPU_SH4_501]	= "SH4-501",
 	[CPU_SH7770]	= "SH7770",	[CPU_SH7780]	= "SH7780",
 	[CPU_SH7781]	= "SH7781",	[CPU_SH7343]	= "SH7343",
-	[CPU_SH7785]	= "SH7785",
+	[CPU_SH7785]	= "SH7785",	[CPU_SH7722]	= "SH7722",
 	[CPU_SH_NONE]	= "Unknown"
 };
 
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 4e0362f..29f4ee3 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -35,6 +35,9 @@
 	select CPU_SH4
 	select CPU_HAS_INTC2_IRQ
 
+config CPU_SHX2
+	bool
+
 #
 # Processor subtypes
 #
@@ -180,6 +183,7 @@
 config CPU_SUBTYPE_SH7785
 	bool "Support SH7785 processor"
 	select CPU_SH4A
+	select CPU_SHX2
 	select CPU_HAS_INTC2_IRQ
 
 comment "SH4AL-DSP Processor Support"
@@ -192,6 +196,12 @@
 	bool "Support SH7343 processor"
 	select CPU_SH4AL_DSP
 
+config CPU_SUBTYPE_SH7722
+	bool "Support SH7722 processor"
+	select CPU_SH4AL_DSP
+	select CPU_SHX2
+	select CPU_HAS_IPR_IRQ
+
 endmenu
 
 menu "Memory management options"
@@ -250,7 +260,7 @@
 
 config X2TLB
 	bool "Enable extended TLB mode"
-	depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL
+	depends on CPU_SHX2 && MMU && EXPERIMENTAL
 	help
 	  Selecting this option will enable the extended mode of the SH-X2
 	  TLB. For legacy SH-X behaviour and interoperability, say N. For