提交 7098f748 编写于 作者: C Chris Dearman 提交者: Ralf Baechle

MIPS: GIC: Random fixes and enhancements.

Signed-off-by: NChris Dearman <chris@mips.com>
Signed-off-by: NRalf Baechle <ralf@linux-mips.org>
上级 2ee0a429
......@@ -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 */
......@@ -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,
......
......@@ -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);
}
......@@ -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)
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册