summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dearman <chris@mips.com>2009-07-10 12:54:09 +0400
committerRalf Baechle <ralf@linux-mips.org>2009-11-02 14:00:06 +0300
commit7098f748283b4c056cca9c284c476b03f004ca12 (patch)
tree51d3f09abeabfe27dff3351a212b8c8a976ebba4
parent2ee0a42961c942c6a2fb70700ef4e25c0acf5fca (diff)
downloadlinux-7098f748283b4c056cca9c284c476b03f004ca12.tar.xz
MIPS: GIC: Random fixes and enhancements.
Signed-off-by: Chris Dearman <chris@mips.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/gcmpregs.h18
-rw-r--r--arch/mips/include/asm/gic.h188
-rw-r--r--arch/mips/kernel/irq-gic.c114
-rw-r--r--arch/mips/mti-malta/malta-int.c101
-rw-r--r--arch/mips/mti-malta/malta-pci.c14
5 files changed, 142 insertions, 293 deletions
diff --git a/arch/mips/include/asm/gcmpregs.h b/arch/mips/include/asm/gcmpregs.h
index 36fd969d64d6..c0cf76a2ca89 100644
--- a/arch/mips/include/asm/gcmpregs.h
+++ b/arch/mips/include/asm/gcmpregs.h
@@ -19,15 +19,20 @@
#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))
@@ -49,10 +54,10 @@
#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
@@ -115,5 +120,6 @@
#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 */
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index a8f57341f123..9b9436a4d816 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -12,7 +12,6 @@
#define _ASM_GICREGS_H
#undef GICISBYTELITTLEENDIAN
-#define GICISWORDLITTLEENDIAN
/* Constants */
#define GIC_POL_POS 1
@@ -20,11 +19,7 @@
#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))
@@ -70,13 +65,13 @@
#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
@@ -164,24 +159,31 @@
(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
@@ -219,161 +221,6 @@
#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,
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index d2072cd38592..b181f2f0ea8e 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -14,38 +14,23 @@
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);
}
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index e568d0da060e..377a925e8cc6 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -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)
diff --git a/arch/mips/mti-malta/malta-pci.c b/arch/mips/mti-malta/malta-pci.c
index efdb4f66ffcf..2fbfa1a8c3a9 100644
--- a/arch/mips/mti-malta/malta-pci.c
+++ b/arch/mips/mti-malta/malta-pci.c
@@ -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;