MIPS: GIC: Random fixes and enhancements.
authorChris Dearman <chris@mips.com>
Fri, 10 Jul 2009 08:54:09 +0000 (01:54 -0700)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 2 Nov 2009 11:00:06 +0000 (12:00 +0100)
Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/gcmpregs.h
arch/mips/include/asm/gic.h
arch/mips/kernel/irq-gic.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-pci.c

index 36fd969d64d6fc83a1b37daf5a22fe3b46c504b1..c0cf76a2ca890a8ace9f0e4caec0377eef7bd8d7 100644 (file)
 #define GCMP_GDB_OFS           0x8000 /* Global Debug Block */
 
 /* Offsets to individual GCMP registers from GCMP base */
-#define GCMPOFS(block, tag, reg)       (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
+#define GCMPOFS(block, tag, reg)       \
+       (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS)
+#define GCMPOFSn(block, tag, reg, n) \
+       (GCMP_##block##_OFS + GCMP_##tag##_##reg##_OFS(n))
 
 #define GCMPGCBOFS(reg)                GCMPOFS(GCB, GCB, reg)
+#define GCMPGCBOFSn(reg, n)    GCMPOFSn(GCB, GCB, reg, n)
 #define GCMPCLCBOFS(reg)       GCMPOFS(CLCB, CCB, reg)
 #define GCMPCOCBOFS(reg)       GCMPOFS(COCB, CCB, reg)
 #define GCMPGDBOFS(reg)                GCMPOFS(GDB, GDB, reg)
 
 /* GCMP register access */
 #define GCMPGCB(reg)                   REGP(_gcmp_base, GCMPGCBOFS(reg))
+#define GCMPGCBn(reg, n)               REGP(_gcmp_base, GCMPGCBOFSn(reg, n))
 #define GCMPCLCB(reg)                  REGP(_gcmp_base, GCMPCLCBOFS(reg))
 #define GCMPCOCB(reg)                  REGP(_gcmp_base, GCMPCOCBOFS(reg))
 #define GCMPGDB(reg)                   REGP(_gcmp_base, GCMPGDBOFS(reg))
 #define  GCMP_GCB_GCMPB_GCMPBASE_MSK   GCMPGCBMSK(GCMPB_GCMPBASE, 17)
 #define  GCMP_GCB_GCMPB_CMDEFTGT_SHF   0
 #define  GCMP_GCB_GCMPB_CMDEFTGT_MSK   GCMPGCBMSK(GCMPB_CMDEFTGT, 2)
-#define  GCMP_GCB_GCMPB_CMDEFTGT_MEM   0
-#define  GCMP_GCB_GCMPB_CMDEFTGT_MEM1  1
-#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU1 2
-#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU2 3
+#define  GCMP_GCB_GCMPB_CMDEFTGT_DISABLED      0
+#define  GCMP_GCB_GCMPB_CMDEFTGT_MEM           1
+#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU1         2
+#define  GCMP_GCB_GCMPB_CMDEFTGT_IOCU2         3
 #define GCMP_GCB_CCMC_OFS              0x0010  /* Global CM Control */
 #define GCMP_GCB_GCSRAP_OFS            0x0020  /* Global CSR Access Privilege */
 #define  GCMP_GCB_GCSRAP_CMACCESS_SHF  0
 #define GCMP_CCB_DBGGROUP_OFS          0x0100          /* DebugBreak Group */
 
 extern int __init gcmp_probe(unsigned long, unsigned long);
-
+extern int __init gcmp_niocu(void);
+extern void __init gcmp_setregion(int, unsigned long, unsigned long, int);
 #endif /* _ASM_GCMPREGS_H */
index a8f57341f12364eca41411cf8041bbcbfa176bea..9b9436a4d816bfe7f26a1eb8a7e7cb677507c388 100644 (file)
@@ -12,7 +12,6 @@
 #define _ASM_GICREGS_H
 
 #undef GICISBYTELITTLEENDIAN
-#define GICISWORDLITTLEENDIAN
 
 /* Constants */
 #define GIC_POL_POS                    1
 #define GIC_TRIG_EDGE                  1
 #define GIC_TRIG_LEVEL                 0
 
-#ifdef CONFIG_SMP
 #define GIC_NUM_INTRS                  (24 + NR_CPUS * 2)
-#else
-#define GIC_NUM_INTRS                  32
-#endif
 
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)            (*(volatile unsigned int *) (addr))
 #define USM_VISIBLE_SECTION_SIZE       0x10000
 
 /* Register Map for Shared Section */
