aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pasemi
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2007-12-20 14:11:18 -0500
committerOlof Johansson <olof@lixom.net>2007-12-28 10:22:24 -0500
commitf365355e65ee619e3b7baeca69b46fd2c4a5ec68 (patch)
tree24133f987dc9ffe8f3a9b02355193e3d5113f8f2 /arch/powerpc/platforms/pasemi
parentc2a7dcad9f0d92d7a96e735abb8bec7b9c621536 (diff)
[POWERPC] pasemi: Implement NMI support
Some PWRficient-based boards have a NMI button that's wired up to a GPIO as interrupt source. By configuring the openpic accordingly, these get delivered as a machine check with high priority, instead of as an external interrupt. The device tree contains a property "nmi-source" in the openpic node for these systems, and it's the (hwirq) source for the input. Also, for these interrupts, the IACK is read from another register than the regular (MCACK instead), but they are EOI'd as usual. So implement said function for the mpic driver. Finally, move a couple of external function defines to include/ instead of local under sysdev. Being able to mask/unmask and eoi directly saves us from setting up a dummy irq handler that will never be called. Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/powerpc/platforms/pasemi')
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c30
1 files changed, 27 insertions, 3 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 {
61 61
62static struct mce_regs mce_regs[MAX_MCE_REGS]; 62static struct mce_regs mce_regs[MAX_MCE_REGS];
63static int num_mce_regs; 63static int num_mce_regs;
64static int nmi_virq = NO_IRQ;
64 65
65 66
66static void pas_restart(char *cmd) 67static void pas_restart(char *cmd)
@@ -189,6 +190,8 @@ static __init void pas_init_IRQ(void)
189 unsigned long openpic_addr; 190 unsigned long openpic_addr;
190 const unsigned int *opprop; 191 const unsigned int *opprop;
191 int naddr, opplen; 192 int naddr, opplen;
193 int mpic_flags;
194 const unsigned int *nmiprop;
192 struct mpic *mpic; 195 struct mpic *mpic;
193 196
194 mpic_node = NULL; 197 mpic_node = NULL;
@@ -221,13 +224,26 @@ static __init void pas_init_IRQ(void)
221 openpic_addr = of_read_number(opprop, naddr); 224 openpic_addr = of_read_number(opprop, naddr);
222 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); 225 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
223 226
227 mpic_flags = MPIC_PRIMARY | MPIC_LARGE_VECTORS;
228
229 nmiprop = of_get_property(mpic_node, "nmi-source", NULL);
230 if (nmiprop)
231 mpic_flags |= MPIC_ENABLE_MCK;
232
224 mpic = mpic_alloc(mpic_node, openpic_addr, 233 mpic = mpic_alloc(mpic_node, openpic_addr,
225 MPIC_PRIMARY|MPIC_LARGE_VECTORS, 234 mpic_flags, 0, 0, "PASEMI-OPIC");
226 0, 0, "PASEMI-OPIC");
227 BUG_ON(!mpic); 235 BUG_ON(!mpic);
228 236
229 mpic_assign_isu(mpic, 0, openpic_addr + 0x10000); 237 mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
230 mpic_init(mpic); 238 mpic_init(mpic);
239 /* The NMI/MCK source needs to be prio 15 */
240 if (nmiprop) {
241 nmi_virq = irq_create_mapping(NULL, *nmiprop);
242 mpic_irq_set_priority(nmi_virq, 15);
243 set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
244 mpic_unmask_irq(nmi_virq);
245 }
246
231 of_node_put(mpic_node); 247 of_node_put(mpic_node);
232 of_node_put(root); 248 of_node_put(root);
233} 249}
@@ -247,6 +263,14 @@ static int pas_machine_check_handler(struct pt_regs *regs)
247 263
248 srr0 = regs->nip; 264 srr0 = regs->nip;
249 srr1 = regs->msr; 265 srr1 = regs->msr;
266
267 if (mpic_get_mcirq() == nmi_virq) {
268 printk(KERN_ERR "NMI delivered\n");
269 debugger(regs);
270 mpic_end_irq(nmi_virq);
271 goto out;
272 }
273
250 dsisr = mfspr(SPRN_DSISR); 274 dsisr = mfspr(SPRN_DSISR);
251 printk(KERN_ERR "Machine Check on CPU %d\n", cpu); 275 printk(KERN_ERR "Machine Check on CPU %d\n", cpu);
252 printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); 276 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)
310 } 334 }
311 } 335 }
312 336
313 337out:
314 /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ 338 /* SRR1[62] is from MSR[62] if recoverable, so pass that back */
315 return !!(srr1 & 0x2); 339 return !!(srr1 & 0x2);
316} 340}