MIPS: Make GIC code platform independent.
authorSteven J. Hill <sjhill@mips.com>
Fri, 31 Aug 2012 21:05:37 +0000 (16:05 -0500)
committerSteven J. Hill <sjhill@mips.com>
Thu, 13 Sep 2012 20:43:47 +0000 (15:43 -0500)
The GIC interrupt code is used by multiple platforms and the
current code was half Malta dependent code. These changes
abstract away the platform specific differences.

Signed-off-by: Steven J. Hill <sjhill@mips.com>
arch/mips/include/asm/gic.h
arch/mips/include/asm/mips-boards/maltaint.h
arch/mips/kernel/irq-gic.c
arch/mips/mti-malta/malta-int.c

index 991b659e254803937cc99c9854d2c24f1153b0d3..77207fa459a52ceb9c3032636bc4a4c500ea7897 100644 (file)
@@ -341,15 +341,44 @@ struct gic_shared_intr_map {
        unsigned int local_intr_mask;
 };
 
+/* GIC nomenclature for Core Interrupt Pins. */
+#define GIC_CPU_INT0           0 /* Core Interrupt 2 */
+#define GIC_CPU_INT1           1 /* .                */
+#define GIC_CPU_INT2           2 /* .                */
+#define GIC_CPU_INT3           3 /* .                */
+#define GIC_CPU_INT4           4 /* .                */
+#define GIC_CPU_INT5           5 /* Core Interrupt 5 */
+
+/* Local GIC interrupts. */
+#define GIC_INT_TMR            (GIC_CPU_INT5)
+#define GIC_INT_PERFCTR                (GIC_CPU_INT5)
+
+/* Add 2 to convert non-EIC hardware interrupt to EIC vector number. */
+#define GIC_CPU_TO_VEC_OFFSET  (2)
+
+/* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */
+#define GIC_PIN_TO_VEC_OFFSET  (1)
+
+extern unsigned long _gic_base;
+extern unsigned int gic_irq_base;
+extern unsigned int gic_irq_flags[];
+extern struct gic_shared_intr_map gic_shared_intr_map[];
+
 extern void gic_init(unsigned long gic_base_addr,
        unsigned long gic_addrspace_size, struct gic_intr_map *intrmap,
        unsigned int intrmap_size, unsigned int irqbase);
 
+extern void gic_clocksource_init(unsigned int);
 extern unsigned int gic_get_int(void);
 extern void gic_send_ipi(unsigned int intr);
 extern unsigned int plat_ipi_call_int_xlate(unsigned int);
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
+extern void gic_enable_interrupt(int irq_vec);
+extern void gic_disable_interrupt(int irq_vec);
+extern void gic_irq_ack(struct irq_data *d);
+extern void gic_finish_irq(struct irq_data *d);
+extern void gic_platform_init(int irqs, struct irq_chip *irq_controller);
 
 #endif /* _ASM_GICREGS_H */
index 5447d9fc421941da85a2b0ce6bed2b865a4a8282..6692448157539ee17182ada478beb65320c69f9e 100644 (file)
@@ -1,31 +1,16 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- * Defines for the Malta interrupt controller.
+ * 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) 2000,2012 MIPS Technologies, Inc.  All rights reserved.
+ *      Carsten Langgaard <carstenl@mips.com>
+ *      Steven J. Hill <sjhill@mips.com>
  */
 #ifndef _MIPS_MALTAINT_H
 #define _MIPS_MALTAINT_H
 
-#include <irq.h>
+#define MIPS_GIC_IRQ_BASE      (MIPS_CPU_IRQ_BASE + 8)
 
 /*
  * Interrupts 0..15 are used for Malta ISA compatible interrupts
 #define MSC01E_INT_PERFCTR     10
 #define MSC01E_INT_CPUCTR      11
 
-/* GIC's Nomenclature for Core Interrupt Pins on the Malta */
-#define GIC_CPU_INT0           0 /* Core Interrupt 2   */
-#define GIC_CPU_INT1           1 /* .                  */
-#define GIC_CPU_INT2           2 /* .                  */
-#define GIC_CPU_INT3           3 /* .                  */
-#define GIC_CPU_INT4           4 /* .                  */
-#define GIC_CPU_INT5           5 /* Core Interrupt 5   */
-
-/* MALTA GIC local interrupts */
-#define GIC_INT_TMR             (GIC_CPU_INT5)
-#define GIC_INT_PERFCTR         (GIC_CPU_INT5)
-
-/* GIC constants */
-/* Add 2 to convert non-eic hw int # to eic vector # */
-#define GIC_CPU_TO_VEC_OFFSET   (2)
-/* If we map an intr to pin X, GIC will actually generate vector X+1 */
-#define GIC_PIN_TO_VEC_OFFSET   (1)
-
-#define GIC_EXT_INTR(x)                x
-
 /* External Interrupts used for IPI */
 #define GIC_IPI_EXT_INTR_RESCHED_VPE0  16
 #define GIC_IPI_EXT_INTR_CALLFNC_VPE0  17
 #define GIC_IPI_EXT_INTR_RESCHED_VPE3  22
 #define GIC_IPI_EXT_INTR_CALLFNC_VPE3  23
 