-#if defined(CONFIG_CPU_LITTLE_ENDIAN) || defined(GICISWORDLITTLEENDIAN)
 
 #define        GIC_SH_CONFIG_OFS               0x0000
 
 /* Shared Global Counter */
 #define GIC_SH_COUNTER_31_00_OFS       0x0010
 #define GIC_SH_COUNTER_63_32_OFS       0x0014
+#define GIC_SH_REVISIONID_OFS          0x0020
 
 /* Interrupt Polarity */
 #define GIC_SH_POL_31_0_OFS            0x0100
        (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + (((vpe) / 32) * 4))
 #define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
 
+/* Convert an interrupt number to a byte offset/bit for multi-word registers */
+#define GIC_INTR_OFS(intr) (((intr) / 32)*4)
+#define GIC_INTR_BIT(intr) ((intr) % 32)
+
 /* Polarity : Reset Value is always 0 */
 #define GIC_SH_SET_POLARITY_OFS                0x0100
 #define GIC_SET_POLARITY(intr, pol) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + (((intr) / 32) * 4)), (pol) << ((intr) % 32))
+       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
+               GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr))
 
 /* Triggering : Reset Value is always 0 */
 #define GIC_SH_SET_TRIGGER_OFS         0x0180
 #define GIC_SET_TRIGGER(intr, trig) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + (((intr) / 32) * 4)), (trig) << ((intr) % 32))
+       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
+               GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr))
 
 /* Mask manipulation */
 #define GIC_SH_SMASK_OFS               0x0380
-#define GIC_SET_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
-
+#define GIC_SET_INTR_MASK(intr) \
+       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + \
+               GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
 #define GIC_SH_RMASK_OFS               0x0300
-#define GIC_CLR_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + (((intr) / 32) * 4)), ((val) << ((intr) % 32)))
+#define GIC_CLR_INTR_MASK(intr) \
+       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + \
+               GIC_INTR_OFS(intr)), 1 << GIC_INTR_BIT(intr))
 
 /* Register Map for Local Section */
 #define GIC_VPE_CTL_OFS                        0x0000
 #define GIC_UMV_SH_COUNTER_31_00_OFS   0x0000
 #define GIC_UMV_SH_COUNTER_63_32_OFS   0x0004
 
