patch-2.4.19 linux-2.4.19/arch/mips/vr4181/common/irq.c

Next file: linux-2.4.19/arch/mips/vr4181/common/serial.c
Previous file: linux-2.4.19/arch/mips/vr4181/common/int_handler.S
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/arch/mips/vr4181/common/irq.c linux-2.4.19/arch/mips/vr4181/common/irq.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * linux/arch/mips/vr4181/common/irq.c
+ *	Completely re-written to use the new irq.c
+ *
+ * Credits to Bradley D. LaRonde and Michael Klar for writing the original
+ * irq.c file which was derived from the common irq.c file.
+ *	
+ * 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/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/gdb-stub.h>
+
+#include <asm/vr4181/vr4181.h>
+
+/*
+ * Strategy:
+ *
+ * We essentially have three irq controllers, CPU, system, and gpio.
+ *
+ * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and
+ * CONFIG_IRQ_CPU config option.
+ *
+ * We here provide sys_irq and gpio_irq controller code.
+ */
+
+static int sys_irq_base;
+static int gpio_irq_base;
+
+/* ---------------------- sys irq ------------------------ */
+static void
+sys_irq_enable(unsigned int irq)
+{
+	irq -= sys_irq_base;
+	if (irq < 16) {
+		*VR4181_MSYSINT1REG |= (u16)(1 << irq);
+	} else {
+		irq -= 16;
+		*VR4181_MSYSINT2REG |= (u16)(1 << irq);
+	}
+}
+
+static void
+sys_irq_disable(unsigned int irq)
+{
+	irq -= sys_irq_base;
+	if (irq < 16) {
+		*VR4181_MSYSINT1REG &= ~((u16)(1 << irq));
+	} else {
+		irq -= 16;
+		*VR4181_MSYSINT2REG &= ~((u16)(1 << irq));
+	}
+
+}
+
+static unsigned int
+sys_irq_startup(unsigned int irq)
+{
+	sys_irq_enable(irq);
+	return 0;
+}
+
+#define sys_irq_shutdown	sys_irq_disable
+#define sys_irq_ack		sys_irq_disable
+
+static void
+sys_irq_end(unsigned int irq)
+{
+	if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		sys_irq_enable(irq);
+}
+
+static hw_irq_controller sys_irq_controller = {
+	"vr4181_sys_irq",
+	sys_irq_startup,
+	sys_irq_shutdown,
+	sys_irq_enable,
+	sys_irq_disable,
+	sys_irq_ack,
+	sys_irq_end,
+	NULL			/* no affinity stuff for UP */
+};
+
+/* ---------------------- gpio irq ------------------------ */
+/* gpio irq lines use reverse logic */
+static void
+gpio_irq_enable(unsigned int irq)
+{
+	irq -= gpio_irq_base;
+	*VR4181_GPINTMSK &= ~((u16)(1 << irq));
+}
+
+static void
+gpio_irq_disable(unsigned int irq)
+{
+	irq -= gpio_irq_base;
+	*VR4181_GPINTMSK |= (u16)(1 << irq);
+}
+
+static unsigned int
+gpio_irq_startup(unsigned int irq)
+{
+	gpio_irq_enable(irq);
+
+	irq -= gpio_irq_base;
+	*VR4181_GPINTEN |= (u16)(1 << irq );
+
+	return 0;
+}
+
+static void
+gpio_irq_shutdown(unsigned int irq)
+{
+	gpio_irq_disable(irq);
+
+	irq -= gpio_irq_base;
+	*VR4181_GPINTEN &= ~((u16)(1 << irq ));
+}
+
+static void
+gpio_irq_ack(unsigned int irq)
+{
+	u16 irqtype;
+	u16 irqshift;
+
+	gpio_irq_disable(irq);
+
+	/* we clear interrupt if it is edge triggered */
+	irq -= gpio_irq_base;
+	if (irq < 8) {
+		irqtype = *VR4181_GPINTTYPL;
+		irqshift = 2 << (irq*2);
+	} else {
+		irqtype = *VR4181_GPINTTYPH;
+		irqshift = 2 << ((irq-8)*2);
+	}
+	if ( ! (irqtype & irqshift) ) {
+		*VR4181_GPINTSTAT = (u16) (1 << irq);
+	}
+}
+
+static void
+gpio_irq_end(unsigned int irq)
+{
+	if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		gpio_irq_enable(irq);
+}
+
+static hw_irq_controller gpio_irq_controller = {
+	"vr4181_gpio_irq",
+	gpio_irq_startup,
+	gpio_irq_shutdown,
+	gpio_irq_enable,
+	gpio_irq_disable,
+	gpio_irq_ack,
+	gpio_irq_end,
+	NULL			/* no affinity stuff for UP */
+};
+
+/* ---------------------  IRQ init stuff ---------------------- */
+
+extern asmlinkage void vr4181_handle_irq(void);
+extern void breakpoint(void);
+extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
+extern void mips_cpu_irq_init(u32 irq_base);
+
+static struct irqaction cascade = 
+	{ no_action, SA_INTERRUPT, 0, "cascade", NULL, NULL };
+static struct irqaction reserved = 
+	{ no_action, SA_INTERRUPT, 0, "cascade", NULL, NULL };
+
+void __init init_IRQ(void)
+{
+	int i;
+	extern irq_desc_t irq_desc[];
+
+	set_except_vector(0, vr4181_handle_irq);
+
+	/* init CPU irqs */
+	mips_cpu_irq_init(VR4181_CPU_IRQ_BASE);
+
+	/* init sys irqs */
+	sys_irq_base = VR4181_SYS_IRQ_BASE;
+	for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &sys_irq_controller;
+	}
+
+	/* init gpio irqs */
+	gpio_irq_base = VR4181_GPIO_IRQ_BASE;
+	for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &gpio_irq_controller;
+	}
+
+	/* Default all ICU IRQs to off ... */
+	*VR4181_MSYSINT1REG = 0;
+	*VR4181_MSYSINT2REG = 0;
+ 
+	/* We initialize the level 2 ICU registers to all bits disabled. */
+	*VR4181_MPIUINTREG = 0;
+	*VR4181_MAIUINTREG = 0;
+	*VR4181_MKIUINTREG = 0;
+
+	/* disable all GPIO intrs */
+	*VR4181_GPINTMSK = 0xffff;
+
+	/* vector handler.  What these do is register the IRQ as non-sharable */
+	setup_irq(VR4181_IRQ_INT0, &cascade);
+	setup_irq(VR4181_IRQ_GIU, &cascade);
+
+	/* 
+	 * RTC interrupts are interesting.  They have two destinations.
+	 * One is at sys irq controller, and the other is at CPU IP3 and IP4.
+	 * RTC timer is used as system timer.
+	 * We enable them here, but timer routine will register later
+	 * with CPU IP3/IP4.
+	 */
+	setup_irq(VR4181_IRQ_RTCL1, &reserved);
+	setup_irq(VR4181_IRQ_RTCL2, &reserved);
+
+#ifdef CONFIG_REMOTE_DEBUG
+	printk("Setting debug traps - please connect the remote debugger.\n");
+
+	set_debug_traps();
+
+	// you may move this line to whereever you want
+	breakpoint();
+#endif
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)