-#define MIPS_GIC_IRQ_BASE      (MIPS_CPU_IRQ_BASE + 8)
-
-#ifndef __ASSEMBLY__
-extern void maltaint_init(void);
-#endif
-
 #endif /* !(_MIPS_MALTAINT_H) */
index 0c527f652196f4be60aad9515e731c703620df49..18124c3bda2fe2b0bb08351ad75371a56b80368e 100644 (file)
 #include <asm-generic/bitops/find.h>
 
 
-static unsigned long _gic_base;
-static unsigned int _irqbase;
-static unsigned int gic_irq_flags[GIC_NUM_INTRS];
-#define GIC_IRQ_FLAG_EDGE      0x0001
+unsigned long _gic_base;
+unsigned int gic_irq_base;
+unsigned int gic_irq_flags[GIC_NUM_INTRS];
 
-struct gic_pcpu_mask pcpu_masks[NR_CPUS];
+static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
 
@@ -87,27 +86,16 @@ unsigned int gic_get_int(void)
        return i;
 }
 
-static void gic_irq_ack(struct irq_data *d)
-{
-       unsigned int irq = d->irq - _irqbase;
-
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
-       GIC_CLR_INTR_MASK(irq);
-
-       if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE)
-               GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
-}
-
 static void gic_mask_irq(struct irq_data *d)
 {
-       unsigned int irq = d->irq - _irqbase;
+       unsigned int irq = d->irq - gic_irq_base;
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        GIC_CLR_INTR_MASK(irq);
 }
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-       unsigned int irq = d->irq - _irqbase;
+       unsigned int irq = d->irq - gic_irq_base;
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        GIC_SET_INTR_MASK(irq);
 }
@@ -119,7 +107,7 @@ static DEFINE_SPINLOCK(gic_lock);
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
                            bool force)
 {
-       unsigned int irq = d->irq - _irqbase;
+       unsigned int irq = d->irq - gic_irq_base;
        cpumask_t       tmp = CPU_MASK_NONE;
        unsigned long   flags;
        int             i;
@@ -194,7 +182,7 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
        if (flags & GIC_FLAG_TRANSPARENT)
                GIC_SET_INTR_MASK(intr);
        if (trigtype == GIC_TRIG_EDGE)
-               gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE;
+               gic_irq_flags[intr] |= GIC_TRIG_EDGE;
 }
 
 static void __init gic_basic_init(int numintrs, int numvpes,
@@ -227,9 +215,6 @@ static void __init gic_basic_init(int numintrs, int numvpes,
        }
 
        vpe_local_setup(numvpes);
-
-       for (i = _irqbase; i < (_irqbase + numintrs); i++)
-               irq_set_chip(i, &gic_irq_controller);
 }
 
 void __init gic_init(unsigned long gic_base_addr,
@@ -242,7 +227,7 @@ void __init gic_init(unsigned long gic_base_addr,
 
        _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
                                                    gic_addrspace_size);
-       _irqbase = irqbase;
+       gic_irq_base = irqbase;
 
        GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
        numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
@@ -255,4 +240,6 @@ void __init gic_init(unsigned long gic_base_addr,
        pr_debug("%s called\n", __func__);
 
        gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
+
+       gic_platform_init(numintrs, &gic_irq_controller);
 }
index 7b13a4caeea41b6377fb9410fe1397f2dce6aef2..5222a7cc41e46c3fc52412df88335a4b97c6dbfa 100644 (file)
@@ -747,3 +747,37 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
 
        return retval;
 }
+
+void gic_enable_interrupt(int irq_vec)
+{
+       GIC_SET_INTR_MASK(irq_vec);
+}
+
+void gic_disable_interrupt(int irq_vec)
+{
+       GIC_CLR_INTR_MASK(irq_vec);
+}
+
+void gic_irq_ack(struct irq_data *d)
+{
+       int irq = (d->irq - gic_irq_base);
+
+       GIC_CLR_INTR_MASK(irq);
+
+       if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
+               GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
+}
+
+void gic_finish_irq(struct irq_data *d)
+{
+       /* Enable interrupts. */
+       GIC_SET_INTR_MASK(d->irq - gic_irq_base);
+}
+
+void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
+{
+       int i;
+
+       for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
+               irq_set_chip(i, irq_controller);
+}