-#else /* CONFIG_CPU_BIG_ENDIAN */
-
-#define        GIC_SH_CONFIG_OFS               0x0000
-
-/* Shared Global Counter */
-#define GIC_SH_COUNTER_31_00_OFS       0x0014
-#define GIC_SH_COUNTER_63_32_OFS       0x0010
-
-/* Interrupt Polarity */
-#define GIC_SH_POL_31_0_OFS            0x0104
-#define GIC_SH_POL_63_32_OFS           0x0100
-#define GIC_SH_POL_95_64_OFS           0x010c
-#define GIC_SH_POL_127_96_OFS          0x0108
-#define GIC_SH_POL_159_128_OFS         0x0114
-#define GIC_SH_POL_191_160_OFS         0x0110
-#define GIC_SH_POL_223_192_OFS         0x011c
-#define GIC_SH_POL_255_224_OFS         0x0118
-
-/* Edge/Level Triggering */
-#define GIC_SH_TRIG_31_0_OFS           0x0184
-#define GIC_SH_TRIG_63_32_OFS          0x0180
-#define GIC_SH_TRIG_95_64_OFS          0x018c
-#define GIC_SH_TRIG_127_96_OFS         0x0188
-#define GIC_SH_TRIG_159_128_OFS                0x0194
-#define GIC_SH_TRIG_191_160_OFS                0x0190
-#define GIC_SH_TRIG_223_192_OFS                0x019c
-#define GIC_SH_TRIG_255_224_OFS                0x0198
-
-/* Dual Edge Triggering */
-#define GIC_SH_DUAL_31_0_OFS           0x0204
-#define GIC_SH_DUAL_63_32_OFS          0x0200
-#define GIC_SH_DUAL_95_64_OFS          0x020c
-#define GIC_SH_DUAL_127_96_OFS         0x0208
-#define GIC_SH_DUAL_159_128_OFS                0x0214
-#define GIC_SH_DUAL_191_160_OFS                0x0210
-#define GIC_SH_DUAL_223_192_OFS                0x021c
-#define GIC_SH_DUAL_255_224_OFS                0x0218
-
-/* Set/Clear corresponding bit in Edge Detect Register */
-#define GIC_SH_WEDGE_OFS               0x0280
-
-/* Reset Mask - Disables Interrupt */
-#define GIC_SH_RMASK_31_0_OFS          0x0304
-#define GIC_SH_RMASK_63_32_OFS         0x0300
-#define GIC_SH_RMASK_95_64_OFS         0x030c
-#define GIC_SH_RMASK_127_96_OFS                0x0308
-#define GIC_SH_RMASK_159_128_OFS       0x0314
-#define GIC_SH_RMASK_191_160_OFS       0x0310
-#define GIC_SH_RMASK_223_192_OFS       0x031c
-#define GIC_SH_RMASK_255_224_OFS       0x0318
-
-/* Set Mask (WO) - Enables Interrupt */
-#define GIC_SH_SMASK_31_0_OFS          0x0384
-#define GIC_SH_SMASK_63_32_OFS         0x0380
-#define GIC_SH_SMASK_95_64_OFS         0x038c
-#define GIC_SH_SMASK_127_96_OFS                0x0388
-#define GIC_SH_SMASK_159_128_OFS       0x0394
-#define GIC_SH_SMASK_191_160_OFS       0x0390
-#define GIC_SH_SMASK_223_192_OFS       0x039c
-#define GIC_SH_SMASK_255_224_OFS       0x0398
-
-/* Global Interrupt Mask Register (RO) - Bit Set == Interrupt enabled */
-#define GIC_SH_MASK_31_0_OFS           0x0404
-#define GIC_SH_MASK_63_32_OFS          0x0400
-#define GIC_SH_MASK_95_64_OFS          0x040c
-#define GIC_SH_MASK_127_96_OFS         0x0408
-#define GIC_SH_MASK_159_128_OFS                0x0414
-#define GIC_SH_MASK_191_160_OFS                0x0410
-#define GIC_SH_MASK_223_192_OFS                0x041c
-#define GIC_SH_MASK_255_224_OFS                0x0418
-
-/* Pending Global Interrupts (RO) */
-#define GIC_SH_PEND_31_0_OFS           0x0484
-#define GIC_SH_PEND_63_32_OFS          0x0480
-#define GIC_SH_PEND_95_64_OFS          0x048c
-#define GIC_SH_PEND_127_96_OFS         0x0488
-#define GIC_SH_PEND_159_128_OFS                0x0494
-#define GIC_SH_PEND_191_160_OFS                0x0490
-#define GIC_SH_PEND_223_192_OFS                0x049c
-#define GIC_SH_PEND_255_224_OFS                0x0498
-
-#define GIC_SH_INTR_MAP_TO_PIN_BASE_OFS        0x0500
-
-/* Maps Interrupt X to a Pin */
-#define GIC_SH_MAP_TO_PIN(intr) \
-       (GIC_SH_INTR_MAP_TO_PIN_BASE_OFS + (4 * intr))
-
-#define GIC_SH_INTR_MAP_TO_VPE_BASE_OFS        0x2004
-
-/*
- * Maps Interrupt X to a VPE.  This is more complex than the LE case, as
- * odd and even registers need to be transposed.  It does work - trust me!
- */
-#define GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe) \
-       (GIC_SH_INTR_MAP_TO_VPE_BASE_OFS + (32 * (intr)) + \
-       (((((vpe) / 32) ^ 1) - 1) * 4))
-#define GIC_SH_MAP_TO_VPE_REG_BIT(vpe) (1 << ((vpe) % 32))
-
-/* Polarity */
-#define GIC_SH_SET_POLARITY_OFS                0x0100
-#define GIC_SET_POLARITY(intr, pol) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (pol) << ((intr) % 32))
-
-/* Triggering */
-#define GIC_SH_SET_TRIGGER_OFS         0x0180
-#define GIC_SET_TRIGGER(intr, trig) \
-       GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), (trig) << ((intr) % 32))
-
-/* Mask manipulation */
-#define GIC_SH_SMASK_OFS               0x0380
-#define GIC_SET_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_SMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)))
-
-#define GIC_SH_RMASK_OFS               0x0300
-#define GIC_CLR_INTR_MASK(intr, val) \
-       GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)))
-
-/* Register Map for Local Section */
-#define GIC_VPE_CTL_OFS                        0x0000
-#define GIC_VPE_PEND_OFS               0x0004
-#define GIC_VPE_MASK_OFS               0x0008
-#define GIC_VPE_RMASK_OFS              0x000c
-#define GIC_VPE_SMASK_OFS              0x0010
-#define GIC_VPE_WD_MAP_OFS             0x0040
-#define GIC_VPE_COMPARE_MAP_OFS                0x0044
-#define GIC_VPE_TIMER_MAP_OFS          0x0048
-#define GIC_VPE_PERFCTR_MAP_OFS                0x0050
-#define GIC_VPE_SWINT0_MAP_OFS         0x0054
-#define GIC_VPE_SWINT1_MAP_OFS         0x0058
-#define GIC_VPE_OTHER_ADDR_OFS         0x0080
-#define GIC_VPE_WD_CONFIG0_OFS         0x0090
-#define GIC_VPE_WD_COUNT0_OFS          0x0094
-#define GIC_VPE_WD_INITIAL0_OFS                0x0098
-#define GIC_VPE_COMPARE_LO_OFS         0x00a4
-#define GIC_VPE_COMPARE_HI_OFS         0x00a0
-
-#define GIC_VPE_EIC_SHADOW_SET_BASE    0x0100
-#define GIC_VPE_EIC_SS(intr) \
-       (GIC_EIC_SHADOW_SET_BASE + (4 * intr))
-
-#define GIC_VPE_EIC_VEC_BASE           0x0800
-#define GIC_VPE_EIC_VEC(intr) \
-       (GIC_VPE_EIC_VEC_BASE + (4 * intr))
-
-#define GIC_VPE_TENABLE_NMI_OFS                0x1000
-#define GIC_VPE_TENABLE_YQ_OFS         0x1004
-#define GIC_VPE_TENABLE_INT_31_0_OFS   0x1080
-#define GIC_VPE_TENABLE_INT_63_32_OFS  0x1084
-
-/* User Mode Visible Section Register Map */
-#define GIC_UMV_SH_COUNTER_31_00_OFS   0x0004
-#define GIC_UMV_SH_COUNTER_63_32_OFS   0x0000
-
-#endif /* !LE */
-
 /* Masks */
 #define GIC_SH_CONFIG_COUNTSTOP_SHF    28
 #define GIC_SH_CONFIG_COUNTSTOP_MSK    (MSK(1) << GIC_SH_CONFIG_COUNTSTOP_SHF)
