summaryrefslogtreecommitdiff
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c30
-rw-r--r--arch/powerpc/sysdev/mpic.c26
-rw-r--r--arch/powerpc/sysdev/mpic.h3
3 files changed, 50 insertions, 9 deletions
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index b5dfd4252110..eb271fded876 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -61,6 +61,7 @@ struct mce_regs {
static struct mce_regs mce_regs[MAX_MCE_REGS];
static int num_mce_regs;
+static int nmi_virq = NO_IRQ;
static void pas_restart(char *cmd)
@@ -189,6 +190,8 @@ static __init void pas_init_IRQ(void)
unsigned long openpic_addr;
const unsigned int *opprop;
int naddr, opplen;
+ int mpic_flags;
+ const unsigned int *nmiprop;
struct mpic *mpic;
mpic_node = NULL;
@@ -221,13 +224,26 @@ static __init void pas_init_IRQ(void)
openpic_addr = of_read_number(opprop, naddr);
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
+ mpic_flags = MPIC_PRIMARY | MPIC_LARGE_VECTORS;
+
+ nmiprop = of_get_property(mpic_node, "nmi-source", NULL);
+ if (nmiprop)
+ mpic_flags |= MPIC_ENABLE_MCK;
+
mpic = mpic_alloc(mpic_node, openpic_addr,
- MPIC_PRIMARY|MPIC_LARGE_VECTORS,
- 0, 0, "PASEMI-OPIC");
+ mpic_flags, 0, 0, "PASEMI-OPIC");
BUG_ON(!mpic);
mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
mpic_init(mpic);
+ /* The NMI/MCK source needs to be prio 15 */
+ if (nmiprop) {
+ nmi_virq = irq_create_mapping(NULL, *nmiprop);
+ mpic_irq_set_priority(nmi_virq, 15);
+ set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
+ mpic_unmask_irq(nmi_virq);
+ }
+
of_node_put(mpic_node);
of_node_put(root);
}
@@ -247,6 +263,14 @@ static int pas_machine_check_handler(struct pt_regs *regs)
srr0 = regs->nip;
srr1 = regs->msr;
+
+ if (mpic_get_mcirq() == nmi_virq) {
+ printk(KERN_ERR "NMI delivered\n");
+ debugger(regs);
+ mpic_end_irq(nmi_virq);
+ goto out;
+ }
+
dsisr = mfspr(SPRN_DSISR);
printk(KERN_ERR "Machine Check on CPU %d\n", cpu);
printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1);
@@ -310,7 +334,7 @@ static int pas_machine_check_handler(struct pt_regs *regs)
}
}
-
+out:
/* SRR1[62] is from MSR[62] if recoverable, so pass that back */
return !!(srr1 & 0x2);
}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index f74fe26b787e..5a9d8c141e60 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -83,6 +83,7 @@ static u32 mpic_infos[][MPIC_IDX_END] = {
MPIC_CPU_WHOAMI,
MPIC_CPU_INTACK,
MPIC_CPU_EOI,
+ MPIC_CPU_MCACK,
MPIC_IRQ_BASE,
MPIC_IRQ_STRIDE,
@@ -121,6 +122,7 @@ static u32 mpic_infos[][MPIC_IDX_END] = {
TSI108_CPU_WHOAMI,
TSI108_CPU_INTACK,
TSI108_CPU_EOI,
+ TSI108_CPU_MCACK,
TSI108_IRQ_BASE,
TSI108_IRQ_STRIDE,
@@ -1126,6 +1128,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mb();
}
+ if (flags & MPIC_ENABLE_MCK)
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+ | MPIC_GREG_GCONF_MCK);
+
/* Read feature register, calculate num CPUs and, for non-ISU
* MPICs, num sources as well. On ISU MPICs, sources are counted
* as ISUs are added
@@ -1438,13 +1445,13 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
}
-unsigned int mpic_get_one_irq(struct mpic *mpic)
+static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg)
{
u32 src;
- src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK);
+ src = mpic_cpu_read(reg) & MPIC_INFO(VECPRI_VECTOR_MASK);
#ifdef DEBUG_LOW
- DBG("%s: get_one_irq(): %d\n", mpic->name, src);
+ DBG("%s: get_one_irq(reg 0x%x): %d\n", mpic->name, reg, src);
#endif
if (unlikely(src == mpic->spurious_vec)) {
if (mpic->flags & MPIC_SPV_EOI)
@@ -1462,6 +1469,11 @@ unsigned int mpic_get_one_irq(struct mpic *mpic)
return irq_linear_revmap(mpic->irqhost, src);
}
+unsigned int mpic_get_one_irq(struct mpic *mpic)
+{
+ return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_INTACK));
+}
+
unsigned int mpic_get_irq(void)
{
struct mpic *mpic = mpic_primary;
@@ -1471,6 +1483,14 @@ unsigned int mpic_get_irq(void)
return mpic_get_one_irq(mpic);
}
+unsigned int mpic_get_mcirq(void)
+{
+ struct mpic *mpic = mpic_primary;
+
+ BUG_ON(mpic == NULL);
+
+ return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_MCACK));
+}
#ifdef CONFIG_SMP
void mpic_request_ipis(void)
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 4783c6e9f30d..fbf8a266941c 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -38,9 +38,6 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
extern void mpic_set_vector(unsigned int virq, unsigned int vector);
-extern void mpic_end_irq(unsigned int irq);
-extern void mpic_mask_irq(unsigned int irq);
-extern void mpic_unmask_irq(unsigned int irq);
extern void mpic_set_affinity(unsigned int irq, cpumask_t cpumask);
#endif /* _POWERPC_SYSDEV_MPIC_H */