#include <linux/console.h>
#include <linux/pci.h>
#include <linux/of_platform.h>
+#include <linux/gfp.h>
#include <asm/prom.h>
#include <asm/system.h>
#include "pasemi.h"
-#if !defined(CONFIG_SMP)
-static void smp_send_stop(void) {}
-#endif
-
/* SDC reset register, must be pre-mapped at reset time */
static void __iomem *reset_reg;
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)
}
#ifdef CONFIG_SMP
-static DEFINE_SPINLOCK(timebase_lock);
+static arch_spinlock_t timebase_lock;
static unsigned long timebase;
static void __devinit pas_give_timebase(void)
{
- spin_lock(&timebase_lock);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ hard_irq_disable();
+ arch_spin_lock(&timebase_lock);
mtspr(SPRN_TBCTL, TBCTL_FREEZE);
isync();
timebase = get_tb();
- spin_unlock(&timebase_lock);
+ arch_spin_unlock(&timebase_lock);
while (timebase)
barrier();
mtspr(SPRN_TBCTL, TBCTL_RESTART);
+ local_irq_restore(flags);
}
static void __devinit pas_take_timebase(void)
while (!timebase)
smp_rmb();
- spin_lock(&timebase_lock);
+ arch_spin_lock(&timebase_lock);
set_tb(timebase >> 32, timebase & 0xffffffff);
timebase = 0;
- spin_unlock(&timebase_lock);
+ arch_spin_unlock(&timebase_lock);
}
struct smp_ops_t pas_smp_ops = {
struct pci_dev *dev;
int reg;
- if (!machine_is(pasemi))
- return -ENODEV;
-
/* Remap various SoC status registers for use by the MCE handler */
reg = 0;
return 0;
}
-device_initcall(pas_setup_mce_regs);
+machine_device_initcall(pasemi, pas_setup_mce_regs);
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;
openpic_addr = of_read_number(opprop, naddr);
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
+ mpic_flags = MPIC_PRIMARY | MPIC_LARGE_VECTORS | MPIC_NO_BIAS;
+
+ 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, " PAS-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);
+ irq_set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
+ mpic_unmask_irq(irq_get_irq_data(nmi_virq));
+ }
+
of_node_put(mpic_node);
of_node_put(root);
}
srr0 = regs->nip;
srr1 = regs->msr;
+
+ if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
+ printk(KERN_ERR "NMI delivered\n");
+ debugger(regs);
+ mpic_end_irq(irq_get_irq_data(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);
}
}
-
+out:
/* SRR1[62] is from MSR[62] if recoverable, so pass that back */
return !!(srr1 & 0x2);
}
/* We know electra_cf devices will always have of_node set, since
* electra_cf is an of_platform driver.
*/
- if (!parent->archdata.of_node)
+ if (!parent->of_node)
return 0;
- if (!of_device_is_compatible(parent->archdata.of_node, "electra-cf"))
+ if (!of_device_is_compatible(parent->of_node, "electra-cf"))
return 0;
/* We use the direct ops for localbus */
static int __init pasemi_publish_devices(void)
{
- if (!machine_is(pasemi))
- return 0;
-
pasemi_pcmcia_init();
/* Publish OF platform devices for SDC and other non-PCI devices */
return 0;
}
-device_initcall(pasemi_publish_devices);
+machine_device_initcall(pasemi, pasemi_publish_devices);
/*