m68knommu: use general interrupt controller for ColdFire 520x family
authorGreg Ungerer <gerg@uclinux.org>
Mon, 27 Apr 2009 05:09:29 +0000 (15:09 +1000)
committerGreg Ungerer <gerg@uclinux.org>
Tue, 15 Sep 2009 23:43:39 +0000 (09:43 +1000)
Create general interrupt controller code for the ColdFire 520x family,
that does proper masking and unmasking of interrupts. With this in
place some of the driver hacks in place to support ColdFire interrupts
can finally go away.

Within the ColdFire family there is a variety of different interrupt
controllers in use. Some are used on multiple parts, some on only one.
There is quite some differences in some varients, so much so that
common code for all ColdFire parts would be impossible.

This commit introduces code to support one of the newer interrupt
controllers in the ColdFire 5208 and 5207 parts. It has very simple
mask and unmask operations, so is one of the easiest to support.

Signed-off-by: Greg Ungerer <gerg@uclinux.org>
arch/m68k/include/asm/m520xsim.h
arch/m68knommu/kernel/irq.c
arch/m68knommu/platform/coldfire/Makefile
arch/m68knommu/platform/coldfire/intc-simr.c [new file with mode: 0644]

index e80b6a54ea9c260649ee78f5aa6c7dcca6ed2e1d..e79b9bc76a123805f5b3b5a8402bebdc9f4b39ca 100644 (file)
@@ -22,6 +22,8 @@
 #define MCFINTC_IMRL        0x0c        /* Interrupt mask 1-31 */
 #define MCFINTC_INTFRCH     0x10        /* Interrupt force 32-63 */
 #define MCFINTC_INTFRCL     0x14        /* Interrupt force 1-31 */
+#define MCFINTC_SIMR        0x1c        /* Set interrupt mask 0-63 */
+#define MCFINTC_CIMR        0x1d        /* Clear interrupt mask 0-63 */
 #define MCFINTC_ICR0        0x40        /* Base ICR register */
 
 #define MCFINT_VECBASE      64
index 9e0c100447ca9ef46d6bf6c91b778b9b4b91c497..47f6af57e18e74d77d42d1fc38b5649ea44ca9f7 100644 (file)
@@ -29,6 +29,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
        set_irq_regs(oldregs);
 }
 
+#if !defined(CONFIG_M520x)
+
 static struct irq_chip m_irq_chip = {
        .name           = "M68K-INTC",
        .enable         = enable_vector,
@@ -50,6 +52,8 @@ void __init init_IRQ(void)
        }
 }
 
+#endif
+
 int show_interrupts(struct seq_file *p, void *v)
 {
        struct irqaction *ap;
index 2667323c7feee36f66cc43d769e83052b7731281..dd242db7daa15df9467af2fc8c94226d46f0adab 100644 (file)
@@ -17,7 +17,7 @@ asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 obj-$(CONFIG_COLDFIRE) += clk.o dma.o entry.o vectors.o
 obj-$(CONFIG_M5206)    += timers.o
 obj-$(CONFIG_M5206e)   += timers.o
-obj-$(CONFIG_M520x)    += pit.o
+obj-$(CONFIG_M520x)    += pit.o intc-simr.o
 obj-$(CONFIG_M523x)    += pit.o dma_timer.o
 obj-$(CONFIG_M5249)    += timers.o
 obj-$(CONFIG_M527x)    += pit.o
diff --git a/arch/m68knommu/platform/coldfire/intc-simr.c b/arch/m68knommu/platform/coldfire/intc-simr.c
new file mode 100644 (file)
index 0000000..3b614a3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * intc-simr.c
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ *
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+static void intc_irq_mask(unsigned int irq)
+{
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 63))
+               __raw_writeb(irq - MCFINT_VECBASE, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_SIMR);
+}
+
+static void intc_irq_unmask(unsigned int irq)
+{
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 63))
+               __raw_writeb(irq - MCFINT_VECBASE, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_CIMR);
+}
+
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 63))
+               __raw_writeb(5, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0 + irq - MCFINT_VECBASE);
+       return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+       .name           = "CF-INTC",
+       .mask           = intc_irq_mask,
+       .unmask         = intc_irq_unmask,
+       .set_type       = intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+       int irq;
+
+       init_vectors();
+
+       for (irq = 0; (irq < NR_IRQS); irq++) {
+               irq_desc[irq].status = IRQ_DISABLED;
+               irq_desc[irq].action = NULL;
+               irq_desc[irq].depth = 1;
+               irq_desc[irq].chip = &intc_irq_chip;
+               intc_irq_set_type(irq, 0);
+       }
+}
+