@@ -473,12 +320,13 @@ struct gic_intrmask_regs {
  * in building ipi_map.
  */
 struct gic_intr_map {
-       unsigned int intrnum;   /* Ext Intr Num         */
        unsigned int cpunum;    /* Directed to this CPU */
        unsigned int pin;       /* Directed to this Pin */
        unsigned int polarity;  /* Polarity : +/-       */
        unsigned int trigtype;  /* Trigger  : Edge/Levl */
-       unsigned int ipiflag;   /* Is used for IPI ?    */
+       unsigned int flags;     /* Misc flags   */
+#define GIC_FLAG_IPI           0x01
+#define GIC_FLAG_TRANSPARENT   0x02
 };
 
 extern void gic_init(unsigned long gic_base_addr,
index d2072cd385922db78c5b1278622ad4d4243a4949..b181f2f0ea8e71709f331c8ee32a7f6792999106 100644 (file)
 
 
 static unsigned long _gic_base;
-static unsigned int _irqbase, _mapsize, numvpes, numintrs;
-static struct gic_intr_map *_intrmap;
+static unsigned int _irqbase;
+static unsigned int gic_irq_flags[GIC_NUM_INTRS];
+#define GIC_IRQ_FLAG_EDGE      0x0001
 
-static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
+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];
 
-#define gic_wedgeb2bok 0       /*
-                                * Can GIC handle b2b writes to wedge register?
-                                */
-#if gic_wedgeb2bok == 0
-static DEFINE_SPINLOCK(gic_wedgeb2b_lock);
-#endif
-
 void gic_send_ipi(unsigned int intr)
 {
-#if gic_wedgeb2bok == 0
-       unsigned long flags;
-#endif
        pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
                 read_c0_status());
-       if (!gic_wedgeb2bok)
-               spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
        GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
-       if (!gic_wedgeb2bok) {
-               (void) GIC_REG(SHARED, GIC_SH_CONFIG);
-               spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
-       }
 }
 
 /* This is Malta specific and needs to be exported */
