diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 020b64fac5fe289896b91a639317dae209b109f8..8ed92ae80b1e202f18d305fcdd9c92538fe3f330 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
 			     mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
 			     iSeries_iommu.o
 
-obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o open_pic.o i8259.o prom_init.o prom.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o
 
 obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
 			     eeh.o pSeries_nvram.o rtasd.o ras.o \
@@ -47,8 +47,8 @@ obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
 
 obj-$(CONFIG_PPC_PMAC)		+= pmac_setup.o pmac_feature.o pmac_pci.o \
-				   pmac_time.o pmac_nvram.o pmac_low_i2c.o \
-				   open_pic_u3.o
+				   pmac_time.o pmac_nvram.o pmac_low_i2c.o
+
 obj-$(CONFIG_U3_DART)		+= u3_iommu.o
 
 ifdef CONFIG_SMP
diff --git a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c
index 2f2b9bf8cf1cd4b4cbfc57cf0c9d858d55bea443..3458cf0c5a544aea026911e32c80908cbf9c2692 100644
--- a/arch/ppc64/kernel/i8259.c
+++ b/arch/ppc64/kernel/i8259.c
@@ -23,7 +23,8 @@ unsigned char cached_8259[2] = { 0xff, 0xff };
 
 static spinlock_t i8259_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
-int i8259_pic_irq_offset;
+static int i8259_pic_irq_offset;
+static int i8259_present;
 
 int i8259_irq(int cpu)
 {
@@ -140,11 +141,13 @@ struct hw_interrupt_type i8259_pic = {
         NULL
 };
 
-void __init i8259_init(void)
+void __init i8259_init(int offset)
 {
 	unsigned long flags;
 	
 	spin_lock_irqsave(&i8259_lock, flags);
+	i8259_pic_irq_offset = offset;
+	i8259_present = 1;
         /* init master interrupt controller */
         outb(0x11, 0x20); /* Start init sequence */
         outb(0x00, 0x21); /* Vector base */
@@ -160,7 +163,18 @@ void __init i8259_init(void)
         outb(cached_A1, 0xA1);
         outb(cached_21, 0x21);
 	spin_unlock_irqrestore(&i8259_lock, flags);
+        
+}
+
+static int i8259_request_cascade(void)
+{
+	if (!i8259_present)
+		return -ENODEV;
+
         request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
                      "82c59 secondary cascade", NULL );
-        
+
+	return 0;
 }
+
+arch_initcall(i8259_request_cascade);
diff --git a/arch/ppc64/kernel/i8259.h b/arch/ppc64/kernel/i8259.h
index 620a99997fb908285a6ac72f91b7794c008c8825..f74764ba0bfa4430aaf3d01effca02819e5c4b08 100644
--- a/arch/ppc64/kernel/i8259.h
+++ b/arch/ppc64/kernel/i8259.h
@@ -11,7 +11,7 @@
 
 extern struct hw_interrupt_type i8259_pic;
 
-void i8259_init(void);
-int i8259_irq(int);
+extern void i8259_init(int offset);
+extern int i8259_irq(int);
 
 #endif /* _PPC_KERNEL_i8259_H */
diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c
new file mode 100644
index 0000000000000000000000000000000000000000..991f4ea06ed8b7c079eb4c6829a46316c9136cd8
--- /dev/null
+++ b/arch/ppc64/kernel/mpic.c
@@ -0,0 +1,859 @@
+/*
+ *  arch/ppc64/kernel/mpic.c
+ *
+ *  Driver for interrupt controllers following the OpenPIC standard, the
+ *  common implementation beeing IBM's MPIC. This driver also can deal
+ *  with various broken implementations of this HW.
+ *
+ *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+
+#include "mpic.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static struct mpic *mpics;
+static struct mpic *mpic_primary;
+static spinlock_t mpic_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * Register accessor functions
+ */
+
+
+static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base,
+			    unsigned int reg)
+{
+	if (be)
+		return in_be32(base + (reg >> 2));
+	else
+		return in_le32(base + (reg >> 2));
+}
+
+static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
+			      unsigned int reg, u32 value)
+{
+	if (be)
+		out_be32(base + (reg >> 2), value);
+	else
+		out_le32(base + (reg >> 2), value);
+}
+
+static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
+{
+	unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
+	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+	if (mpic->flags & MPIC_BROKEN_IPI)
+		be = !be;
+	return _mpic_read(be, mpic->gregs, offset);
+}
+
+static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
+{
+	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
+}
+
+static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
+{
+	unsigned int cpu = 0;
+
+	if (mpic->flags & MPIC_PRIMARY)
+		cpu = hard_smp_processor_id();
+
+	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg);
+}
+
+static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
+{
+	unsigned int cpu = 0;
+
+	if (mpic->flags & MPIC_PRIMARY)
+		cpu = hard_smp_processor_id();
+
+	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value);
+}
+
+static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg)
+{
+	unsigned int	isu = src_no >> mpic->isu_shift;
+	unsigned int	idx = src_no & mpic->isu_mask;
+
+	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+			  reg + (idx * MPIC_IRQ_STRIDE));
+}
+
+static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
+				   unsigned int reg, u32 value)
+{
+	unsigned int	isu = src_no >> mpic->isu_shift;
+	unsigned int	idx = src_no & mpic->isu_mask;
+
+	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+		    reg + (idx * MPIC_IRQ_STRIDE), value);
+}
+
+#define mpic_read(b,r)		_mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
+#define mpic_write(b,r,v)	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v))
+#define mpic_ipi_read(i)	_mpic_ipi_read(mpic,(i))
+#define mpic_ipi_write(i,v)	_mpic_ipi_write(mpic,(i),(v))
+#define mpic_cpu_read(i)	_mpic_cpu_read(mpic,(i))
+#define mpic_cpu_write(i,v)	_mpic_cpu_write(mpic,(i),(v))
+#define mpic_irq_read(s,r)	_mpic_irq_read(mpic,(s),(r))
+#define mpic_irq_write(s,r,v)	_mpic_irq_write(mpic,(s),(r),(v))
+
+
+/*
+ * Low level utility functions
+ */
+
+
+
+/* Check if we have one of those nice broken MPICs with a flipped endian on
+ * reads from IPI registers
+ */
+static void __init mpic_test_broken_ipi(struct mpic *mpic)
+{
+	u32 r;
+
+	mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
+	r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+
+	if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
+		printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
+		mpic->flags |= MPIC_BROKEN_IPI;
+	}
+}
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+
+/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
+ * to force the edge setting on the MPIC and do the ack workaround.
+ */
+static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no)
+{
+	if (source_no >= 128 || !mpic->fixups)
+		return 0;
+	return mpic->fixups[source_no].base != NULL;
+}
+
+static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
+{
+	struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
+	u32 tmp;
+
+	spin_lock(&mpic->fixup_lock);
+	writeb(0x11 + 2 * fixup->irq, fixup->base);
+	tmp = readl(fixup->base + 2);
+	writel(tmp | 0x80000000ul, fixup->base + 2);
+	/* config writes shouldn't be posted but let's be safe ... */
+	(void)readl(fixup->base + 2);
+	spin_unlock(&mpic->fixup_lock);
+}
+
+
+static void __init mpic_amd8111_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+{
+	int i, irq;
+	u32 tmp;
+
+	printk(KERN_INFO "mpic:    - Workarounds on AMD 8111 @ %p\n", devbase);
+
+	for (i=0; i < 24; i++) {
+		writeb(0x10 + 2*i, devbase + 0xf2);
+		tmp = readl(devbase + 0xf4);
+		if ((tmp & 0x1) || !(tmp & 0x20))
+			continue;
+		irq = (tmp >> 16) & 0xff;
+		mpic->fixups[irq].irq = i;
+		mpic->fixups[irq].base = devbase + 0xf2;
+	}
+}
+ 
+static void __init mpic_amd8131_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+{
+	int i, irq;
+	u32 tmp;
+
+	printk(KERN_INFO "mpic:    - Workarounds on AMD 8131 @ %p\n", devbase);
+
+	for (i=0; i < 4; i++) {
+		writeb(0x10 + 2*i, devbase + 0xba);
+		tmp = readl(devbase + 0xbc);
+		if ((tmp & 0x1) || !(tmp & 0x20))
+			continue;
+		irq = (tmp >> 16) & 0xff;
+		mpic->fixups[irq].irq = i;
+		mpic->fixups[irq].base = devbase + 0xba;
+	}
+}
+ 
+static void __init mpic_scan_ioapics(struct mpic *mpic)
+{
+	unsigned int devfn;
+	u8 __iomem *cfgspace;
+
+	printk(KERN_INFO "mpic: Setting up IO-APICs workarounds for U3\n");
+
+	/* Allocate fixups array */
+	mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
+	BUG_ON(mpic->fixups == NULL);
+	memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
+
+	/* Init spinlock */
+	spin_lock_init(&mpic->fixup_lock);
+
+	/* Map u3 config space. We assume all IO-APICs are on the primary bus
+	 * and slot will never be above "0xf" so we only need to map 32k
+	 */
+	cfgspace = (unsigned char __iomem *)ioremap(0xf2000000, 0x8000);
+	BUG_ON(cfgspace == NULL);
+
+	/* Now we scan all slots. We do a very quick scan, we read the header type,
+	 * vendor ID and device ID only, that's plenty enough
+	 */
+	for (devfn = 0; devfn < PCI_DEVFN(0x10,0); devfn ++) {
+		u8 __iomem *devbase = cfgspace + (devfn << 8);
+		u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
+		u32 l = readl(devbase + PCI_VENDOR_ID);
+		u16 vendor_id, device_id;
+		int multifunc = 0;
+
+		DBG("devfn %x, l: %x\n", devfn, l);
+
+		/* If no device, skip */
+		if (l == 0xffffffff || l == 0x00000000 ||
+		    l == 0x0000ffff || l == 0xffff0000)
+			goto next;
+
+		/* Check if it's a multifunction device (only really used
+		 * to function 0 though
+		 */
+		multifunc = !!(hdr_type & 0x80);
+		vendor_id = l & 0xffff;
+		device_id = (l >> 16) & 0xffff;
+
+		/* If a known device, go to fixup setup code */
+		if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7460)
+			mpic_amd8111_read_irq(mpic, devbase);
+		if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7450)
+			mpic_amd8131_read_irq(mpic, devbase);
+	next:
+		/* next device, if function 0 */
+		if ((PCI_FUNC(devfn) == 0) && !multifunc)
+			devfn += 7;
+	}
+}
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+
+/* Find an mpic associated with a given linux interrupt */
+static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
+{
+	struct mpic *mpic = mpics;
+
+	while(mpic) {
+		/* search IPIs first since they may override the main interrupts */
+		if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) {
+			if (is_ipi)
+				*is_ipi = 1;
+			return mpic;
+		}
+		if (irq >= mpic->irq_offset &&
+		    irq < (mpic->irq_offset + mpic->irq_count)) {
+			if (is_ipi)
+				*is_ipi = 0;
+			return mpic;
+		}
+		mpic = mpic -> next;
+	}
+	return NULL;
+}
+
+/* Convert a cpu mask from logical to physical cpu numbers. */
+static inline u32 mpic_physmask(u32 cpumask)
+{
+	int i;
+	u32 mask = 0;
+
+	for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
+		mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
+	return mask;
+}
+
+#ifdef CONFIG_SMP
+/* Get the mpic structure from the IPI number */
+static inline struct mpic * mpic_from_ipi(unsigned int ipi)
+{
+	return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi);
+}
+#endif
+
+/* Get the mpic structure from the irq number */
+static inline struct mpic * mpic_from_irq(unsigned int irq)
+{
+	return container_of(irq_desc[irq].handler, struct mpic, hc_irq);
+}
+
+/* Send an EOI */
+static inline void mpic_eoi(struct mpic *mpic)
+{
+	mpic_cpu_write(MPIC_CPU_EOI, 0);
+	(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+}
+
+#ifdef CONFIG_SMP
+static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct mpic *mpic = dev_id;
+
+	smp_message_recv(irq - mpic->ipi_offset, regs);
+	return IRQ_HANDLED;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+
+static void mpic_enable_irq(unsigned int irq)
+{
+	unsigned int loops = 100000;
+	struct mpic *mpic = mpic_from_irq(irq);
+	unsigned int src = irq - mpic->irq_offset;
+
+	DBG("%s: enable_irq: %d (src %d)\n", mpic->name, irq, src);
+
+	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & ~MPIC_VECPRI_MASK);
+
+	/* make sure mask gets to controller before we return to user */
+	do {
+		if (!loops--) {
+			printk(KERN_ERR "mpic_enable_irq timeout\n");
+			break;
+		}
+	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	
+}
+
+static void mpic_disable_irq(unsigned int irq)
+{
+	unsigned int loops = 100000;
+	struct mpic *mpic = mpic_from_irq(irq);
+	unsigned int src = irq - mpic->irq_offset;
+
+	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
+
+	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | MPIC_VECPRI_MASK);
+
+	/* make sure mask gets to controller before we return to user */
+	do {
+		if (!loops--) {
+			printk(KERN_ERR "mpic_enable_irq timeout\n");
+			break;
+		}
+	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+}
+
+static void mpic_end_irq(unsigned int irq)
+{
+	struct mpic *mpic = mpic_from_irq(irq);
+
+	DBG("%s: end_irq: %d\n", mpic->name, irq);
+
+	/* We always EOI on end_irq() even for edge interrupts since that
+	 * should only lower the priority, the MPIC should have properly
+	 * latched another edge interrupt coming in anyway
+	 */
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	if (mpic->flags & MPIC_BROKEN_U3) {
+		unsigned int src = irq - mpic->irq_offset;
+		if (mpic_is_ht_interrupt(mpic, src))
+			mpic_apic_end_irq(mpic, src);
+	}
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+	mpic_eoi(mpic);
+}
+
+#ifdef CONFIG_SMP
+
+static void mpic_enable_ipi(unsigned int irq)
+{
+	struct mpic *mpic = mpic_from_ipi(irq);
+	unsigned int src = irq - mpic->ipi_offset;
+
+	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
+	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
+}
+
+static void mpic_disable_ipi(unsigned int irq)
+{
+	/* NEVER disable an IPI... that's just plain wrong! */
+}
+
+static void mpic_end_ipi(unsigned int irq)
+{
+	struct mpic *mpic = mpic_from_ipi(irq);
+
+	/*
+	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
+	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
+	 * applying to them. We EOI them late to avoid re-entering.
+	 * We mark IPI's with SA_INTERRUPT as they must run with
+	 * irqs disabled.
+	 */
+	mpic_eoi(mpic);
+}
+
+#endif /* CONFIG_SMP */
+
+static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+	struct mpic *mpic = mpic_from_irq(irq);
+
+	cpumask_t tmp;
+
+	cpus_and(tmp, cpumask, cpu_online_map);
+
+	mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
+		       mpic_physmask(cpus_addr(tmp)[0]));	
+}
+
+
+/*
+ * Exported functions
+ */
+
+
+struct mpic * __init mpic_alloc(unsigned long phys_addr,
+				unsigned int flags,
+				unsigned int isu_size,
+				unsigned int irq_offset,
+				unsigned int irq_count,
+				unsigned int ipi_offset,
+				unsigned char *senses,
+				unsigned int senses_count,
+				const char *name)
+{
+	struct mpic	*mpic;
+	u32		reg;
+	const char	*vers;
+	int		i;
+
+	mpic = (struct mpic *)alloc_bootmem(sizeof(struct mpic));
+	if (mpic == NULL)
+		return NULL;
+	
+	memset(mpic, 0, sizeof(struct mpic));
+	mpic->name = name;
+
+	mpic->hc_irq.typename = name;
+	mpic->hc_irq.enable = mpic_enable_irq;
+	mpic->hc_irq.disable = mpic_disable_irq;
+	mpic->hc_irq.end = mpic_end_irq;
+	if (flags & MPIC_PRIMARY)
+		mpic->hc_irq.set_affinity = mpic_set_affinity;
+#ifdef CONFIG_SMP
+	mpic->hc_ipi.typename = name;
+	mpic->hc_ipi.enable = mpic_enable_ipi;
+	mpic->hc_ipi.disable = mpic_disable_ipi;
+	mpic->hc_ipi.end = mpic_end_ipi;
+#endif /* CONFIG_SMP */
+
+	mpic->flags = flags;
+	mpic->isu_size = isu_size;
+	mpic->irq_offset = irq_offset;
+	mpic->irq_count = irq_count;
+	mpic->ipi_offset = ipi_offset;
+	mpic->num_sources = 0; /* so far */
+	mpic->senses = senses;
+	mpic->senses_count = senses_count;
+
+	/* Map the global registers */
+	mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
+	mpic->tmregs = mpic->gregs + (MPIC_TIMER_BASE >> 2);
+	BUG_ON(mpic->gregs == NULL);
+
+	/* Reset */
+	if (flags & MPIC_WANTS_RESET) {
+		mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+			   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+			   | MPIC_GREG_GCONF_RESET);
+		while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		       & MPIC_GREG_GCONF_RESET)
+			mb();
+	}
+
+	/* 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
+	 */
+	reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+	mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
+	if (isu_size == 0)
+		mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+				     >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+
+	/* Map the per-CPU registers */
+	for (i = 0; i < mpic->num_cpus; i++) {
+		mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
+					   i * MPIC_CPU_STRIDE, 0x1000);
+		BUG_ON(mpic->cpuregs[i] == NULL);
+	}
+
+	/* Initialize main ISU if none provided */
+	if (mpic->isu_size == 0) {
+		mpic->isu_size = mpic->num_sources;
+		mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
+					MPIC_IRQ_STRIDE * mpic->isu_size);
+		BUG_ON(mpic->isus[0] == NULL);
+	}
+	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
+	mpic->isu_mask = (1 << mpic->isu_shift) - 1;
+
+	/* Display version */
+	switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
+	case 1:
+		vers = "1.0";
+		break;
+	case 2:
+		vers = "1.2";
+		break;
+	case 3:
+		vers = "1.3";
+		break;
+	default:
+		vers = "<unknown>";
+		break;
+	}
+	printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n",
+	       name, vers, phys_addr, mpic->num_cpus);
+	printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size,
+	       mpic->isu_shift, mpic->isu_mask);
+
+	mpic->next = mpics;
+	mpics = mpic;
+
+	if (flags & MPIC_PRIMARY)
+		mpic_primary = mpic;
+
+	return mpic;
+}
+
+void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+			    unsigned long phys_addr)
+{
+	BUG_ON(isu_num >= MPIC_MAX_ISU);
+
+	mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
+	if ((isu_num + mpic->isu_size) > mpic->num_sources)
+		mpic->num_sources = isu_num + mpic->isu_size;
+}
+
+void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
+			       void *data)
+{
+	struct mpic *mpic = mpic_find(irq, NULL);
+	unsigned long flags;
+
+	/* Synchronization here is a bit dodgy, so don't try to replace cascade
+	 * interrupts on the fly too often ... but normally it's set up at boot.
+	 */
+	spin_lock_irqsave(&mpic_lock, flags);
+	if (mpic->cascade)	       
+		mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
+	mpic->cascade = NULL;
+	wmb();
+	mpic->cascade_vec = irq - mpic->irq_offset;
+	mpic->cascade_data = data;
+	wmb();
+	mpic->cascade = handler;
+	mpic_enable_irq(irq);
+	spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+void __init mpic_init(struct mpic *mpic)
+{
+	int i;
+
+	BUG_ON(mpic->num_sources == 0);
+
+	printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
+
+	/* Set current processor priority to max */
+	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+	/* Initialize timers: just disable them all */
+	for (i = 0; i < 4; i++) {
+		mpic_write(mpic->tmregs,
+			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+		mpic_write(mpic->tmregs,
+			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+			   MPIC_VECPRI_MASK |
+			   (MPIC_VEC_TIMER_0 + i));
+	}
+
+	/* Initialize IPIs to our reserved vectors and mark them disabled for now */
+	mpic_test_broken_ipi(mpic);
+	for (i = 0; i < 4; i++) {
+		mpic_ipi_write(i,
+			       MPIC_VECPRI_MASK |
+			       (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
+			       (MPIC_VEC_IPI_0 + i));
+#ifdef CONFIG_SMP
+		if (!(mpic->flags & MPIC_PRIMARY))
+			continue;
+		irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
+		irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi;
+		
+#endif /* CONFIG_SMP */
+	}
+
+	/* Initialize interrupt sources */
+	if (mpic->irq_count == 0)
+		mpic->irq_count = mpic->num_sources;
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	/* Do the ioapic fixups on U3 broken mpic */
+	DBG("MPIC flags: %x\n", mpic->flags);
+	if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
+		mpic_scan_ioapics(mpic);
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+	for (i = 0; i < mpic->num_sources; i++) {
+		/* start with vector = source number, and masked */
+		u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
+		int level = 0;
+		
+		/* if it's an IPI, we skip it */
+		if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
+		    (mpic->irq_offset + i) <  (mpic->ipi_offset + i + 4))
+			continue;
+
+		/* do senses munging */
+		if (mpic->senses && i < mpic->senses_count) {
+			if (mpic->senses[i] & IRQ_SENSE_LEVEL)
+				vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+			if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
+				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+		} else
+			vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+
+		/* remember if it was a level interrupts */
+		level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
+
+		/* deal with broken U3 */
+		if (mpic->flags & MPIC_BROKEN_U3) {
+#ifdef CONFIG_MPIC_BROKEN_U3
+			if (mpic_is_ht_interrupt(mpic, i)) {
+				vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
+					    MPIC_VECPRI_POLARITY_MASK);
+				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+			}
+#else
+			printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n");
+#endif
+		}
+
+		DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
+		    (level != 0));
+
+		/* init hw */
+		mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
+		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+			       1 << get_hard_smp_processor_id(boot_cpuid));
+
+		/* init linux descriptors */
+		if (i < mpic->irq_count) {
+			irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0;
+			irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq;
+		}
+	}
+	
+	/* Init spurrious vector */
+	mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+
+	/* Disable 8259 passthrough */
+	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+		   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+
+	/* Set current processor priority to 0 */
+	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+}
+
+
+
+void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+{
+	int is_ipi;
+	struct mpic *mpic = mpic_find(irq, &is_ipi);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&mpic_lock, flags);
+	if (is_ipi) {
+		reg = mpic_ipi_read(irq - mpic->ipi_offset) & MPIC_VECPRI_PRIORITY_MASK;
+		mpic_ipi_write(irq - mpic->ipi_offset,
+			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+	} else {
+		reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI)
+			& MPIC_VECPRI_PRIORITY_MASK;
+		mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
+			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+	}
+	spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+unsigned int mpic_irq_get_priority(unsigned int irq)
+{
+	int is_ipi;
+	struct mpic *mpic = mpic_find(irq, &is_ipi);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&mpic_lock, flags);
+	if (is_ipi)
+		reg = mpic_ipi_read(irq - mpic->ipi_offset);
+	else
+		reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI);
+	spin_unlock_irqrestore(&mpic_lock, flags);
+	return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
+}
+
+void mpic_setup_this_cpu(void)
+{
+#ifdef CONFIG_SMP
+	struct mpic *mpic = mpic_primary;
+	unsigned long flags;
+#ifdef CONFIG_IRQ_ALL_CPUS
+	u32 msk = 1 << hard_smp_processor_id();
+	unsigned int i;
+#endif
+
+	BUG_ON(mpic == NULL);
+
+	DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+
+	spin_lock_irqsave(&mpic_lock, flags);
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+ 	/* let the mpic know we want intrs. default affinity is 0xffffffff
+	 * until changed via /proc. That's how it's done on x86. If we want
+	 * it differently, then we should make sure we also change the default
+	 * values of irq_affinity in irq.c.
+ 	 */
+ 	for (i = 0; i < mpic->num_sources ; i++)
+		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+			mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+#endif /* CONFIG_IRQ_ALL_CPUS */
+
+	/* Set current processor priority to 0 */
+	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+
+	spin_unlock_irqrestore(&mpic_lock, flags);
+#endif /* CONFIG_SMP */
+}
+
+void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
+{
+	struct mpic *mpic = mpic_primary;
+
+	BUG_ON(mpic == NULL);
+
+	DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
+
+	mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
+}
+
+int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
+{
+	u32 irq;
+
+	irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+	DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
+
+	if (mpic->cascade && irq == mpic->cascade_vec) {
+		DBG("%s: cascading ...\n", mpic->name);
+		irq = mpic->cascade(regs, mpic->cascade_data);
+		mpic_eoi(mpic);
+		return irq;
+	}
+	if (unlikely(irq == MPIC_VEC_SPURRIOUS))
+		return -1;
+	if (irq < MPIC_VEC_IPI_0) 
+		return irq + mpic->irq_offset;
+       	DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
+	return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
+}
+
+int mpic_get_irq(struct pt_regs *regs)
+{
+	struct mpic *mpic = mpic_primary;
+
+	BUG_ON(mpic == NULL);
+
+	return mpic_get_one_irq(mpic, regs);
+}
+
+
+#ifdef CONFIG_SMP
+void mpic_request_ipis(void)
+{
+	struct mpic *mpic = mpic_primary;
+
+	BUG_ON(mpic == NULL);
+	
+	printk("requesting IPIs ... \n");
+
+	/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+	request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
+		    "IPI0 (call function)", mpic);
+	request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
+		   "IPI1 (reschedule)", mpic);
+	request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
+		   "IPI2 (unused)", mpic);
+	request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
+		   "IPI3 (debugger break)", mpic);
+
+	printk("IPIs requested... \n");
+}
+#endif /* CONFIG_SMP */
diff --git a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h
new file mode 100644
index 0000000000000000000000000000000000000000..571b3c99e0623827c682d15260f07b622a3b4058
--- /dev/null
+++ b/arch/ppc64/kernel/mpic.h
@@ -0,0 +1,267 @@
+#include <linux/irq.h>
+
+/*
+ * Global registers
+ */
+
+#define MPIC_GREG_BASE			0x01000
+
+#define MPIC_GREG_FEATURE_0		0x00000
+#define		MPIC_GREG_FEATURE_LAST_SRC_MASK		0x07ff0000
+#define		MPIC_GREG_FEATURE_LAST_SRC_SHIFT	16
+#define		MPIC_GREG_FEATURE_LAST_CPU_MASK		0x00001f00
+#define		MPIC_GREG_FEATURE_LAST_CPU_SHIFT	8
+#define		MPIC_GREG_FEATURE_VERSION_MASK		0xff
+#define MPIC_GREG_FEATURE_1		0x00010
+#define MPIC_GREG_GLOBAL_CONF_0		0x00020
+#define		MPIC_GREG_GCONF_RESET			0x80000000
+#define		MPIC_GREG_GCONF_8259_PTHROU_DIS		0x20000000
+#define		MPIC_GREG_GCONF_BASE_MASK		0x000fffff
+#define MPIC_GREG_GLOBAL_CONF_1		0x00030
+#define MPIC_GREG_VENDOR_0		0x00040
+#define MPIC_GREG_VENDOR_1		0x00050
+#define MPIC_GREG_VENDOR_2		0x00060
+#define MPIC_GREG_VENDOR_3		0x00070
+#define MPIC_GREG_VENDOR_ID		0x00080
+#define 	MPIC_GREG_VENDOR_ID_STEPPING_MASK	0x00ff0000
+#define 	MPIC_GREG_VENDOR_ID_STEPPING_SHIFT	16
+#define 	MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK	0x0000ff00
+#define 	MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT	8
+#define 	MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK	0x000000ff
+#define MPIC_GREG_PROCESSOR_INIT	0x00090
+#define MPIC_GREG_IPI_VECTOR_PRI_0	0x000a0
+#define MPIC_GREG_IPI_VECTOR_PRI_1	0x000b0
+#define MPIC_GREG_IPI_VECTOR_PRI_2	0x000c0
+#define MPIC_GREG_IPI_VECTOR_PRI_3	0x000d0
+#define MPIC_GREG_SPURIOUS		0x000e0
+#define MPIC_GREG_TIMER_FREQ		0x000f0
+
+/*
+ *
+ * Timer registers
+ */
+#define MPIC_TIMER_BASE			0x01100
+#define MPIC_TIMER_STRIDE		0x40
+
+#define MPIC_TIMER_CURRENT_CNT		0x00000
+#define MPIC_TIMER_BASE_CNT		0x00010
+#define MPIC_TIMER_VECTOR_PRI		0x00020
+#define MPIC_TIMER_DESTINATION		0x00030
+
+/*
+ * Per-Processor registers
+ */
+
+#define MPIC_CPU_THISBASE		0x00000
+#define MPIC_CPU_BASE			0x20000
+#define MPIC_CPU_STRIDE			0x01000
+
+#define MPIC_CPU_IPI_DISPATCH_0		0x00040
+#define MPIC_CPU_IPI_DISPATCH_1		0x00050
+#define MPIC_CPU_IPI_DISPATCH_2		0x00060
+#define MPIC_CPU_IPI_DISPATCH_3		0x00070
+#define MPIC_CPU_CURRENT_TASK_PRI	0x00080
+#define 	MPIC_CPU_TASKPRI_MASK			0x0000000f
+#define MPIC_CPU_WHOAMI			0x00090
+#define 	MPIC_CPU_WHOAMI_MASK			0x0000001f
+#define MPIC_CPU_INTACK			0x000a0
+#define MPIC_CPU_EOI			0x000b0
+
+/*
+ * Per-source registers
+ */
+
+#define MPIC_IRQ_BASE			0x10000
+#define MPIC_IRQ_STRIDE			0x00020
+#define MPIC_IRQ_VECTOR_PRI		0x00000
+#define 	MPIC_VECPRI_MASK			0x80000000
+#define 	MPIC_VECPRI_ACTIVITY			0x40000000	/* Read Only */
+#define 	MPIC_VECPRI_PRIORITY_MASK		0x000f0000
+#define 	MPIC_VECPRI_PRIORITY_SHIFT		16
+#define 	MPIC_VECPRI_VECTOR_MASK			0x000007ff
+#define 	MPIC_VECPRI_POLARITY_POSITIVE		0x00800000
+#define 	MPIC_VECPRI_POLARITY_NEGATIVE		0x00000000
+#define 	MPIC_VECPRI_POLARITY_MASK		0x00800000
+#define 	MPIC_VECPRI_SENSE_LEVEL			0x00400000
+#define 	MPIC_VECPRI_SENSE_EDGE			0x00000000
+#define 	MPIC_VECPRI_SENSE_MASK			0x00400000
+#define MPIC_IRQ_DESTINATION		0x00010
+
+#define MPIC_MAX_IRQ_SOURCES	2048
+#define MPIC_MAX_CPUS		32
+#define MPIC_MAX_ISU		32
+
+/*
+ * Special vector numbers (internal use only)
+ */
+#define MPIC_VEC_SPURRIOUS	255
+#define MPIC_VEC_IPI_3		254
+#define MPIC_VEC_IPI_2		253
+#define MPIC_VEC_IPI_1		252
+#define MPIC_VEC_IPI_0		251
+
+/* unused */
+#define MPIC_VEC_TIMER_3	250
+#define MPIC_VEC_TIMER_2	249
+#define MPIC_VEC_TIMER_1	248
+#define MPIC_VEC_TIMER_0	247
+
+/* Type definition of the cascade handler */
+typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+/* Fixup table entry */
+struct mpic_irq_fixup
+{
+	u8 __iomem	*base;
+	unsigned int   irq;
+};
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+
+/* The instance data of a given MPIC */
+struct mpic
+{
+	/* The "linux" controller struct */
+	hw_irq_controller	hc_irq;
+#ifdef CONFIG_SMP
+	hw_irq_controller	hc_ipi;
+#endif
+	const char		*name;
+	/* Flags */
+	unsigned int		flags;
+	/* How many irq sources in a given ISU */
+	unsigned int		isu_size;
+	unsigned int		isu_shift;
+	unsigned int		isu_mask;
+	/* Offset of irq vector numbers */
+	unsigned int		irq_offset;	
+	unsigned int		irq_count;
+	/* Offset of ipi vector numbers */
+	unsigned int		ipi_offset;
+	/* Number of sources */
+	unsigned int		num_sources;
+	/* Number of CPUs */
+	unsigned int		num_cpus;
+	/* cascade handler */
+	mpic_cascade_t		cascade;
+	void			*cascade_data;
+	unsigned int		cascade_vec;
+	/* senses array */
+	unsigned char		*senses;
+	unsigned int		senses_count;
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	/* The fixup table */
+	struct mpic_irq_fixup	*fixups;
+	spinlock_t		fixup_lock;
+#endif
+
+	/* The various ioremap'ed bases */
+	volatile u32 __iomem	*gregs;
+	volatile u32 __iomem	*tmregs;
+	volatile u32 __iomem	*cpuregs[MPIC_MAX_CPUS];
+	volatile u32 __iomem	*isus[MPIC_MAX_ISU];
+
+	/* link */
+	struct mpic		*next;
+};
+
+/* This is the primary controller, only that one has IPIs and
+ * has afinity control. A non-primary MPIC always uses CPU0
+ * registers only
+ */
+#define MPIC_PRIMARY			0x00000001
+/* Set this for a big-endian MPIC */
+#define MPIC_BIG_ENDIAN			0x00000002
+/* Broken U3 MPIC */
+#define MPIC_BROKEN_U3			0x00000004
+/* Broken IPI registers (autodetected) */
+#define MPIC_BROKEN_IPI			0x00000008
+/* MPIC wants a reset */
+#define MPIC_WANTS_RESET		0x00000010
+
+/* Allocate the controller structure and setup the linux irq descs
+ * for the range if interrupts passed in. No HW initialization is
+ * actually performed.
+ * 
+ * @phys_addr:	physial base address of the MPIC
+ * @flags:	flags, see constants above
+ * @isu_size:	number of interrupts in an ISU. Use 0 to use a
+ *              standard ISU-less setup (aka powermac)
+ * @irq_offset: first irq number to assign to this mpic
+ * @irq_count:  number of irqs to use with this mpic IRQ sources. Pass 0
+ *	        to match the number of sources
+ * @ipi_offset: first irq number to assign to this mpic IPI sources,
+ *		used only on primary mpic
+ * @senses:	array of sense values
+ * @senses_num: number of entries in the array
+ *
+ * Note about the sense array. If none is passed, all interrupts are
+ * setup to be level negative unless MPIC_BROKEN_U3 is set in which
+ * case they are edge positive (and the array is ignored anyway).
+ * The values in the array start at the first source of the MPIC,
+ * that is senses[0] correspond to linux irq "irq_offset".
+ */
+extern struct mpic *mpic_alloc(unsigned long phys_addr,
+			       unsigned int flags,
+			       unsigned int isu_size,
+			       unsigned int irq_offset,
+			       unsigned int irq_count,
+			       unsigned int ipi_offset,
+			       unsigned char *senses,
+			       unsigned int senses_num,
+			       const char *name);
+
+/* Assign ISUs, to call before mpic_init()
+ *
+ * @mpic:	controller structure as returned by mpic_alloc()
+ * @isu_num:	ISU number
+ * @phys_addr:	physical address of the ISU
+ */
+extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+			    unsigned long phys_addr);
+
+/* Initialize the controller. After this has been called, none of the above
+ * should be called again for this mpic
+ */
+extern void mpic_init(struct mpic *mpic);
+
+/* Setup a cascade. Currently, only one cascade is supported this
+ * way, though you can always do a normal request_irq() and add
+ * other cascades this way. You should call this _after_ having
+ * added all the ISUs
+ *
+ * @irq_no:	"linux" irq number of the cascade (that is offset'ed vector)
+ * @handler:	cascade handler function
+ */
+extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
+			       void *data);
+
+/*
+ * All of the following functions must only be used after the
+ * ISUs have been assigned and the controller fully initialized
+ * with mpic_init()
+ */
+
+
+/* Change/Read the priority of an interrupt. Default is 8 for irqs and
+ * 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the
+ * IPI number is then the offset'ed (linux irq number mapped to the IPI)
+ */
+extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri);
+extern unsigned int mpic_irq_get_priority(unsigned int irq);
+
+/* Setup a non-boot CPU */
+extern void mpic_setup_this_cpu(void);
+
+/* Request IPIs on primary mpic */
+extern void mpic_request_ipis(void);
+
+/* Send an IPI (non offseted number 0..3) */
+extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
+
+/* Fetch interrupt from a given mpic */
+extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
+/* This one gets to the primary mpic */
+extern int mpic_get_irq(struct pt_regs *regs);
diff --git a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c
deleted file mode 100644
index 656a493bf11c53cfeee3cf6a73429903e7a59afa..0000000000000000000000000000000000000000
--- a/arch/ppc64/kernel/open_pic.c
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
- *  arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-
-#include <asm/machdep.h>
-
-#include "open_pic.h"
-#include "open_pic_defs.h"
-#include "i8259.h"
-#include <asm/ppcdebug.h>
-
-void* OpenPIC_Addr;
-static volatile struct OpenPIC *OpenPIC = NULL;
-u_int OpenPIC_NumInitSenses __initdata = 0;
-u_char *OpenPIC_InitSenses __initdata = NULL;
-
-/*
- *  Local (static) OpenPIC Operations
- */
-
-
-/* Global Operations */
-static void openpic_reset(void);
-static void openpic_enable_8259_pass_through(void);
-static void openpic_disable_8259_pass_through(void);
-static u_int openpic_irq(void);
-static void openpic_eoi(void);
-static u_int openpic_get_priority(void);
-static void openpic_set_priority(u_int pri);
-static u_int openpic_get_spurious(void);
-static void openpic_set_spurious(u_int vector);
-
-#ifdef CONFIG_SMP
-/* Interprocessor Interrupts */
-static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
-					struct pt_regs *regs);
-#endif
-
-/* Timer Interrupts */
-static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
-static void openpic_maptimer(u_int timer, u_int cpumask);
-
-/* Interrupt Sources */
-static void openpic_enable_irq(u_int irq);
-static void openpic_disable_irq(u_int irq);
-static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
-			    int is_level);
-static void openpic_mapirq(u_int irq, u_int cpumask);
-
-static void find_ISUs(void);
-
-static u_int NumProcessors;
-static u_int NumSources;
-static int NumISUs;
-static int open_pic_irq_offset;
-static volatile unsigned char* chrp_int_ack_special;
-
-OpenPIC_SourcePtr ISU[OPENPIC_MAX_ISU];
-
-static void openpic_end_irq(unsigned int irq_nr);
-static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
-
-struct hw_interrupt_type open_pic = {
-	" OpenPIC  ",
-	NULL,
-	NULL,
-	openpic_enable_irq,
-	openpic_disable_irq,
-	NULL,
-	openpic_end_irq,
-	openpic_set_affinity
-};
-
-#ifdef CONFIG_SMP
-static void openpic_end_ipi(unsigned int irq_nr);
-static void openpic_enable_ipi(unsigned int irq_nr);
-static void openpic_disable_ipi(unsigned int irq_nr);
-
-struct hw_interrupt_type open_pic_ipi = {
-	" OpenPIC  ",
-	NULL,
-	NULL,
-	openpic_enable_ipi,
-	openpic_disable_ipi,
-	NULL,
-	openpic_end_ipi,
-	NULL
-};
-#endif /* CONFIG_SMP */
-
-unsigned int openpic_vec_ipi;
-unsigned int openpic_vec_timer;
-unsigned int openpic_vec_spurious;
-
-/*
- *  Accesses to the current processor's openpic registers
- */
-#ifdef CONFIG_SMP
-#define THIS_CPU		Processor[cpu]
-#define DECL_THIS_CPU		int cpu = hard_smp_processor_id()
-#define CHECK_THIS_CPU		check_arg_cpu(cpu)
-#else
-#define THIS_CPU		Processor[hard_smp_processor_id()]
-#define DECL_THIS_CPU
-#define CHECK_THIS_CPU
-#endif /* CONFIG_SMP */
-
-#if 0
-#define check_arg_ipi(ipi) \
-    if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
-	printk(KERN_ERR "open_pic.c:%d: invalid ipi %d\n", __LINE__, ipi);
-#define check_arg_timer(timer) \
-    if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
-	printk(KERN_ERR "open_pic.c:%d: invalid timer %d\n", __LINE__, timer);
-#define check_arg_vec(vec) \
-    if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
-	printk(KERN_ERR "open_pic.c:%d: invalid vector %d\n", __LINE__, vec);
-#define check_arg_pri(pri) \
-    if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
-	printk(KERN_ERR "open_pic.c:%d: invalid priority %d\n", __LINE__, pri);
-/*
- * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's
- * data has probably been corrupted and we're going to panic or deadlock later
- * anyway --Troy
- */
-#define check_arg_irq(irq) \
-    if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \
-      printk(KERN_ERR "open_pic.c:%d: invalid irq %d\n", __LINE__, irq); \
-      dump_stack(); }
-#define check_arg_cpu(cpu) \
-    if (cpu < 0 || cpu >= OPENPIC_MAX_PROCESSORS){ \
-	printk(KERN_ERR "open_pic.c:%d: invalid cpu %d\n", __LINE__, cpu); \
-	dump_stack(); }
-#else
-#define check_arg_ipi(ipi)	do {} while (0)
-#define check_arg_timer(timer)	do {} while (0)
-#define check_arg_vec(vec)	do {} while (0)
-#define check_arg_pri(pri)	do {} while (0)
-#define check_arg_irq(irq)	do {} while (0)
-#define check_arg_cpu(cpu)	do {} while (0)
-#endif
-
-#define GET_ISU(source)	ISU[(source) >> 4][(source) & 0xf]
-
-void __init pSeries_init_openpic(void)
-{
-        struct device_node *np;
-        int i;
-        unsigned int *addrp;
-        unsigned char* chrp_int_ack_special = NULL;
-        unsigned char init_senses[NR_IRQS - NUM_ISA_INTERRUPTS];
-        int nmi_irq = -1;
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
-        struct device_node *kbd;
-#endif
-
-        if (!(np = of_find_node_by_name(NULL, "pci"))
-            || !(addrp = (unsigned int *)
-                 get_property(np, "8259-interrupt-acknowledge", NULL)))
-                printk(KERN_ERR "Cannot find pci to get ack address\n");
-        else
-		chrp_int_ack_special = (unsigned char *)
-			__ioremap(addrp[prom_n_addr_cells(np)-1], 1, _PAGE_NO_CACHE);
-        /* hydra still sets OpenPIC_InitSenses to a static set of values */
-        if (OpenPIC_InitSenses == NULL) {
-                prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS);
-                OpenPIC_InitSenses = init_senses;
-                OpenPIC_NumInitSenses = NR_IRQS - NUM_ISA_INTERRUPTS;
-        }
-        openpic_init(1, NUM_ISA_INTERRUPTS, chrp_int_ack_special, nmi_irq);
-        for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
-                irq_desc[i].handler = &i8259_pic;
-	of_node_put(np);
-}
-
-static inline u_int openpic_read(volatile u_int *addr)
-{
-	u_int val;
-
-	val = in_le32(addr);
-	return val;
-}
-
-static inline void openpic_write(volatile u_int *addr, u_int val)
-{
-	out_le32(addr, val);
-}
-
-static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
-{
-	u_int val = openpic_read(addr);
-	return val & mask;
-}
-
-static inline void openpic_writefield(volatile u_int *addr, u_int mask,
-			       u_int field)
-{
-	u_int val = openpic_read(addr);
-	openpic_write(addr, (val & ~mask) | (field & mask));
-}
-
-static inline void openpic_clearfield(volatile u_int *addr, u_int mask)
-{
-	openpic_writefield(addr, mask, 0);
-}
-
-static inline void openpic_setfield(volatile u_int *addr, u_int mask)
-{
-	openpic_writefield(addr, mask, mask);
-}
-
-static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
-				    u_int field)
-{
-	unsigned int loops = 100000;
-
-	openpic_setfield(addr, OPENPIC_MASK);
-	while (openpic_read(addr) & OPENPIC_ACTIVITY) {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_safe_writefield timeout\n");
-			break;
-		}
-	}
-	openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
-}
-
-#ifdef CONFIG_SMP
-
-static int broken_ipi_registers;
-
-static u_int openpic_read_IPI(volatile u_int* addr)
-{
-        u_int val = 0;
-
-	if (broken_ipi_registers)
-		/* yes this is right ... bug, feature, you decide! -- tgall */
-		val = in_be32(addr);
-	else
-		val = in_le32(addr);
-
-        return val;
-}
-
-static void openpic_test_broken_IPI(void)
-{
-	u_int t;
-
-	openpic_write(&OpenPIC->Global.IPI_Vector_Priority(0), OPENPIC_MASK);
-	t = openpic_read(&OpenPIC->Global.IPI_Vector_Priority(0));
-	if (t == le32_to_cpu(OPENPIC_MASK)) {
-		printk(KERN_INFO "OpenPIC reversed IPI registers detected\n");
-		broken_ipi_registers = 1;
-	}
-}
-
-/* because of the power3 be / le above, this is needed */
-static inline void openpic_writefield_IPI(volatile u_int* addr, u_int mask, u_int field)
-{
-        u_int  val = openpic_read_IPI(addr);
-        openpic_write(addr, (val & ~mask) | (field & mask));
-}
-
-static inline void openpic_clearfield_IPI(volatile u_int *addr, u_int mask)
-{
-        openpic_writefield_IPI(addr, mask, 0);
-}
-
-static inline void openpic_setfield_IPI(volatile u_int *addr, u_int mask)
-{
-        openpic_writefield_IPI(addr, mask, mask);
-}
-
-static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int field)
-{
-	unsigned int loops = 100000;
-
-        openpic_setfield_IPI(addr, OPENPIC_MASK);
-
-        /* wait until it's not in use */
-        /* BenH: Is this code really enough ? I would rather check the result
-         *       and eventually retry ...
-         */
-        while(openpic_read_IPI(addr) & OPENPIC_ACTIVITY) {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_safe_writefield timeout\n");
-			break;
-		}
-	}
-
-        openpic_writefield_IPI(addr, mask, field | OPENPIC_MASK);
-}
-#endif /* CONFIG_SMP */
-
-void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
-			 int programmer_switch_irq)
-{
-	u_int t, i;
-	u_int timerfreq;
-	const char *version;
-
-	if (!OpenPIC_Addr) {
-		printk(KERN_INFO "No OpenPIC found !\n");
-		return;
-	}
-	OpenPIC = (volatile struct OpenPIC *)OpenPIC_Addr;
-
-	ppc64_boot_msg(0x20, "OpenPic Init");
-
-	t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
-	switch (t & OPENPIC_FEATURE_VERSION_MASK) {
-	case 1:
-		version = "1.0";
-		break;
-	case 2:
-		version = "1.2";
-		break;
-	case 3:
-		version = "1.3";
-		break;
-	default:
-		version = "?";
-		break;
-	}
-	NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
-			 OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
-	NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
-		      OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
-	printk(KERN_INFO "OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n",
-	       version, NumProcessors, NumSources, OpenPIC);
-	timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
-	if (timerfreq)
-		printk(KERN_INFO "OpenPIC timer frequency is %d.%06d MHz\n",
-		       timerfreq / 1000000, timerfreq % 1000000);
-
-	if (!main_pic)
-		return;
-
-	open_pic_irq_offset = offset;
-	chrp_int_ack_special = (volatile unsigned char*)chrp_ack;
-
-	find_ISUs();
-
-	/* Initialize timer interrupts */
-	for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
-		/* Disabled, Priority 0 */
-		openpic_inittimer(i, 0, openpic_vec_timer+i);
-		/* No processor */
-		openpic_maptimer(i, 0);
-	}
-
-#ifdef CONFIG_SMP
-	/* Initialize IPI interrupts */
-	openpic_test_broken_IPI();
-	for (i = 0; i < OPENPIC_NUM_IPI; i++) {
-		/* Disabled, Priority 10..13 */
-		openpic_initipi(i, 10+i, openpic_vec_ipi+i);
-		/* IPIs are per-CPU */
-		irq_desc[openpic_vec_ipi+i].status |= IRQ_PER_CPU;
-		irq_desc[openpic_vec_ipi+i].handler = &open_pic_ipi;
-	}
-#endif
-
-	/* Initialize external interrupts */
-	openpic_set_priority(0xf);
-
-	/* SIOint (8259 cascade) is special */
-	if (offset) {
-		openpic_initirq(0, 8, offset, 1, 1);
-		openpic_mapirq(0, 1 << get_hard_smp_processor_id(boot_cpuid));
-	}
-
-	/* Init all external sources */
-	for (i = 0; i < NumSources; i++) {
-		int pri, sense;
-
-		/* skip cascade if any */
-		if (offset && i == 0)
-			continue;
-		/* the bootloader may have left it enabled (bad !) */
-		openpic_disable_irq(i+offset);
-
-		pri = (i == programmer_switch_irq)? 9: 8;
-		sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1;
-		if (sense)
-			irq_desc[i+offset].status = IRQ_LEVEL;
-
-		/* Enabled, Priority 8 or 9 */
-		openpic_initirq(i, pri, i+offset, !sense, sense);
-		/* Processor 0 */
-		openpic_mapirq(i, 1 << get_hard_smp_processor_id(boot_cpuid));
-	}
-
-	/* Init descriptors */
-	for (i = offset; i < NumSources + offset; i++)
-		irq_desc[i].handler = &open_pic;
-
-	/* Initialize the spurious interrupt */
-	openpic_set_spurious(openpic_vec_spurious);
-
-	openpic_set_priority(0);
-	openpic_disable_8259_pass_through();
-
-	ppc64_boot_msg(0x25, "OpenPic Done");
-}
-
-/* 
- * We cant do this in init_IRQ because we need the memory subsystem up for
- * request_irq()
- */
-static int __init openpic_setup_i8259(void)
-{
-	if (systemcfg->platform == PLATFORM_POWERMAC)
-		return 0;
-
-	if (naca->interrupt_controller == IC_OPEN_PIC) {
-		/* Initialize the cascade */
-		if (request_irq(NUM_ISA_INTERRUPTS, no_action, SA_INTERRUPT,
-				"82c59 cascade", NULL))
-			printk(KERN_ERR "Unable to get OpenPIC IRQ 0 for cascade\n");
-		i8259_init();
-	}
-
-	return 0;
-}
-arch_initcall(openpic_setup_i8259);
-
-void openpic_setup_ISU(int isu_num, unsigned long addr)
-{
-	if (isu_num >= OPENPIC_MAX_ISU)
-		return;
-	ISU[isu_num] = (OpenPIC_SourcePtr) __ioremap(addr, 0x400, _PAGE_NO_CACHE);
-	if (isu_num >= NumISUs)
-		NumISUs = isu_num + 1;
-}
-
-void find_ISUs(void)
-{
-	/* For PowerMac, setup ISUs on base openpic */
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		int i;
-		for (i=0; i<128; i+=0x10) {
-			ISU[i>>4] = &((struct OpenPIC *)OpenPIC_Addr)->Source[i];
-			NumISUs++;
-		}
-	}
-        /* Use /interrupt-controller/reg and
-         * /interrupt-controller/interrupt-ranges from OF device tree
-	 * the ISU array is setup in chrp_pci.c in ibm_add_bridges
-	 * as a result
-	 * -- tgall
-         */
-
-	/* basically each ISU is a bus, and this assumes that
-	 * open_pic_isu_count interrupts per bus are possible 
-	 * ISU == Interrupt Source
-	 *
-	 * On G5, we keep the original NumSources provided by the controller,
-	 * it's below 128, so we have room to stuff the IPIs and timers like darwin
-	 * does. We put the spurrious vector up at 0xff though.
-	 */
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		openpic_vec_ipi = NumSources;
-		openpic_vec_timer = openpic_vec_ipi + 4; 
-		openpic_vec_spurious = 0xff;
-	} else {
-		NumSources = NumISUs * 0x10;
-
-		openpic_vec_ipi = NumSources + open_pic_irq_offset;
-		openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI; 
-		openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS;
-	}
-}
-
-static inline void openpic_reset(void)
-{
-	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_RESET);
-}
-
-static inline void openpic_enable_8259_pass_through(void)
-{
-	openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
-			   OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-static void openpic_disable_8259_pass_through(void)
-{
-	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-/*
- *  Find out the current interrupt
- */
-static u_int openpic_irq(void)
-{
-	u_int vec;
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
-				OPENPIC_VECTOR_MASK);
-	return vec;
-}
-
-static void openpic_eoi(void)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
-	/* Handle PCI write posting */
-	(void)openpic_read(&OpenPIC->THIS_CPU.EOI);
-}
-
-
-static inline u_int openpic_get_priority(void)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
-				 OPENPIC_CURRENT_TASK_PRIORITY_MASK);
-}
-
-static void openpic_set_priority(u_int pri)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	check_arg_pri(pri);
-	openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
-			   OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
-}
-
-/*
- *  Get/set the spurious vector
- */
-static inline u_int openpic_get_spurious(void)
-{
-	return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
-				 OPENPIC_VECTOR_MASK);
-}
-
-static void openpic_set_spurious(u_int vec)
-{
-	check_arg_vec(vec);
-	openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
-			   vec);
-}
-
-/*
- * Convert a cpu mask from logical to physical cpu numbers.
- */
-static inline u32 physmask(u32 cpumask)
-{
-	int i;
-	u32 mask = 0;
-
-	for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
-		mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
-	return mask;
-}
-
-void openpic_init_processor(u_int cpumask)
-{
-	openpic_write(&OpenPIC->Global.Processor_Initialization,
-		      physmask(cpumask & cpus_addr(cpu_online_map)[0]));
-}
-
-#ifdef CONFIG_SMP
-/*
- *  Initialize an interprocessor interrupt (and disable it)
- *
- *  ipi: OpenPIC interprocessor interrupt number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- */
-static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
-{
-	check_arg_ipi(ipi);
-	check_arg_pri(pri);
-	check_arg_vec(vec);
-	openpic_safe_writefield_IPI(&OpenPIC->Global.IPI_Vector_Priority(ipi),
-				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
-				(pri << OPENPIC_PRIORITY_SHIFT) | vec);
-}
-
-/*
- *  Send an IPI to one or more CPUs
- *  
- *  Externally called, however, it takes an IPI number (0...OPENPIC_NUM_IPI)
- *  and not a system-wide interrupt number
- */
-void openpic_cause_IPI(u_int ipi, u_int cpumask)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	check_arg_ipi(ipi);
-	openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
-		      physmask(cpumask & cpus_addr(cpu_online_map)[0]));
-}
-
-void openpic_request_IPIs(void)
-{
-	int i;
-	
-	/*
-	 * Make sure this matches what is defined in smp.c for 
-	 * smp_message_{pass|recv}() or what shows up in 
-	 * /proc/interrupts will be wrong!!! --Troy */
-	
-	if (OpenPIC == NULL)
-		return;
-
-	/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
-	request_irq(openpic_vec_ipi, openpic_ipi_action, SA_INTERRUPT,
-		    "IPI0 (call function)", NULL);
-	request_irq(openpic_vec_ipi+1, openpic_ipi_action, SA_INTERRUPT,
-		   "IPI1 (reschedule)", NULL);
-	request_irq(openpic_vec_ipi+2, openpic_ipi_action, SA_INTERRUPT,
-		   "IPI2 (unused)", NULL);
-	request_irq(openpic_vec_ipi+3, openpic_ipi_action, SA_INTERRUPT,
-		   "IPI3 (debugger break)", NULL);
-
-	for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
-		openpic_enable_ipi(openpic_vec_ipi+i);
-}
-
-/*
- * Do per-cpu setup for SMP systems.
- *
- * Get IPI's working and start taking interrupts.
- *   -- Cort
- */
-static spinlock_t openpic_setup_lock __devinitdata = SPIN_LOCK_UNLOCKED;
-
-void __devinit do_openpic_setup_cpu(void)
-{
-#ifdef CONFIG_IRQ_ALL_CPUS
- 	int i;
-	u32 msk = 1 << hard_smp_processor_id();
-#endif
-
-	spin_lock(&openpic_setup_lock);
-
-#ifdef CONFIG_IRQ_ALL_CPUS
- 	/* let the openpic know we want intrs. default affinity
- 	 * is 0xffffffff until changed via /proc
- 	 * That's how it's done on x86. If we want it differently, then
- 	 * we should make sure we also change the default values of irq_affinity
- 	 * in irq.c.
- 	 */
- 	for (i = 0; i < NumSources ; i++)
-		openpic_mapirq(i, openpic_read(&GET_ISU(i).Destination) | msk);
-#endif /* CONFIG_IRQ_ALL_CPUS */
- 	openpic_set_priority(0);
-
-	spin_unlock(&openpic_setup_lock);
-}
-#endif /* CONFIG_SMP */
-
-/*
- *  Initialize a timer interrupt (and disable it)
- *
- *  timer: OpenPIC timer number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- */
-static void __init openpic_inittimer(u_int timer, u_int pri, u_int vec)
-{
-	check_arg_timer(timer);
-	check_arg_pri(pri);
-	check_arg_vec(vec);
-	openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
-				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
-				(pri << OPENPIC_PRIORITY_SHIFT) | vec);
-}
-
-/*
- *  Map a timer interrupt to one or more CPUs
- */
-static void __init openpic_maptimer(u_int timer, u_int cpumask)
-{
-	check_arg_timer(timer);
-	openpic_write(&OpenPIC->Global.Timer[timer].Destination,
-		      physmask(cpumask & cpus_addr(cpu_online_map)[0]));
-}
-
-
-/*
- *
- * All functions below take an offset'ed irq argument
- *
- */
-
-
-/*
- *  Enable/disable an external interrupt source
- *
- *  Externally called, irq is an offseted system-wide interrupt number
- */
-static void openpic_enable_irq(u_int irq)
-{
-	unsigned int loops = 100000;
-	check_arg_irq(irq);
-
-	openpic_clearfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_enable_irq timeout\n");
-			break;
-		}
-
-		mb(); /* sync is probably useless here */
-	} while(openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
-			OPENPIC_MASK));
-}
-
-static void openpic_disable_irq(u_int irq)
-{
-	u32 vp;
-	unsigned int loops = 100000;
-	
-	check_arg_irq(irq);
-
-	openpic_setfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_disable_irq timeout\n");
-			break;
-		}
-
-		mb();  /* sync is probably useless here */
-		vp = openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
-    			OPENPIC_MASK | OPENPIC_ACTIVITY);
-	} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
-}
-
-#ifdef CONFIG_SMP
-/*
- *  Enable/disable an IPI interrupt source
- *  
- *  Externally called, irq is an offseted system-wide interrupt number
- */
-void openpic_enable_ipi(u_int irq)
-{
-	irq -= openpic_vec_ipi;
-	check_arg_ipi(irq);
-	openpic_clearfield_IPI(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK);
-
-}
-void openpic_disable_ipi(u_int irq)
-{
-   /* NEVER disable an IPI... that's just plain wrong! */
-}
-
-#endif
-
-/*
- *  Initialize an interrupt source (and disable it!)
- *
- *  irq: OpenPIC interrupt number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- *  pol: polarity (1 for positive, 0 for negative)
- *  sense: 1 for level, 0 for edge
- */
-static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
-{
-	openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
-				OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
-				(pri << OPENPIC_PRIORITY_SHIFT) | vec |
-				(pol ? OPENPIC_POLARITY_POSITIVE :
-			    		OPENPIC_POLARITY_NEGATIVE) |
-				(sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
-}
-
-/*
- *  Map an interrupt source to one or more CPUs
- */
-static void openpic_mapirq(u_int irq, u_int physmask)
-{
-	openpic_write(&GET_ISU(irq).Destination, physmask);
-}
-
-/*
- *  Set the sense for an interrupt source (and disable it!)
- *
- *  sense: 1 for level, 0 for edge
- */
-#if 0	/* not used */
-static void openpic_set_sense(u_int irq, int sense)
-{
-	openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				OPENPIC_SENSE_LEVEL,
-				(sense ? OPENPIC_SENSE_LEVEL : 0));
-}
-
-static int openpic_get_sense(u_int irq)
-{
-	return openpic_readfield(&GET_ISU(irq).Vector_Priority,
-				 OPENPIC_SENSE_LEVEL) != 0;
-}
-#endif
-
-static void openpic_end_irq(unsigned int irq_nr)
-{
-	openpic_eoi();
-}
-
-static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask)
-{
-	cpumask_t tmp;
-
-	cpus_and(tmp, cpumask, cpu_online_map);
-	openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpus_addr(tmp)[0]));
-}
-
-#ifdef CONFIG_SMP
-static void openpic_end_ipi(unsigned int irq_nr)
-{
-	/*
-	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
-	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
-	 * applying to them. We EOI them late to avoid re-entering.
-	 * We mark IPI's with SA_INTERRUPT as they must run with
-	 * irqs disabled.
-	 */
-	openpic_eoi();
-}
-
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
-					struct pt_regs *regs)
-{
-	smp_message_recv(cpl-openpic_vec_ipi, regs);
-	return IRQ_HANDLED;
-}
-
-#endif /* CONFIG_SMP */
-
-int openpic_get_irq(struct pt_regs *regs)
-{
-	extern int i8259_irq(int cpu);
-
-	int irq = openpic_irq();
-
-        if (open_pic_irq_offset && irq == open_pic_irq_offset) {
-                /*
-                 * This magic address generates a PCI IACK cycle.
-                 */
-		if ( chrp_int_ack_special )
-			irq = *chrp_int_ack_special;
-		else
-			irq = i8259_irq( smp_processor_id() );
-		openpic_eoi();
-        }
-	if (irq == openpic_vec_spurious)
-		irq = -1;
-	return irq;
-}
diff --git a/arch/ppc64/kernel/open_pic.h b/arch/ppc64/kernel/open_pic.h
deleted file mode 100644
index 21f0a7afb84a9eb3234ea83583ee0a7f60ac065d..0000000000000000000000000000000000000000
--- a/arch/ppc64/kernel/open_pic.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- *  
- */
-
-#ifndef _PPC64_KERNEL_OPEN_PIC_H
-#define _PPC64_KERNEL_OPEN_PIC_H
-
-#include <linux/config.h>
-#include <linux/cpumask.h>
-#include <linux/irq.h>
-
-#define OPENPIC_SIZE	0x40000
-
-/* OpenPIC IRQ controller structure */
-extern struct hw_interrupt_type open_pic;
-
-/* OpenPIC IPI controller structure */
-#ifdef CONFIG_SMP
-extern struct hw_interrupt_type open_pic_ipi;
-#endif /* CONFIG_SMP */
-
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-extern void* OpenPIC_Addr;
-
-/* Exported functions */
-extern void openpic_init(int, int, unsigned char *, int);
-extern void openpic_request_IPIs(void);
-extern void do_openpic_setup_cpu(void);
-extern int openpic_get_irq(struct pt_regs *regs);
-extern void openpic_init_processor(u_int cpumask);
-extern void openpic_setup_ISU(int isu_num, unsigned long addr);
-extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
-
-#endif /* _PPC64_KERNEL_OPEN_PIC_H */
diff --git a/arch/ppc64/kernel/open_pic_defs.h b/arch/ppc64/kernel/open_pic_defs.h
deleted file mode 100644
index 6459392dee89e2e442457a462e9645a4eb654431..0000000000000000000000000000000000000000
--- a/arch/ppc64/kernel/open_pic_defs.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- *  linux/openpic.h -- OpenPIC definitions
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is based on the following documentation:
- *
- *	The Open Programmable Interrupt Controller (PIC)
- *	Register Interface Specification Revision 1.2
- *
- *	Issue Date: October 1995
- *
- *	Issued jointly by Advanced Micro Devices and Cyrix Corporation
- *
- *	AMD is a registered trademark of Advanced Micro Devices, Inc.
- *	Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
- *	All Rights Reserved.
- *
- *  To receive a copy of this documentation, send an email to openpic@amd.com.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#ifndef _LINUX_OPENPIC_H
-#define _LINUX_OPENPIC_H
-
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-
-/*
- *  OpenPIC supports up to 2048 interrupt sources and up to 32 processors
- */
-
-#define OPENPIC_MAX_SOURCES	2048
-#define OPENPIC_MAX_PROCESSORS	32
-#define OPENPIC_MAX_ISU		32
-
-#define OPENPIC_NUM_TIMERS	4
-#define OPENPIC_NUM_IPI		4
-#define OPENPIC_NUM_PRI		16
-#define OPENPIC_NUM_VECTORS	OPENPIC_MAX_SOURCES
-
-/*
- *  OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
- */
-
-typedef struct _OpenPIC_Reg {
-	u_int Reg;					/* Little endian! */
-	char Pad[0xc];
-} OpenPIC_Reg;
-
-
-/*
- *  Per Processor Registers
- */
-
-typedef struct _OpenPIC_Processor {
-	/*
-	 *  Private Shadow Registers (for SLiC backwards compatibility)
-	 */
-	u_int IPI0_Dispatch_Shadow;			/* Write Only */
-	char Pad1[0x4];
-	u_int IPI0_Vector_Priority_Shadow;		/* Read/Write */
-	char Pad2[0x34];
-	/*
-	 *  Interprocessor Interrupt Command Ports
-	 */
-	OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI];	/* Write Only */
-	/*
-	 *  Current Task Priority Register
-	 */
-	OpenPIC_Reg _Current_Task_Priority;		/* Read/Write */
-	char Pad3[0x10];
-	/*
-	 *  Interrupt Acknowledge Register
-	 */
-	OpenPIC_Reg _Interrupt_Acknowledge;		/* Read Only */
-	/*
-	 *  End of Interrupt (EOI) Register
-	 */
-	OpenPIC_Reg _EOI;				/* Read/Write */
-	char Pad5[0xf40];
-} OpenPIC_Processor;
-
-
-    /*
-     *  Timer Registers
-     */
-
-typedef struct _OpenPIC_Timer {
-	OpenPIC_Reg _Current_Count;			/* Read Only */
-	OpenPIC_Reg _Base_Count;			/* Read/Write */
-	OpenPIC_Reg _Vector_Priority;			/* Read/Write */
-	OpenPIC_Reg _Destination;			/* Read/Write */
-} OpenPIC_Timer;
-
-
-    /*
-     *  Global Registers
-     */
-
-typedef struct _OpenPIC_Global {
-	/*
-	 *  Feature Reporting Registers
-	 */
-	OpenPIC_Reg _Feature_Reporting0;		/* Read Only */
-	OpenPIC_Reg _Feature_Reporting1;		/* Future Expansion */
-	/*
-	 *  Global Configuration Registers
-	 */
-	OpenPIC_Reg _Global_Configuration0;		/* Read/Write */
-	OpenPIC_Reg _Global_Configuration1;		/* Future Expansion */
-	/*
-	 *  Vendor Specific Registers
-	 */
-	OpenPIC_Reg _Vendor_Specific[4];
-	/*
-	 *  Vendor Identification Register
-	 */
-	OpenPIC_Reg _Vendor_Identification;		/* Read Only */
-	/*
-	 *  Processor Initialization Register
-	 */
-	OpenPIC_Reg _Processor_Initialization;		/* Read/Write */
-	/*
-	 *  IPI Vector/Priority Registers
-	 */
-	OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */
-	/*
-	 *  Spurious Vector Register
-	 */
-	OpenPIC_Reg _Spurious_Vector;			/* Read/Write */
-	/*
-	 *  Global Timer Registers
-	 */
-	OpenPIC_Reg _Timer_Frequency;			/* Read/Write */
-	OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
-	char Pad1[0xee00];
-} OpenPIC_Global;
-
-
-    /*
-     *  Interrupt Source Registers
-     */
-
-typedef struct _OpenPIC_Source {
-	OpenPIC_Reg _Vector_Priority;			/* Read/Write */
-	OpenPIC_Reg _Destination;			/* Read/Write */
-} OpenPIC_Source, *OpenPIC_SourcePtr;
-
-
-    /*
-     *  OpenPIC Register Map
-     */
-
-struct OpenPIC {
-	char Pad1[0x1000];
-	/*
-	 *  Global Registers
-	 */
-	OpenPIC_Global Global;
-	/*
-	 *  Interrupt Source Configuration Registers
-	 */
-	OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
-	/*
-	 *  Per Processor Registers
-	 */
-	OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
-};
-
-
-/*
- *  Current Task Priority Register
- */
-
-#define OPENPIC_CURRENT_TASK_PRIORITY_MASK	0x0000000f
-
-/*
- *  Who Am I Register
- */
-
-#define OPENPIC_WHO_AM_I_ID_MASK		0x0000001f
-
-/*
- *  Feature Reporting Register 0
- */
-
-#define OPENPIC_FEATURE_LAST_SOURCE_MASK	0x07ff0000
-#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT	16
-#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK	0x00001f00
-#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT	8
-#define OPENPIC_FEATURE_VERSION_MASK		0x000000ff
-
-/*
- *  Global Configuration Register 0
- */
-
-#define OPENPIC_CONFIG_RESET			0x80000000
-#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE	0x20000000
-#define OPENPIC_CONFIG_BASE_MASK		0x000fffff
-
-/*
- *  Vendor Identification Register
- */
-
-#define OPENPIC_VENDOR_ID_STEPPING_MASK		0x00ff0000
-#define OPENPIC_VENDOR_ID_STEPPING_SHIFT	16
-#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK	0x0000ff00
-#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT	8
-#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK	0x000000ff
-
-/*
- *  Vector/Priority Registers
- */
-
-#define OPENPIC_MASK				0x80000000
-#define OPENPIC_ACTIVITY			0x40000000	/* Read Only */
-#define OPENPIC_PRIORITY_MASK			0x000f0000
-#define OPENPIC_PRIORITY_SHIFT			16
-#define OPENPIC_VECTOR_MASK			0x000007ff
-
-
-/*
- *  Interrupt Source Registers
- */
-
-#define OPENPIC_POLARITY_POSITIVE		0x00800000
-#define OPENPIC_POLARITY_NEGATIVE		0x00000000
-#define OPENPIC_POLARITY_MASK			0x00800000
-#define OPENPIC_SENSE_LEVEL			0x00400000
-#define OPENPIC_SENSE_EDGE			0x00000000
-#define OPENPIC_SENSE_MASK			0x00400000
-
-
-/*
- *  Timer Registers
- */
-
-#define OPENPIC_COUNT_MASK			0x7fffffff
-#define OPENPIC_TIMER_TOGGLE			0x80000000
-#define OPENPIC_TIMER_COUNT_INHIBIT		0x80000000
-
-
-/*
- *  Aliases to make life simpler
- */
-
-/* Per Processor Registers */
-#define IPI_Dispatch(i)			_IPI_Dispatch[i].Reg
-#define Current_Task_Priority		_Current_Task_Priority.Reg
-#define Interrupt_Acknowledge		_Interrupt_Acknowledge.Reg
-#define EOI				_EOI.Reg
-
-/* Global Registers */
-#define Feature_Reporting0		_Feature_Reporting0.Reg
-#define Feature_Reporting1		_Feature_Reporting1.Reg
-#define Global_Configuration0		_Global_Configuration0.Reg
-#define Global_Configuration1		_Global_Configuration1.Reg
-#define Vendor_Specific(i)		_Vendor_Specific[i].Reg
-#define Vendor_Identification		_Vendor_Identification.Reg
-#define Processor_Initialization	_Processor_Initialization.Reg
-#define IPI_Vector_Priority(i)		_IPI_Vector_Priority[i].Reg
-#define Spurious_Vector			_Spurious_Vector.Reg
-#define Timer_Frequency			_Timer_Frequency.Reg
-
-/* Timer Registers */
-#define Current_Count			_Current_Count.Reg
-#define Base_Count			_Base_Count.Reg
-#define Vector_Priority			_Vector_Priority.Reg
-#define Destination			_Destination.Reg
-
-/* Interrupt Source Registers */
-#define Vector_Priority			_Vector_Priority.Reg
-#define Destination			_Destination.Reg
-
-
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_OPENPIC_H */
diff --git a/arch/ppc64/kernel/open_pic_u3.c b/arch/ppc64/kernel/open_pic_u3.c
deleted file mode 100644
index 42376756c176c6dbaf6f113fe5705299d5f35cd3..0000000000000000000000000000000000000000
--- a/arch/ppc64/kernel/open_pic_u3.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- *  arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-
-#include <asm/machdep.h>
-
-#include "open_pic.h"
-#include "open_pic_defs.h"
-
-void* OpenPIC2_Addr;
-static volatile struct OpenPIC *OpenPIC2 = NULL;
-
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-
-static u_int NumSources;
-static int NumISUs;
-static int open_pic2_irq_offset;
-
-static OpenPIC_SourcePtr ISU2[OPENPIC_MAX_ISU];
-
-unsigned int openpic2_vec_spurious;
-
-/*
- *  Accesses to the current processor's openpic registers
- *  U3 secondary openpic has only one output
- */
-#define THIS_CPU		Processor[0]
-#define DECL_THIS_CPU
-#define CHECK_THIS_CPU
-
-#define GET_ISU(source)	ISU2[(source) >> 4][(source) & 0xf]
-
-static inline u_int openpic2_read(volatile u_int *addr)
-{
-	u_int val;
-
-	val = in_be32(addr);
-	return val;
-}
-
-static inline void openpic2_write(volatile u_int *addr, u_int val)
-{
-	out_be32(addr, val);
-}
-
-static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask)
-{
-	u_int val = openpic2_read(addr);
-	return val & mask;
-}
-
-static inline void openpic2_writefield(volatile u_int *addr, u_int mask,
-			       u_int field)
-{
-	u_int val = openpic2_read(addr);
-	openpic2_write(addr, (val & ~mask) | (field & mask));
-}
-
-static inline void openpic2_clearfield(volatile u_int *addr, u_int mask)
-{
-	openpic2_writefield(addr, mask, 0);
-}
-
-static inline void openpic2_setfield(volatile u_int *addr, u_int mask)
-{
-	openpic2_writefield(addr, mask, mask);
-}
-
-static void openpic2_safe_writefield(volatile u_int *addr, u_int mask,
-				    u_int field)
-{
-	unsigned int loops = 100000;
-
-	openpic2_setfield(addr, OPENPIC_MASK);
-	while (openpic2_read(addr) & OPENPIC_ACTIVITY) {
-		if (!loops--) {
-			printk(KERN_ERR "openpic2_safe_writefield timeout\n");
-			break;
-		}
-	}
-	openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
-}
-
-
-static inline void openpic2_reset(void)
-{
-	openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_RESET);
-}
-
-static void openpic2_disable_8259_pass_through(void)
-{
-	openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-/*
- *  Find out the current interrupt
- */
-static u_int openpic2_irq(void)
-{
-	u_int vec;
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge,
-				 OPENPIC_VECTOR_MASK);
-	return vec;
-}
-
-static void openpic2_eoi(void)
-{
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0);
-	/* Handle PCI write posting */
-	(void)openpic2_read(&OpenPIC2->THIS_CPU.EOI);
-}
-
-
-static inline u_int openpic2_get_priority(void)
-{
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
-				  OPENPIC_CURRENT_TASK_PRIORITY_MASK);
-}
-
-static void openpic2_set_priority(u_int pri)
-{
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
-			    OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
-}
-
-/*
- *  Get/set the spurious vector
- */
-static inline u_int openpic2_get_spurious(void)
-{
-	return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector,
-				  OPENPIC_VECTOR_MASK);
-}
-
-static void openpic2_set_spurious(u_int vec)
-{
-	openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
-			    vec);
-}
-
-/*
- *  Enable/disable an external interrupt source
- *
- *  Externally called, irq is an offseted system-wide interrupt number
- */
-static void openpic2_enable_irq(u_int irq)
-{
-	unsigned int loops = 100000;
-
-	openpic2_clearfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_enable_irq timeout\n");
-			break;
-		}
-
-		mb(); /* sync is probably useless here */
-	} while(openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
-			OPENPIC_MASK));
-}
-
-static void openpic2_disable_irq(u_int irq)
-{
-	u32 vp;
-	unsigned int loops = 100000;
-	
-	openpic2_setfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
-			  OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_disable_irq timeout\n");
-			break;
-		}
-
-		mb();  /* sync is probably useless here */
-		vp = openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
-    			OPENPIC_MASK | OPENPIC_ACTIVITY);
-	} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
-}
-
-/*
- *  Initialize an interrupt source (and disable it!)
- *
- *  irq: OpenPIC interrupt number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- *  pol: polarity (1 for positive, 0 for negative)
- *  sense: 1 for level, 0 for edge
- */
-static void openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
-{
-	openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
-				 OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
-				 (pri << OPENPIC_PRIORITY_SHIFT) | vec |
-				 (pol ? OPENPIC_POLARITY_POSITIVE :
-				  OPENPIC_POLARITY_NEGATIVE) |
-				 (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
-}
-
-/*
- *  Map an interrupt source to one or more CPUs
- */
-static void openpic2_mapirq(u_int irq, u_int physmask)
-{
-	openpic2_write(&GET_ISU(irq).Destination, physmask);
-}
-
-/*
- *  Set the sense for an interrupt source (and disable it!)
- *
- *  sense: 1 for level, 0 for edge
- */
-static inline void openpic2_set_sense(u_int irq, int sense)
-{
-	openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				 OPENPIC_SENSE_LEVEL,
-				 (sense ? OPENPIC_SENSE_LEVEL : 0));
-}
-
-static void openpic2_end_irq(unsigned int irq_nr)
-{
-	openpic2_eoi();
-}
-
-int openpic2_get_irq(struct pt_regs *regs)
-{
-	int irq = openpic2_irq();
-
-	if (irq == openpic2_vec_spurious)
-		return -1;
-	return irq + open_pic2_irq_offset;
-}
-
-struct hw_interrupt_type open_pic2 = {
-	" OpenPIC2 ",
-	NULL,
-	NULL,
-	openpic2_enable_irq,
-	openpic2_disable_irq,
-	NULL,
-	openpic2_end_irq,
-};
-
-void __init openpic2_init(int offset)
-{
-	u_int t, i;
-	const char *version;
-
-	if (!OpenPIC2_Addr) {
-		printk(KERN_INFO "No OpenPIC2 found !\n");
-		return;
-	}
-	OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr;
-
-	ppc64_boot_msg(0x20, "OpenPic U3 Init");
-
-	t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0);
-	switch (t & OPENPIC_FEATURE_VERSION_MASK) {
-	case 1:
-		version = "1.0";
-		break;
-	case 2:
-		version = "1.2";
-		break;
-	case 3:
-		version = "1.3";
-		break;
-	default:
-		version = "?";
-		break;
-	}
-	printk(KERN_INFO "OpenPIC (U3) Version %s\n", version);
-
-	open_pic2_irq_offset = offset;
-
-	for (i=0; i<128; i+=0x10) {
-		ISU2[i>>4] = &((struct OpenPIC *)OpenPIC2_Addr)->Source[i];
-		NumISUs++;
-	}
-	NumSources = NumISUs * 0x10;
-	openpic2_vec_spurious = NumSources;
-
-	openpic2_set_priority(0xf);
-
-	/* Init all external sources */
-	for (i = 0; i < NumSources; i++) {
-		int pri, sense;
-
-		/* the bootloader may have left it enabled (bad !) */
-		openpic2_disable_irq(i+offset);
-
-		pri = 8;
-		sense = (i < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[i]: 1;
-		if (sense)
-			irq_desc[i+offset].status = IRQ_LEVEL;
-
-		/* Enabled, Priority 8 or 9 */
-		openpic2_initirq(i, pri, i, !sense, sense);
-		/* Processor 0 */
-		openpic2_mapirq(i, 0x1);
-	}
-
-	/* Init descriptors */
-	for (i = offset; i < NumSources + offset; i++)
-		irq_desc[i].handler = &open_pic2;
-
-	/* Initialize the spurious interrupt */
-	openpic2_set_spurious(openpic2_vec_spurious);
-
-	openpic2_set_priority(0);
-	openpic2_disable_8259_pass_through();
-
-	ppc64_boot_msg(0x25, "OpenPic U3 Done");
-}
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
index 9d06b5f6855315179bdbdc04bb7eb7cc51d56579..2f261b60e9edf80c69b326ee02bffebcf71d71a8 100644
--- a/arch/ppc64/kernel/pSeries_pci.c
+++ b/arch/ppc64/kernel/pSeries_pci.c
@@ -42,7 +42,7 @@
 #include <asm/iommu.h>
 #include <asm/rtas.h>
 
