[MIPS] Support for several more SNI RM models.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
new file mode 100644
index 0000000..517dc69
--- /dev/null
+++ b/arch/mips/sni/rm200.c
@@ -0,0 +1,186 @@
+/*
+ * RM200 specific code
+ *
+ * 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.
+ *
+ * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/sni.h>
+#include <asm/time.h>
+#include <asm/ds1216.h>
+#include <asm/irq_cpu.h>
+
+#define PORT(_base,_irq)				\
+	{						\
+		.iobase		= _base,		\
+		.irq		= _irq,			\
+		.uartclk	= 1843200,		\
+		.iotype		= UPIO_PORT,		\
+		.flags		= UPF_BOOT_AUTOCONF,	\
+	}
+
+static struct plat_serial8250_port rm200_data[] = {
+	PORT(0x3f8, 4),
+	PORT(0x2f8, 3),
+	{ },
+};
+
+static struct platform_device rm200_serial8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= rm200_data,
+	},
+};
+
+static struct resource snirm_82596_rm200_rsrc[] = {
+	{
+		.start = 0xb8000000,
+		.end   = 0xb80fffff,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 0xbb000000,
+		.end   = 0xbb000004,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 0xbff00000,
+		.end   = 0xbff00020,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 27,
+		.end   = 27,
+		.flags = IORESOURCE_IRQ
+	},
+	{
+		.flags = 0x00
+	}
+};
+
+static struct platform_device snirm_82596_rm200_pdev = {
+	.name           = "snirm_82596",
+	.num_resources  = ARRAY_SIZE(snirm_82596_rm200_rsrc),
+	.resource       = snirm_82596_rm200_rsrc
+};
+
+static struct resource snirm_53c710_rm200_rsrc[] = {
+	{
+		.start = 0xb9000000,
+		.end   = 0xb90fffff,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.start = 26,
+		.end   = 26,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct platform_device snirm_53c710_rm200_pdev = {
+	.name           = "snirm_53c710",
+	.num_resources  = ARRAY_SIZE(snirm_53c710_rm200_rsrc),
+	.resource       = snirm_53c710_rm200_rsrc
+};
+
+static int __init snirm_setup_devinit(void)
+{
+	if (sni_brd_type == SNI_BRD_RM200) {
+		platform_device_register(&rm200_serial8250_device);
+		platform_device_register(&snirm_82596_rm200_pdev);
+		platform_device_register(&snirm_53c710_rm200_pdev);
+	}
+	return 0;
+}
+
+device_initcall(snirm_setup_devinit);
+
+
+#define SNI_RM200_INT_STAT_REG  0xbc000000
+#define SNI_RM200_INT_ENA_REG   0xbc080000
+
+#define SNI_RM200_INT_START  24
+#define SNI_RM200_INT_END    28
+
+static void enable_rm200_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
+
+	*(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
+}
+
+void disable_rm200_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
+
+	*(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
+}
+
+void end_rm200_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_rm200_irq(irq);
+}
+
+static struct irq_chip rm200_irq_type = {
+	.typename = "RM200",
+	.ack = disable_rm200_irq,
+	.mask = disable_rm200_irq,
+	.mask_ack = disable_rm200_irq,
+	.unmask = enable_rm200_irq,
+	.end = end_rm200_irq,
+};
+
+static void sni_rm200_hwint(void)
+{
+	u32 pending = read_c0_cause() & read_c0_status();
+	u8 mask;
+	u8 stat;
+	int irq;
+
+	if (pending & C_IRQ5)
+		do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7);
+	else if (pending & C_IRQ0) {
+		clear_c0_status (IE_IRQ0);
+		mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
+		stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14;
+		irq = ffs(stat & mask & 0x1f);
+
+		if (likely(irq > 0))
+			do_IRQ (irq + SNI_RM200_INT_START - 1);
+		set_c0_status (IE_IRQ0);
+	}
+}
+
+void __init sni_rm200_irq_init(void)
+{
+	int i;
+
+	* (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f;
+
+	mips_cpu_irq_init();
+	/* Actually we've got more interrupts to handle ...  */
+	for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
+		set_irq_chip(i, &rm200_irq_type);
+	sni_hwint = sni_rm200_hwint;
+	change_c0_status(ST0_IM, IE_IRQ0);
+	setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq);
+}
+
+void sni_rm200_init(void)
+{
+	set_io_port_base(SNI_PORT_BASE + 0x02000000);
+	ioport_resource.end += 0x02000000;
+	ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE;
+	rtc_mips_get_time = ds1216_get_cmos_time;
+	board_time_init = sni_cpu_time_init;
+}