-static void vpe_local_setup(unsigned int numvpes)
+static void __init vpe_local_setup(unsigned int numvpes)
 {
        int i;
        unsigned long timer_interrupt = 5, perf_interrupt = 5;
@@ -105,44 +90,34 @@ unsigned int gic_get_int(void)
 
 static unsigned int gic_irq_startup(unsigned int irq)
 {
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_SET_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_SET_INTR_MASK(irq);
        return 0;
 }
 
 static void gic_irq_ack(unsigned int irq)
 {
-#if gic_wedgeb2bok == 0
-       unsigned long flags;
-#endif
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_CLR_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_CLR_INTR_MASK(irq);
 
-       if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
-               if (!gic_wedgeb2bok)
-                       spin_lock_irqsave(&gic_wedgeb2b_lock, flags);
+       if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE)
                GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
-               if (!gic_wedgeb2bok) {
-                       (void) GIC_REG(SHARED, GIC_SH_CONFIG);
-                       spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags);
-               }
-       }
 }
 
 static void gic_mask_irq(unsigned int irq)
 {
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_CLR_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_CLR_INTR_MASK(irq);
 }
 
 static void gic_unmask_irq(unsigned int irq)
 {
-       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GIC_SET_INTR_MASK(irq, 1);
+       pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
+       GIC_SET_INTR_MASK(irq);
 }
 
 #ifdef CONFIG_SMP
@@ -155,9 +130,8 @@ static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
        unsigned long   flags;
        int             i;
 
-       pr_debug(KERN_DEBUG "%s called\n", __func__);
        irq -= _irqbase;
-
+       pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq);
        cpumask_and(&tmp, cpumask, cpu_online_mask);
        if (cpus_empty(tmp))
                return -1;
@@ -168,13 +142,6 @@ static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
                /* Re-route this IRQ */
                GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));
 
-               /*
-                * FIXME: assumption that _intrmap is ordered and has no holes
-                */
-
-               /* Update the intr_map */
-               _intrmap[irq].cpunum = first_cpu(tmp);
-
                /* Update the pcpu_masks */
                for (i = 0; i < NR_CPUS; i++)
                        clear_bit(irq, pcpu_masks[i].pcpu_mask);
@@ -201,8 +168,9 @@ static struct irq_chip gic_irq_controller = {
 #endif
 };
 