-#include "open_pic.h"
+#include "mpic.h"
 #include "pci.h"
 
 /* RTAS tokens */
@@ -54,6 +54,7 @@ static int ibm_write_pci_config;
 static int s7a_workaround;
 
 extern unsigned long pci_probe_only;
+extern struct mpic *pSeries_mpic;
 
 static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
 {
@@ -399,9 +400,9 @@ unsigned long __init find_and_init_phbs(void)
 		pci_process_bridge_OF_ranges(phb, node);
 		pci_setup_phb_io(phb, index == 0);
 
-		if (naca->interrupt_controller == IC_OPEN_PIC) {
+		if (naca->interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
 			int addr = root_size_cells * (index + 2) - 1;
-			openpic_setup_ISU(index, opprop[addr]); 
+			mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
 		}
 
 		index++;
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 80e0289049dc806514aa42e77bdfadea85f934d0..fc17de2a354f659d0ccf82847d4e0eea77f4e9c5 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -61,19 +61,18 @@
 #include <asm/nvram.h>
 
 #include "i8259.h"
-#include "open_pic.h"
 #include <asm/xics.h>
 #include <asm/ppcdebug.h>
 #include <asm/cputable.h>
 
+#include "mpic.h"
+
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
 #else
 #define DBG(fmt...)
 #endif
 
-extern void pSeries_init_openpic(void);
-
 extern void find_and_init_phbs(void);
 extern void pSeries_final_fixup(void);
 
@@ -91,6 +90,9 @@ extern unsigned long loops_per_jiffy;
 extern unsigned long ppc_proc_freq;
 extern unsigned long ppc_tb_freq;
 
+static volatile void __iomem * chrp_int_ack_special;
+struct mpic *pSeries_mpic;
+
 void pSeries_get_cpuinfo(struct seq_file *m)
 {
 	struct device_node *root;
@@ -120,15 +122,86 @@ static void __init fwnmi_init(void)
 		fwnmi_active = 1;
 }
 
-static void __init pSeries_setup_arch(void)
+static int pSeries_irq_cascade(struct pt_regs *regs, void *data)
+{
+	if (chrp_int_ack_special)
+		return readb(chrp_int_ack_special);
+	else
+		return i8259_irq(smp_processor_id());
+}
+
+static void __init pSeries_init_mpic(void)
+{
+        unsigned int *addrp;
+        unsigned char* chrp_int_ack_special = NULL;
+	struct device_node *np;
+        int i;
+
+	/* All ISUs are setup, complete initialization */
+	mpic_init(pSeries_mpic);
+
+	/* Check what kind of cascade ACK we have */
+        if (!(np = of_find_node_by_name(NULL, "pci"))
+            || !(addrp = (unsigned int *)
+                 get_property(np, "8259-interrupt-acknowledge", NULL)))
+                printk(KERN_ERR "Cannot find pci to get ack address\n");
+        else
+		chrp_int_ack_special = (unsigned char *) 
+			ioremap(addrp[prom_n_addr_cells(np)-1], 1);
+	of_node_put(np);
+
+	/* Setup the legacy interrupts & controller */
+        for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
+                irq_desc[i].handler = &i8259_pic;
+	i8259_init(0);
+
+	/* Hook cascade to mpic */
+	mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL);
+}
+
+static void __init pSeries_setup_mpic(void)
 {
-	struct device_node *root;
 	unsigned int *opprop;
+	unsigned long openpic_addr = 0;
+        unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS];
+        struct device_node *root;
+	int irq_count;
+
+	/* Find the Open PIC if present */
+	root = of_find_node_by_path("/");
+	opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL);
+	if (opprop != 0) {
+		int n = prom_n_addr_cells(root);
 
+		for (openpic_addr = 0; n > 0; --n)
+			openpic_addr = (openpic_addr << 32) + *opprop++;
+		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
+	}
+	of_node_put(root);
+
+	BUG_ON(openpic_addr == 0);
+
+	/* Get the sense values from OF */
+	prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
+	
+	/* Setup the openpic driver */
+	irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
+	pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY,
+				  16, 16, irq_count, /* isu size, irq offset, irq count */ 
+				  NR_IRQS - 4, /* ipi offset */
+				  senses, irq_count, /* sense & sense size */
+				  " MPIC     ");
+}
+
+static void __init pSeries_setup_arch(void)
+{
 	/* Fixup ppc_md depending on the type of interrupt controller */
 	if (naca->interrupt_controller == IC_OPEN_PIC) {
-		ppc_md.init_IRQ       = pSeries_init_openpic; 
-		ppc_md.get_irq        = openpic_get_irq;
+		ppc_md.init_IRQ       = pSeries_init_mpic; 
+		ppc_md.get_irq        = mpic_get_irq;
+		/* Allocate the mpic now, so that find_and_init_phbs() can
+		 * fill the ISUs */
+		pSeries_setup_mpic();
 	} else {
 		ppc_md.init_IRQ       = xics_init_IRQ;
 		ppc_md.get_irq        = xics_get_irq;
@@ -156,21 +229,6 @@ static void __init pSeries_setup_arch(void)
 	eeh_init();
 	find_and_init_phbs();
 
-	/* Find the Open PIC if present */
-	root = of_find_node_by_path("/");
-	opprop = (unsigned int *) get_property(root,
-				"platform-open-pic", NULL);
-	if (opprop != 0) {
-		int n = prom_n_addr_cells(root);
-		unsigned long openpic;
-
-		for (openpic = 0; n > 0; --n)
-			openpic = (openpic << 32) + *opprop++;
-		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
-		OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
-	}
-	of_node_put(root);
-
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index 49fb814445220436f1c1a8b7c4389ab32c7a2280..56a1296dcbc0b8eb05a058434106ad5750ae09e1 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -72,6 +72,7 @@
 #include <asm/lmb.h>
 
 #include "pmac.h"
+#include "mpic.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -319,29 +320,9 @@ void __init pmac_init_early(void)
 	DBG(" <- pmac_init_early\n");
 }
 
-extern void* OpenPIC_Addr;
-extern void* OpenPIC2_Addr;
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-extern void openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
-			 int programmer_switch_irq);
-extern void openpic2_init(int offset);
-extern int openpic_get_irq(struct pt_regs *regs);
-extern int openpic2_get_irq(struct pt_regs *regs);
-
-static int pmac_cascade_irq = -1;
-
-static irqreturn_t pmac_u3_do_cascade(int cpl, void *dev_id, struct pt_regs *regs)
+static int pmac_u3_cascade(struct pt_regs *regs, void *data)
 {
-	int irq;
-
-	for (;;) {
-		irq = openpic2_get_irq(regs);
-		if (irq == -1)
-			break;
-		ppc_irq_dispatch_handler(regs, irq);
-	}
-	return IRQ_HANDLED;
+	return mpic_get_one_irq((struct mpic *)data, regs);
 }
 
 static __init void pmac_init_IRQ(void)
