MIPS: PowerTV: Base files for Cisco PowerTV platform

Add the Cisco Powertv cable settop box to the MIPS tree. This platform is
based on a MIPS 24Kc processor with various devices integrated on the same
ASIC. There are multiple models of this box, with differing configuration
but the same kernel runs across the product line.

Signed-off-by: David VomLehn <dvomlehn@cisco.com>
Cc: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/132/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
new file mode 100644
index 0000000..b54d244
--- /dev/null
+++ b/arch/mips/powertv/asic/irq_asic.c
@@ -0,0 +1,116 @@
+/*
+ * Portions copyright (C) 2005-2009 Scientific Atlanta
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ * Modified from arch/mips/kernel/irq-rm7000.c:
+ * Copyright (C) 2003 Ralf Baechle
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <asm/mach-powertv/asic_regs.h>
+
+static inline void unmask_asic_irq(unsigned int irq)
+{
+	unsigned long enable_bit;
+
+	enable_bit = (1 << (irq & 0x1f));
+
+	switch (irq >> 5) {
+	case 0:
+		asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
+		break;
+	case 1:
+		asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
+		break;
+	case 2:
+		asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
+		break;
+	case 3:
+		asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void mask_asic_irq(unsigned int irq)
+{
+	unsigned long disable_mask;
+
+	disable_mask = ~(1 << (irq & 0x1f));
+
+	switch (irq >> 5) {
+	case 0:
+		asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
+		break;
+	case 1:
+		asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
+		break;
+	case 2:
+		asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
+		break;
+	case 3:
+		asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static struct irq_chip asic_irq_chip = {
+	.name = "ASIC Level",
+	.ack = mask_asic_irq,
+	.mask = mask_asic_irq,
+	.mask_ack = mask_asic_irq,
+	.unmask = unmask_asic_irq,
+	.eoi = unmask_asic_irq,
+};
+
+void __init asic_irq_init(void)
+{
+	int i;
+
+	/* set priority to 0 */
+	write_c0_status(read_c0_status() & ~(0x0000fc00));
+
+	asic_write(0, ien_int_0);
+	asic_write(0, ien_int_1);
+	asic_write(0, ien_int_2);
+	asic_write(0, ien_int_3);
+
+	asic_write(0x0fffffff, int_level_3_3);
+	asic_write(0xffffffff, int_level_3_2);
+	asic_write(0xffffffff, int_level_3_1);
+	asic_write(0xffffffff, int_level_3_0);
+	asic_write(0xffffffff, int_level_2_3);
+	asic_write(0xffffffff, int_level_2_2);
+	asic_write(0xffffffff, int_level_2_1);
+	asic_write(0xffffffff, int_level_2_0);
+	asic_write(0xffffffff, int_level_1_3);
+	asic_write(0xffffffff, int_level_1_2);
+	asic_write(0xffffffff, int_level_1_1);
+	asic_write(0xffffffff, int_level_1_0);
+	asic_write(0xffffffff, int_level_0_3);
+	asic_write(0xffffffff, int_level_0_2);
+	asic_write(0xffffffff, int_level_0_1);
+	asic_write(0xffffffff, int_level_0_0);
+
+	asic_write(0xf, int_int_scan);
+
+	/*
+	 * Initialize interrupt handlers.
+	 */
+	for (i = 0; i < NR_IRQS; i++)
+		set_irq_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
+}