-static void __init setup_intr(unsigned int intr, unsigned int cpu,
-       unsigned int pin, unsigned int polarity, unsigned int trigtype)
+static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
+       unsigned int pin, unsigned int polarity, unsigned int trigtype,
+       unsigned int flags)
 {
        /* Setup Intr to Pin mapping */
        if (pin & GIC_MAP_TO_NMI_MSK) {
@@ -227,38 +195,43 @@ static void __init setup_intr(unsigned int intr, unsigned int cpu,
        GIC_SET_TRIGGER(intr, trigtype);
 
        /* Init Intr Masks */
-       GIC_SET_INTR_MASK(intr, 0);
+       GIC_CLR_INTR_MASK(intr);
+       /* Initialise per-cpu Interrupt software masks */
+       if (flags & GIC_FLAG_IPI)
+               set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+       if (flags & GIC_FLAG_TRANSPARENT)
+               GIC_SET_INTR_MASK(intr);
+       if (trigtype == GIC_TRIG_EDGE)
+               gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE;
 }
 
-static void __init gic_basic_init(void)
+static void __init gic_basic_init(int numintrs, int numvpes,
+                       struct gic_intr_map *intrmap, int mapsize)
 {
        unsigned int i, cpu;
 
        /* Setup defaults */
-       for (i = 0; i < GIC_NUM_INTRS; i++) {
+       for (i = 0; i < numintrs; i++) {
                GIC_SET_POLARITY(i, GIC_POL_POS);
                GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
-               GIC_SET_INTR_MASK(i, 0);
+               GIC_CLR_INTR_MASK(i);
+               if (i < GIC_NUM_INTRS)
+                       gic_irq_flags[i] = 0;
        }
 
        /* Setup specifics */
-       for (i = 0; i < _mapsize; i++) {
-               cpu = _intrmap[i].cpunum;
+       for (i = 0; i < mapsize; i++) {
+               cpu = intrmap[i].cpunum;
                if (cpu == X)
                        continue;
-
-               if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 &&
-                                       _intrmap[i].ipiflag == 0)
+               if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
                        continue;
-
-               setup_intr(_intrmap[i].intrnum,
-                               _intrmap[i].cpunum,
-                               _intrmap[i].pin,
-                               _intrmap[i].polarity,
-                               _intrmap[i].trigtype);
-               /* Initialise per-cpu Interrupt software masks */
-               if (_intrmap[i].ipiflag)
-                       set_bit(_intrmap[i].intrnum, pcpu_masks[cpu].pcpu_mask);
+               gic_setup_intr(i,
+                       intrmap[i].cpunum,
+                       intrmap[i].pin,
+                       intrmap[i].polarity,
+                       intrmap[i].trigtype,
+                       intrmap[i].flags);
        }
 
        vpe_local_setup(numvpes);
@@ -273,12 +246,11 @@ void __init gic_init(unsigned long gic_base_addr,
                     unsigned int irqbase)
 {
        unsigned int gicconfig;
+       int numvpes, numintrs;
 
        _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
                                                    gic_addrspace_size);
        _irqbase = irqbase;
-       _intrmap = intr_map;
-       _mapsize = intr_map_size;
 
        GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
        numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
@@ -290,5 +262,5 @@ void __init gic_init(unsigned long gic_base_addr,
 
        pr_debug("%s called\n", __func__);
 
-       gic_basic_init();
+       gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
 }
index e568d0da060eb5e141321b645cd292ba2d458810..377a925e8cc62987754bec006f5f7a9ed0512f08 100644 (file)
@@ -379,32 +379,32 @@ static msc_irqmap_t __initdata msc_eicirqmap[] = {
 
 static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 
-#if defined(CONFIG_MIPS_MT_SMP)
 /*
  * This GIC specific tabular array defines the association between External
  * Interrupts and CPUs/Core Interrupts. The nature of the External
  * Interrupts is also defined here - polarity/trigger.
  */
+
+#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
 static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
-       { GIC_EXT_INTR(0),      X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(1),      X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(2),      X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(3),      0,      GIC_CPU_INT0,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(4),      0,      GIC_CPU_INT1,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(5),      0,      GIC_CPU_INT2,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(6),      0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(7),      0,      GIC_CPU_INT4,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(8),      0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(9),      0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(10),     X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(11),     X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(12),     0,      GIC_CPU_INT3,   GIC_POL_POS,    GIC_TRIG_LEVEL, 0 },
-       { GIC_EXT_INTR(13),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
-       { GIC_EXT_INTR(14),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
-       { GIC_EXT_INTR(15),     X,      X,              X,              X,              0 },
-/* This is the end of the general interrupts now we do IPI ones */
+       { X, X,            X,           X,              0 },
+       { X, X,            X,           X,              0 },
+       { X, X,            X,           X,              0 },
+       { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { X, X,            X,           X,              0 },
+       { X, X,            X,           X,              0 },
+       { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_NMI,  GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { 0, GIC_CPU_NMI,  GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
+       { X, X,            X,           X,              0 },
+       /* The remainder of this table is initialised by fill_ipi_map */
 };
-#endif
 
 /*
  * GCMP needs to be detected before any SMP initialisation
@@ -419,20 +419,35 @@ int __init gcmp_probe(unsigned long addr, unsigned long size)
        gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
 
        if (gcmp_present)
-               printk(KERN_DEBUG "GCMP present\n");
+               pr_debug("GCMP present\n");
        return gcmp_present;
 }
 
+/* Return the number of IOCU's present */
+int __init gcmp_niocu(void)
+{
+  return gcmp_present ?
+    (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF :
+    0;
+}
+
+/* Set GCMP region attributes */
+void __init gcmp_setregion(int region, unsigned long base,
+                          unsigned long mask, int type)
+{
+       GCMPGCBn(CMxBASE, region) = base;
+       GCMPGCBn(CMxMASK, region) = mask | type;
+}
+
 #if defined(CONFIG_MIPS_MT_SMP)
 static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
 {
        int intr = baseintr + cpu;
-       gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr);
        gic_intr_map[intr].cpunum = cpu;
        gic_intr_map[intr].pin = cpupin;
        gic_intr_map[intr].polarity = GIC_POL_POS;
        gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
-       gic_intr_map[intr].ipiflag = 1;
+       gic_intr_map[intr].flags = GIC_FLAG_IPI;
        ipi_map[cpu] |= (1 << (cpupin + 2));
 }
 
@@ -447,6 +462,12 @@ static void __init fill_ipi_map(void)
 }
 #endif
 
+void __init arch_init_ipiirq(int irq, struct irqaction *action)
+{
+       setup_irq(irq, action);
+       set_irq_handler(irq, handle_percpu_irq);
+}
+
 void __init arch_init_irq(void)
 {
        init_i8259_irqs();
@@ -463,7 +484,7 @@ void __init arch_init_irq(void)
                MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF;
        }
        if (gic_present)
-               printk(KERN_DEBUG "GIC present\n");
+               pr_debug("GIC present\n");
 
        switch (mips_revision_sconid) {
        case MIPS_REVISION_SCON_SOCIT:
@@ -526,16 +547,16 @@ void __init arch_init_irq(void)
                                                &corehi_irqaction);
        }
 
-#if defined(CONFIG_MIPS_MT_SMP)
        if (gic_present) {
                /* FIXME */
                int i;
-
+#if defined(CONFIG_MIPS_MT_SMP)
                gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
                gic_resched_int_base = gic_call_int_base - NR_CPUS;
-
                fill_ipi_map();
-               gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
+#endif
+               gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
+                               ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
                if (!gcmp_present) {
                        /* Enable the GIC */
                        i = REG(_msc01_biu_base, MSC01_SC_CFG);
@@ -543,7 +564,7 @@ void __init arch_init_irq(void)
                                (i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
                        pr_debug("GIC Enabled\n");
                }
-
+#if defined(CONFIG_MIPS_MT_SMP)
                /* set up ipi interrupts */
                if (cpu_has_vint) {
                        set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
@@ -556,16 +577,14 @@ void __init arch_init_irq(void)
                write_c0_status(0x1100dc00);
                printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
                for (i = 0; i < NR_CPUS; i++) {
-                       setup_irq(MIPS_GIC_IRQ_BASE +
-                                       GIC_RESCHED_INT(i), &irq_resched);
-                       setup_irq(MIPS_GIC_IRQ_BASE +
-                                       GIC_CALL_INT(i), &irq_call);
-                       set_irq_handler(MIPS_GIC_IRQ_BASE +
-                                       GIC_RESCHED_INT(i), handle_percpu_irq);
-                       set_irq_handler(MIPS_GIC_IRQ_BASE +
-                                       GIC_CALL_INT(i), handle_percpu_irq);
+                       arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
+                                        GIC_RESCHED_INT(i), &irq_resched);
+                       arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
+                                        GIC_CALL_INT(i), &irq_call);
                }
+#endif
        } else {
+#if defined(CONFIG_MIPS_MT_SMP)
                /* set up ipi interrupts */
                if (cpu_has_veic) {
                        set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
@@ -580,14 +599,10 @@ void __init arch_init_irq(void)
                        cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
                        cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
                }
-
-               setup_irq(cpu_ipi_resched_irq, &irq_resched);
-               setup_irq(cpu_ipi_call_irq, &irq_call);
-
-               set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
-               set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
-       }
+               arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
+               arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
 #endif
+       }
 }
 
 void malta_be_init(void)
index efdb4f66ffcf70050da25653f2c493894da977ce..2fbfa1a8c3a9a96a4a2bc159a9eb8c986bc4297e 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/init.h>
 
 #include <asm/gt64120.h>
-
+#include <asm/gcmpregs.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/bonito64.h>
 #include <asm/mips-boards/msc01_pci.h>
@@ -201,7 +201,11 @@ void __init mips_pcibios_init(void)
                msc_mem_resource.start = start & mask;
                msc_mem_resource.end = (start & mask) | ~mask;
                msc_controller.mem_offset = (start & mask) - (map & mask);
-
+#ifdef CONFIG_MIPS_CMP
+               if (gcmp_niocu())
+                       gcmp_setregion(0, start, mask,
+                               GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
+#endif
                MSC_READ(MSC01_PCI_SC2PIOBASL, start);
                MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
                MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
@@ -209,7 +213,11 @@ void __init mips_pcibios_init(void)
                msc_io_resource.end = (map & mask) | ~mask;
                msc_controller.io_offset = 0;
                ioport_resource.end = ~mask;
-
+#ifdef CONFIG_MIPS_CMP
+               if (gcmp_niocu())
+                       gcmp_setregion(1, start, mask,
+                               GCMP_GCB_GCMPB_CMDEFTGT_IOCU1);
+#endif
                /* If ranges overlap I/O takes precedence.  */
                start = start & mask;
                end = start | ~mask;