@@ -349,6 +330,7 @@ static __init void pmac_init_IRQ(void)
         struct device_node *irqctrler  = NULL;
         struct device_node *irqctrler2 = NULL;
 	struct device_node *np = NULL;
+	struct mpic *mpic1, *mpic2;
 
 	/* We first try to detect Apple's new Core99 chipset, since mac-io
 	 * is quite different on those machines and contains an IBM MPIC2.
@@ -368,44 +350,37 @@ static __init void pmac_init_IRQ(void)
 		       (unsigned int)irqctrler->addrs[0].address);
 
 		prom_get_irq_senses(senses, 0, 128);
-		OpenPIC_InitSenses = senses;
-		OpenPIC_NumInitSenses = 128;
-		OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
-				       irqctrler->addrs[0].size);
-		openpic_init(1, 0, NULL, -1);
+		mpic1 = mpic_alloc(irqctrler->addrs[0].address,
+				   MPIC_PRIMARY | MPIC_WANTS_RESET,
+				   0, 0, 128, 256, senses, 128, " K2-MPIC  ");
+		BUG_ON(mpic1 == NULL);
+		mpic_init(mpic1);		
 
 		if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
 		    irqctrler2->n_addrs > 0) {
 			printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
 			       (u32)irqctrler2->addrs[0].address,
 			       irqctrler2->intrs[0].line);
+
 			pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
-			OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,
-						irqctrler2->addrs[0].size);
 			prom_get_irq_senses(senses, 128, 128 + 128);
-			OpenPIC_InitSenses = senses;
-			OpenPIC_NumInitSenses = 128;
-			openpic2_init(128);
-			pmac_cascade_irq = irqctrler2->intrs[0].line;
+
+			/* We don't need to set MPIC_BROKEN_U3 here since we don't have
+			 * hypertransport interrupts routed to it
+			 */
+			mpic2 = mpic_alloc(irqctrler2->addrs[0].address,
+					   MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
+					   0, 128, 128, 0, senses, 128, " U3-MPIC  ");
+			BUG_ON(mpic2 == NULL);
+			mpic_init(mpic2);
+			mpic_setup_cascade(irqctrler2->intrs[0].line,
+					   pmac_u3_cascade, mpic2);
 		}
 	}
 	of_node_put(irqctrler);
 	of_node_put(irqctrler2);
 }
 
-/* We cannot do request_irq too early ... Right now, we get the
- * cascade as a core_initcall, which should be fine for our needs
- */
-static int __init pmac_irq_cascade_init(void)
-{
-	if (request_irq(pmac_cascade_irq, pmac_u3_do_cascade, 0,
-			"U3->K2 Cascade", NULL))
-		printk(KERN_ERR "Unable to get OpenPIC IRQ for cascade\n");
-	return 0;
-}
-
-core_initcall(pmac_irq_cascade_init);
-
 static void __init pmac_progress(char *s, unsigned short hex)
 {
 	if (sccdbg) {
@@ -463,7 +438,7 @@ struct machdep_calls __initdata pmac_md = {
 	.init_early		= pmac_init_early,
        	.get_cpuinfo		= pmac_show_cpuinfo,
 	.init_IRQ		= pmac_init_IRQ,
-	.get_irq		= openpic_get_irq,
+	.get_irq		= mpic_get_irq,
 	.pcibios_fixup		= pmac_pcibios_fixup,
 	.restart		= pmac_restart,
 	.power_off		= pmac_power_off,
diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
index fb6ab40147ed1f65168e969559ce4e264f669474..e430ac579d9db47622abcc4421476451fa82f09e 100644
--- a/arch/ppc64/kernel/pmac_smp.c
+++ b/arch/ppc64/kernel/pmac_smp.c
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -48,14 +49,13 @@
 #include <asm/cacheflush.h>
 #include <asm/keylargo.h>
 
-#include "open_pic.h"
+#include "mpic.h"
+
 
 extern void pmac_secondary_start_1(void);
 extern void pmac_secondary_start_2(void);
 extern void pmac_secondary_start_3(void);
 
-extern void smp_openpic_message_pass(int target, int msg);
-
 extern struct smp_ops_t *smp_ops;
 
 static int __init smp_core99_probe(void)
@@ -75,7 +75,7 @@ static int __init smp_core99_probe(void)
 	printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
 
 	if (ncpus > 1)
-		openpic_request_IPIs();
+		mpic_request_ipis();
 
 	return ncpus;
 }
@@ -138,8 +138,8 @@ static void __init smp_core99_kick_cpu(int nr)
 
 static void __init smp_core99_setup_cpu(int cpu_nr)
 {
-	/* Setup openpic */
-	do_openpic_setup_cpu();
+	/* Setup MPIC */
+	mpic_setup_this_cpu();
 
 	if (cpu_nr == 0) {
 		extern void g5_phy_disable_cpu1(void);
@@ -157,7 +157,7 @@ extern void smp_generic_give_timebase(void);
 extern void smp_generic_take_timebase(void);
 
 struct smp_ops_t core99_smp_ops __pmacdata = {
-	.message_pass	= smp_openpic_message_pass,
+	.message_pass	= smp_mpic_message_pass,
 	.probe		= smp_core99_probe,
 	.kick_cpu	= smp_core99_kick_cpu,
 	.setup_cpu	= smp_core99_setup_cpu,
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index f9eec2a5405b759253b45f3ea3906fb21bd8ea7b..2f530a7dd2f5c6e5f48f5e5a1d1c7636effc2f9b 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -52,7 +52,6 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
-#include "open_pic.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -1092,8 +1091,7 @@ prom_n_size_cells(struct device_node* np)
  * Work out the sense (active-low level / active-high edge)
  * of each interrupt from the device tree.
  */
-void __init
-prom_get_irq_senses(unsigned char *senses, int off, int max)
+void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
 {
 	struct device_node *np;
 	int i, j;
@@ -1105,7 +1103,9 @@ prom_get_irq_senses(unsigned char *senses, int off, int max)
 		for (j = 0; j < np->n_intrs; j++) {
 			i = np->intrs[j].line;
 			if (i >= off && i < max)
-				senses[i-off] = np->intrs[j].sense;
+				senses[i-off] = np->intrs[j].sense ?
+					IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
+					IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
 		}
 	}
 }
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 52f8999a9685010e14c2dfc1e47f8e22b30c2184..de9aacb4cc4df6bf9ad6690d7e4aa761f2498dc5 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -51,7 +51,6 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
-#include "open_pic.h"
 
 #ifdef CONFIG_LOGO_LINUX_CLUT224
 #include <linux/linux_logo.h>
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index 09236dcc353a373e60ccec4a33660bc3251b85c4..1a85a8de0ab0c0916e9e4bbc8c9d143379e61de1 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -48,11 +48,12 @@
 #include <asm/iSeries/HvCallCfg.h>
 #include <asm/time.h>
 #include <asm/ppcdebug.h>
-#include "open_pic.h"
 #include <asm/machdep.h>
 #include <asm/xics.h>
 #include <asm/cputable.h>
 #include <asm/system.h>
+
+#include "mpic.h"
 #include <asm/rtas.h>
 #include <asm/plpar_wrappers.h>
 
@@ -194,7 +195,7 @@ void __init smp_init_iSeries(void)
 #endif
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-void smp_openpic_message_pass(int target, int msg)
+void smp_mpic_message_pass(int target, int msg)
 {
 	/* make sure we're sending something that translates to an IPI */
 	if ( msg > 0x3 ){
@@ -205,33 +206,36 @@ void smp_openpic_message_pass(int target, int msg)
 	switch ( target )
 	{
 	case MSG_ALL:
-		openpic_cause_IPI(msg, 0xffffffff);
+		mpic_send_ipi(msg, 0xffffffff);
 		break;
 	case MSG_ALL_BUT_SELF:
-		openpic_cause_IPI(msg,
-				  0xffffffff & ~(1 << smp_processor_id()));
+		mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
 		break;
 	default:
-		openpic_cause_IPI(msg, 1<<target);
+		mpic_send_ipi(msg, 1 << target);
 		break;
 	}
 }
 
-static int __init smp_openpic_probe(void)
+int __init smp_mpic_probe(void)
 {
 	int nr_cpus;
 
+	DBG("smp_mpic_probe()...\n");
+
 	nr_cpus = cpus_weight(cpu_possible_map);
 
+	DBG("nr_cpus: %d\n", nr_cpus);
+
 	if (nr_cpus > 1)
-		openpic_request_IPIs();
+		mpic_request_ipis();
 
 	return nr_cpus;
 }
 
-static void __devinit smp_openpic_setup_cpu(int cpu)
+void __devinit smp_mpic_setup_cpu(int cpu)
 {
-	do_openpic_setup_cpu();
+	mpic_setup_this_cpu();
 }
 
 #endif /* CONFIG_PPC_MULTIPLATFORM */
@@ -532,11 +536,11 @@ static void __devinit pSeries_take_timebase(void)
 	spin_unlock(&timebase_lock);
 }
 
-static struct smp_ops_t pSeries_openpic_smp_ops = {
-	.message_pass	= smp_openpic_message_pass,
-	.probe		= smp_openpic_probe,
+static struct smp_ops_t pSeries_mpic_smp_ops = {
+	.message_pass	= smp_mpic_message_pass,
+	.probe		= smp_mpic_probe,
 	.kick_cpu	= smp_pSeries_kick_cpu,
-	.setup_cpu	= smp_openpic_setup_cpu,
+	.setup_cpu	= smp_mpic_setup_cpu,
 };
 
 static struct smp_ops_t pSeries_xics_smp_ops = {
@@ -554,7 +558,7 @@ void __init smp_init_pSeries(void)
 	DBG(" -> smp_init_pSeries()\n");
 
 	if (naca->interrupt_controller == IC_OPEN_PIC)
-		smp_ops = &pSeries_openpic_smp_ops;
+		smp_ops = &pSeries_mpic_smp_ops;
 	else
 		smp_ops = &pSeries_xics_smp_ops;
 
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index a23da49b09cc4b11b7c1004b0694b1d0a3f5fc22..ed0deef871adc3554249a6bb608a860a25171b6a 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -578,7 +578,7 @@ static int __init xics_setup_i8259(void)
 				no_action, 0, "8259 cascade", NULL))
 			printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
 					"cascade\n");
-		i8259_init();
+		i8259_init(0);
 	}
 	return 0;
 }
diff --git a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h
index fafe9618437c430830e706752afb0b9c23526560..f04361c9b3c56a62621493c6c53efba561ff8f3b 100644
--- a/include/asm-ppc64/irq.h
+++ b/include/asm-ppc64/irq.h
@@ -20,6 +20,19 @@
 /* this number is used when no interrupt has been assigned */
 #define NO_IRQ			(-1)
 
+/*
+ * These constants are used for passing information about interrupt
+ * signal polarity and level/edge sensing to the low-level PIC chip
+ * drivers.
+ */
+#define IRQ_SENSE_MASK		0x1
+#define IRQ_SENSE_LEVEL		0x1	/* interrupt on active level */
+#define IRQ_SENSE_EDGE		0x0	/* interrupt triggered by edge */
+
+#define IRQ_POLARITY_MASK	0x2
+#define IRQ_POLARITY_POSITIVE	0x2	/* high level or low->high edge */
+#define IRQ_POLARITY_NEGATIVE	0x0	/* low level or high->low edge */
+
 #define get_irq_desc(irq) (&irq_desc[(irq)])
 
 /* Define a way to iterate across irqs. */
diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
index fc8be1b40bb026b056cb17699da5c18588dc2889..ab7000f8b43a38c340cd3f8d43249b066231b2ed 100644
--- a/include/asm-ppc64/smp.h
+++ b/include/asm-ppc64/smp.h
@@ -67,6 +67,10 @@ extern int query_cpu_stopped(unsigned int pcpu);
 
 extern int smt_enabled_at_boot;
 
+extern int smp_mpic_probe(void);
+extern void smp_mpic_setup_cpu(int cpu);
+extern void smp_mpic_message_pass(int target, int msg);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* !(_PPC64_SMP_H) */