aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Makefile5
-rw-r--r--arch/powerpc/sysdev/commproc.c20
-rw-r--r--arch/powerpc/sysdev/cpm2_common.c21
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c46
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c2
-rw-r--r--arch/powerpc/sysdev/mpic.c162
-rw-r--r--arch/powerpc/sysdev/mpic.h38
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c183
-rw-r--r--arch/powerpc/sysdev/mpic_u3msi.c186
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c29
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c5
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_slow.c7
-rw-r--r--arch/powerpc/sysdev/rom.c32
-rw-r--r--arch/powerpc/sysdev/tsi108_dev.c7
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c12
-rw-r--r--arch/powerpc/sysdev/uic.c2
16 files changed, 666 insertions, 91 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index e96ca9618db..9ce775c38ab 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -2,7 +2,9 @@ ifeq ($(CONFIG_PPC64),y)
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-$(CONFIG_MPIC) += mpic.o
+mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o
+obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
+
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_MPC106) += grackle.o
obj-$(CONFIG_PPC_DCR) += dcr.o
@@ -26,7 +28,6 @@ endif
# Temporary hack until we have migrated to asm-powerpc
ifeq ($(ARCH),powerpc)
-obj-$(CONFIG_MTD) += rom.o
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
obj-$(CONFIG_8xx) += mpc8xx_pic.o commproc.o
obj-$(CONFIG_UCODE_PATCH) += micropatch.o
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index 9b4fafd9a84..4f67b89ba1d 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -330,7 +330,7 @@ void m8xx_cpm_dpinit(void)
* with the processor and the microcode patches applied / activated.
* But the following should be at least safe.
*/
- rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+ rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
}
/*
@@ -338,9 +338,9 @@ void m8xx_cpm_dpinit(void)
* This function returns an offset into the DPRAM area.
* Use cpm_dpram_addr() to get the virtual address of the area.
*/
-uint cpm_dpalloc(uint size, uint align)
+unsigned long cpm_dpalloc(uint size, uint align)
{
- void *start;
+ unsigned long start;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
@@ -352,30 +352,30 @@ uint cpm_dpalloc(uint size, uint align)
}
EXPORT_SYMBOL(cpm_dpalloc);
-int cpm_dpfree(uint offset)
+int cpm_dpfree(unsigned long offset)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
- ret = rh_free(&cpm_dpmem_info, (void *)offset);
+ ret = rh_free(&cpm_dpmem_info, offset);
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
return ret;
}
EXPORT_SYMBOL(cpm_dpfree);
-uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
{
- void *start;
+ unsigned long start;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
cpm_dpmem_info.alignment = align;
- start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+ start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
- return (uint)start;
+ return start;
}
EXPORT_SYMBOL(cpm_dpalloc_fixed);
@@ -385,7 +385,7 @@ void cpm_dpdump(void)
}
EXPORT_SYMBOL(cpm_dpdump);
-void *cpm_dpram_addr(uint offset)
+void *cpm_dpram_addr(unsigned long offset)
{
return (void *)(dpram_vbase + offset);
}
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index ec265995d5d..92441297479 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -248,15 +248,14 @@ static void cpm2_dpinit(void)
* varies with the processor and the microcode patches activated.
* But the following should be at least safe.
*/
- rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE,
- CPM_DATAONLY_SIZE);
+ rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
}
/* This function returns an index into the DPRAM area.
*/
-uint cpm_dpalloc(uint size, uint align)
+unsigned long cpm_dpalloc(uint size, uint align)
{
- void *start;
+ unsigned long start;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
@@ -268,13 +267,13 @@ uint cpm_dpalloc(uint size, uint align)
}
EXPORT_SYMBOL(cpm_dpalloc);
-int cpm_dpfree(uint offset)
+int cpm_dpfree(unsigned long offset)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
- ret = rh_free(&cpm_dpmem_info, (void *)offset);
+ ret = rh_free(&cpm_dpmem_info, offset);
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
return ret;
@@ -282,17 +281,17 @@ int cpm_dpfree(uint offset)
EXPORT_SYMBOL(cpm_dpfree);
/* not sure if this is ever needed */
-uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
{
- void *start;
+ unsigned long start;
unsigned long flags;
spin_lock_irqsave(&cpm_dpmem_lock, flags);
cpm_dpmem_info.alignment = align;
- start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+ start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
- return (uint)start;
+ return start;
}
EXPORT_SYMBOL(cpm_dpalloc_fixed);
@@ -302,7 +301,7 @@ void cpm_dpdump(void)
}
EXPORT_SYMBOL(cpm_dpdump);
-void *cpm_dpram_addr(uint offset)
+void *cpm_dpram_addr(unsigned long offset)
{
return (void *)(im_dprambase + offset);
}
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 336186dd7f1..a1d2042bb30 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -36,6 +36,7 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
+#include <linux/suspend.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/iommu.h>
@@ -54,6 +55,9 @@ static unsigned long dart_tablesize;
/* Virtual base address of the DART table */
static u32 *dart_vbase;
+#ifdef CONFIG_PM
+static u32 *dart_copy;
+#endif
/* Mapped base address for the dart */
static unsigned int __iomem *dart;
@@ -346,6 +350,48 @@ void iommu_init_early_dart(void)
set_pci_dma_ops(&dma_direct_ops);
}
+#ifdef CONFIG_PM
+static void iommu_dart_save(void)
+{
+ memcpy(dart_copy, dart_vbase, 2*1024*1024);
+}
+
+static void iommu_dart_restore(void)
+{
+ memcpy(dart_vbase, dart_copy, 2*1024*1024);
+ dart_tlb_invalidate_all();
+}
+
+static int __init iommu_init_late_dart(void)
+{
+ unsigned long tbasepfn;
+ struct page *p;
+
+ /* if no dart table exists then we won't need to save it
+ * and the area has also not been reserved */
+ if (!dart_tablebase)
+ return 0;
+
+ tbasepfn = __pa(dart_tablebase) >> PAGE_SHIFT;
+ register_nosave_region_late(tbasepfn,
+ tbasepfn + ((1<<24) >> PAGE_SHIFT));
+
+ /* For suspend we need to copy the dart contents because
+ * it is not part of the regular mapping (see above) and
+ * thus not saved automatically. The memory for this copy
+ * must be allocated early because we need 2 MB. */
+ p = alloc_pages(GFP_KERNEL, 21 - PAGE_SHIFT);
+ BUG_ON(!p);
+ dart_copy = page_address(p);
+
+ ppc_md.iommu_save = iommu_dart_save;
+ ppc_md.iommu_restore = iommu_dart_restore;
+
+ return 0;
+}
+
+late_initcall(iommu_init_late_dart);
+#endif
void __init alloc_dart_table(void)
{
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 8a123c71449..cad17572435 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -907,7 +907,7 @@ static int __init fs_enet_of_init(void)
struct fs_platform_info fs_enet_data;
const unsigned int *id;
const unsigned int *phy_addr;
- void *mac_addr;
+ const void *mac_addr;
const phandle *ph;
const char *model;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 0b84b7c775d..4fd2bec8991 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -36,6 +36,8 @@
#include <asm/mpic.h>
#include <asm/smp.h>
+#include "mpic.h"
+
#ifdef DEBUG
#define DBG(fmt...) printk(fmt)
#else
@@ -354,6 +356,12 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
tmp |= 0x22;
writel(tmp, fixup->base + 4);
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+ /* use the lowest bit inverted to the actual HW,
+ * set if this fixup was enabled, clear otherwise */
+ mpic->save_data[source].fixup_data = tmp | 1;
+#endif
}
static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
@@ -375,8 +383,58 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
tmp |= 1;
writel(tmp, fixup->base + 4);
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+
+#ifdef CONFIG_PM
+ /* use the lowest bit inverted to the actual HW,
+ * set if this fixup was enabled, clear otherwise */
+ mpic->save_data[source].fixup_data = tmp & ~1;
+#endif
}
+#ifdef CONFIG_PCI_MSI
+static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
+ unsigned int devfn)
+{
+ u8 __iomem *base;
+ u8 pos, flags;
+ u64 addr = 0;
+
+ for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
+ pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
+ u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
+ if (id == PCI_CAP_ID_HT) {
+ id = readb(devbase + pos + 3);
+ if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_MSI_MAPPING)
+ break;
+ }
+ }
+
+ if (pos == 0)
+ return;
+
+ base = devbase + pos;
+
+ flags = readb(base + HT_MSI_FLAGS);
+ if (!(flags & HT_MSI_FLAGS_FIXED)) {
+ addr = readl(base + HT_MSI_ADDR_LO) & HT_MSI_ADDR_LO_MASK;
+ addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32);
+ }
+
+ printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%lx\n",
+ PCI_SLOT(devfn), PCI_FUNC(devfn),
+ flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr);
+
+ if (!(flags & HT_MSI_FLAGS_ENABLE))
+ writeb(flags | HT_MSI_FLAGS_ENABLE, base + HT_MSI_FLAGS);
+}
+#else
+static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
+ unsigned int devfn)
+{
+ return;
+}
+#endif
+
static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
unsigned int devfn, u32 vdid)
{
@@ -468,6 +526,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
goto next;
mpic_scan_ht_pic(mpic, devbase, devfn, l);
+ mpic_scan_ht_msi(mpic, devbase, devfn);
next:
/* next device, if function 0 */
@@ -559,7 +618,7 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
*/
-static void mpic_unmask_irq(unsigned int irq)
+void mpic_unmask_irq(unsigned int irq)
{
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq(irq);
@@ -579,7 +638,7 @@ static void mpic_unmask_irq(unsigned int irq)
} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
}
-static void mpic_mask_irq(unsigned int irq)
+void mpic_mask_irq(unsigned int irq)
{
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq(irq);
@@ -600,7 +659,7 @@ static void mpic_mask_irq(unsigned int irq)
} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
}
-static void mpic_end_irq(unsigned int irq)
+void mpic_end_irq(unsigned int irq)
{
struct mpic *mpic = mpic_from_irq(irq);
@@ -733,7 +792,7 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
}
}
-static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
+int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
{
struct mpic *mpic = mpic_from_irq(virq);
unsigned int src = mpic_irq_to_hw(virq);
@@ -834,6 +893,8 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
if (hw >= mpic->irq_count)
return -EINVAL;
+ mpic_msi_reserve_hwirq(mpic, hw);
+
/* Default chip */
chip = &mpic->hc_irq;
@@ -1142,8 +1203,10 @@ void __init mpic_init(struct mpic *mpic)
/* Do the HT PIC fixups on U3 broken mpic */
DBG("MPIC flags: %x\n", mpic->flags);
- if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY))
- mpic_scan_ht_pics(mpic);
+ if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) {
+ mpic_scan_ht_pics(mpic);
+ mpic_u3msi_init(mpic);
+ }
for (i = 0; i < mpic->num_sources; i++) {
/* start with vector = source number, and masked */
@@ -1167,6 +1230,12 @@ void __init mpic_init(struct mpic *mpic)
/* Set current processor priority to 0 */
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
+
+#ifdef CONFIG_PM
+ /* allocate memory to save mpic state */
+ mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save));
+ BUG_ON(mpic->save_data == NULL);
+#endif
}
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -1333,8 +1402,11 @@ unsigned int mpic_get_one_irq(struct mpic *mpic)
#ifdef DEBUG_LOW
DBG("%s: get_one_irq(): %d\n", mpic->name, src);
#endif
- if (unlikely(src == mpic->spurious_vec))
+ if (unlikely(src == mpic->spurious_vec)) {
+ if (mpic->flags & MPIC_SPV_EOI)
+ mpic_eoi(mpic);
return NO_IRQ;
+ }
return irq_linear_revmap(mpic->irqhost, src);
}
@@ -1417,3 +1489,79 @@ void __devinit smp_mpic_setup_cpu(int cpu)
mpic_setup_this_cpu();
}
#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_PM
+static int mpic_suspend(struct sys_device *dev, pm_message_t state)
+{
+ struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+ int i;
+
+ for (i = 0; i < mpic->num_sources; i++) {
+ mpic->save_data[i].vecprio =
+ mpic_irq_read(i, MPIC_INFO(IRQ_VECTOR_PRI));
+ mpic->save_data[i].dest =
+ mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
+ }
+
+ return 0;
+}
+
+static int mpic_resume(struct sys_device *dev)
+{
+ struct mpic *mpic = container_of(dev, struct mpic, sysdev);
+ int i;
+
+ for (i = 0; i < mpic->num_sources; i++) {
+ mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI),
+ mpic->save_data[i].vecprio);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+ mpic->save_data[i].dest);
+
+#ifdef CONFIG_MPIC_U3_HT_IRQS
+ {
+ struct mpic_irq_fixup *fixup = &mpic->fixups[i];
+
+ if (fixup->base) {
+ /* we use the lowest bit in an inverted meaning */
+ if ((mpic->save_data[i].fixup_data & 1) == 0)
+ continue;
+
+ /* Enable and configure */
+ writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+
+ writel(mpic->save_data[i].fixup_data & ~1,
+ fixup->base + 4);
+ }
+ }
+#endif
+ } /* end for loop */
+
+ return 0;
+}
+#endif
+
+static struct sysdev_class mpic_sysclass = {
+#ifdef CONFIG_PM
+ .resume = mpic_resume,
+ .suspend = mpic_suspend,
+#endif
+ set_kset_name("mpic"),
+};
+
+static int mpic_init_sys(void)
+{
+ struct mpic *mpic = mpics;
+ int error, id = 0;
+
+ error = sysdev_class_register(&mpic_sysclass);
+
+ while (mpic && !error) {
+ mpic->sysdev.cls = &mpic_sysclass;
+ mpic->sysdev.id = id++;
+ error = sysdev_register(&mpic->sysdev);
+ mpic = mpic->next;
+ }
+ return error;
+}
+
+device_initcall(mpic_init_sys);
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
new file mode 100644
index 00000000000..3a1c3d2c594
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic.h
@@ -0,0 +1,38 @@
+#ifndef _POWERPC_SYSDEV_MPIC_H
+#define _POWERPC_SYSDEV_MPIC_H
+
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#ifdef CONFIG_PCI_MSI
+extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
+extern int mpic_msi_init_allocator(struct mpic *mpic);
+extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
+extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
+extern int mpic_u3msi_init(struct mpic *mpic);
+#else
+static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
+ irq_hw_number_t hwirq)
+{
+ return;
+}
+
+static inline int mpic_u3msi_init(struct mpic *mpic)
+{
+ return -1;
+}
+#endif
+
+extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
+extern void mpic_end_irq(unsigned int irq);
+extern void mpic_mask_irq(unsigned int irq);
+extern void mpic_unmask_irq(unsigned int irq);
+
+#endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
new file mode 100644
index 00000000000..b076793033c
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/bitmap.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+
+static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+ pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
+ bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
+}
+
+void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
+{
+ unsigned long flags;
+
+ /* The mpic calls this even when there is no allocator setup */
+ if (!mpic->hwirq_bitmap)
+ return;
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ __mpic_msi_reserve_hwirq(mpic, hwirq);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
+{
+ unsigned long flags;
+ int offset, order = get_count_order(num);
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ /*
+ * This is fast, but stricter than we need. We might want to add
+ * a fallback routine which does a linear search with no alignment.
+ */
+ offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
+ order);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+
+ pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
+ num, order, offset);
+
+ return offset;
+}
+
+void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
+{
+ unsigned long flags;
+ int order = get_count_order(num);
+
+ pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
+ num, order, offset);
+
+ spin_lock_irqsave(&mpic->bitmap_lock, flags);
+ bitmap_release_region(mpic->hwirq_bitmap, offset, order);
+ spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
+}
+
+#ifdef CONFIG_MPIC_U3_HT_IRQS
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
+{
+ irq_hw_number_t hwirq;
+ struct irq_host_ops *ops = mpic->irqhost->ops;
+ struct device_node *np;
+ int flags, index, i;
+ struct of_irq oirq;
+
+ pr_debug("mpic: found U3, guessing msi allocator setup\n");
+
+ /* Reserve source numbers we know are reserved in the HW */
+ for (i = 0; i < 8; i++)
+ __mpic_msi_reserve_hwirq(mpic, i);
+
+ for (i = 42; i < 46; i++)
+ __mpic_msi_reserve_hwirq(mpic, i);
+
+ for (i = 100; i < 105; i++)
+ __mpic_msi_reserve_hwirq(mpic, i);
+
+ np = NULL;
+ while ((np = of_find_all_nodes(np))) {
+ pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
+
+ index = 0;
+ while (of_irq_map_one(np, index++, &oirq) == 0) {
+ ops->xlate(mpic->irqhost, NULL, oirq.specifier,
+ oirq.size, &hwirq, &flags);
+ __mpic_msi_reserve_hwirq(mpic, hwirq);
+ }
+ }
+
+ return 0;
+}
+#else
+static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
+{
+ return -1;
+}
+#endif
+
+static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
+{
+ int i, len;
+ const u32 *p;
+
+ p = of_get_property(mpic->of_node, "msi-available-ranges", &len);
+ if (!p) {
+ pr_debug("mpic: no msi-available-ranges property found on %s\n",
+ mpic->of_node->full_name);
+ return -ENODEV;
+ }
+
+ if (len % 8 != 0) {
+ printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
+ "property on %s\n", mpic->of_node->full_name);
+ return -EINVAL;
+ }
+
+ bitmap_allocate_region(mpic->hwirq_bitmap, 0,
+ get_count_order(mpic->irq_count));
+
+ /* Format is: (<u32 start> <u32 count>)+ */
+ len /= sizeof(u32);
+ for (i = 0; i < len / 2; i++, p += 2)
+ mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
+
+ return 0;
+}
+
+int mpic_msi_init_allocator(struct mpic *mpic)
+{
+ int rc, size;
+
+ BUG_ON(mpic->hwirq_bitmap);
+ spin_lock_init(&mpic->bitmap_lock);
+
+ size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
+ pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
+
+ if (mem_init_done)
+ mpic->hwirq_bitmap = kmalloc(size, GFP_KERNEL);
+ else
+ mpic->hwirq_bitmap = alloc_bootmem(size);
+
+ if (!mpic->hwirq_bitmap) {
+ pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
+ return -ENOMEM;
+ }
+
+ memset(mpic->hwirq_bitmap, 0, size);
+
+ rc = mpic_msi_reserve_dt_hwirqs(mpic);
+ if (rc) {
+ if (mpic->flags & MPIC_U3_HT_IRQS)
+ rc = mpic_msi_reserve_u3_hwirqs(mpic);
+
+ if (rc)
+ goto out_free;
+ }
+
+ return 0;
+
+ out_free:
+ if (mem_init_done)
+ kfree(mpic->hwirq_bitmap);
+
+ mpic->hwirq_bitmap = NULL;
+ return rc;
+}
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
new file mode 100644
index 00000000000..305b864c25d
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2006, Segher Boessenkool, IBM Corporation.
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+#include "mpic.h"
+
+/* A bit ugly, can we get this from the pci_dev somehow? */
+static struct mpic *msi_mpic;
+
+static void mpic_u3msi_mask_irq(unsigned int irq)
+{
+ mask_msi_irq(irq);
+ mpic_mask_irq(irq);
+}
+
+static void mpic_u3msi_unmask_irq(unsigned int irq)
+{
+ mpic_unmask_irq(irq);
+ unmask_msi_irq(irq);
+}
+
+static struct irq_chip mpic_u3msi_chip = {
+ .shutdown = mpic_u3msi_mask_irq,
+ .mask = mpic_u3msi_mask_irq,
+ .unmask = mpic_u3msi_unmask_irq,
+ .eoi = mpic_end_irq,
+ .set_type = mpic_set_irq_type,
+ .typename = "MPIC-U3MSI",
+};
+
+static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
+{
+ u8 flags;
+ u32 tmp;
+ u64 addr;
+
+ pci_read_config_byte(pdev, pos + HT_MSI_FLAGS, &flags);
+
+ if (flags & HT_MSI_FLAGS_FIXED)
+ return HT_MSI_FIXED_ADDR;
+
+ pci_read_config_dword(pdev, pos + HT_MSI_ADDR_LO, &tmp);
+ addr = tmp & HT_MSI_ADDR_LO_MASK;
+ pci_read_config_dword(pdev, pos + HT_MSI_ADDR_HI, &tmp);
+ addr = addr | ((u64)tmp << 32);
+
+ return addr;
+}
+
+static u64 find_ht_magic_addr(struct pci_dev *pdev)
+{
+ struct pci_bus *bus;
+ unsigned int pos;
+
+ for (bus = pdev->bus; bus; bus = bus->parent) {
+ pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
+ if (pos)
+ return read_ht_magic_addr(bus->self, pos);
+ }
+
+ return 0;
+}
+
+static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+ if (type == PCI_CAP_ID_MSIX)
+ pr_debug("u3msi: MSI-X untested, trying anyway.\n");
+
+ /* If we can't find a magic address then MSI ain't gonna work */
+ if (find_ht_magic_addr(pdev) == 0) {
+ pr_debug("u3msi: no magic address found for %s\n",
+ pci_name(pdev));
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
+{
+ struct msi_desc *entry;
+
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ if (entry->irq == NO_IRQ)
+ continue;
+
+ set_irq_msi(entry->irq, NULL);
+ mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1);
+ irq_dispose_mapping(entry->irq);
+ }
+
+ return;
+}
+
+static void u3msi_compose_msi_msg(struct pci_dev *pdev, int virq,
+ struct msi_msg *msg)
+{
+ u64 addr;
+
+ addr = find_ht_magic_addr(pdev);
+ msg->address_lo = addr & 0xFFFFFFFF;
+ msg->address_hi = addr >> 32;
+ msg->data = virq_to_hw(virq);
+
+ pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) at address 0x%lx\n",
+ virq, virq_to_hw(virq), addr);
+}
+
+static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+ irq_hw_number_t hwirq;
+ int rc;
+ unsigned int virq;
+ struct msi_desc *entry;
+ struct msi_msg msg;
+
+ list_for_each_entry(entry, &pdev->msi_list, list) {
+ hwirq = mpic_msi_alloc_hwirqs(msi_mpic, 1);
+ if (hwirq < 0) {
+ rc = hwirq;
+ pr_debug("u3msi: failed allocating hwirq\n");
+ goto out_free;
+ }
+
+ virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
+ if (virq == NO_IRQ) {
+ pr_debug("u3msi: failed mapping hwirq 0x%lx\n", hwirq);
+ mpic_msi_free_hwirqs(msi_mpic, hwirq, 1);
+ rc = -ENOSPC;
+ goto out_free;
+ }
+
+ set_irq_msi(virq, entry);
+ set_irq_chip(virq, &mpic_u3msi_chip);
+ set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+
+ u3msi_compose_msi_msg(pdev, virq, &msg);
+ write_msi_msg(virq, &msg);
+
+ hwirq++;
+ }
+
+ return 0;
+
+ out_free:
+ u3msi_teardown_msi_irqs(pdev);
+ return rc;
+}
+
+int mpic_u3msi_init(struct mpic *mpic)
+{
+ int rc;
+
+ rc = mpic_msi_init_allocator(mpic);
+ if (rc) {
+ pr_debug("u3msi: Error allocating bitmap!\n");
+ return rc;
+ }
+
+ pr_debug("u3msi: Registering MPIC U3 MSI callbacks.\n");
+
+ BUG_ON(msi_mpic);
+ msi_mpic = mpic;
+
+ WARN_ON(ppc_md.setup_msi_irqs);
+ ppc_md.setup_msi_irqs = u3msi_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = u3msi_teardown_msi_irqs;
+ ppc_md.msi_check_device = u3msi_msi_check_device;
+
+ return 0;
+}
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 7f4c0754396..90f87408b5d 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(qe_put_snum);
static int qe_sdma_init(void)
{
struct sdma *sdma = &qe_immr->sdma;
- u32 sdma_buf_offset;
+ unsigned long sdma_buf_offset;
if (!sdma)
return -ENODEV;
@@ -252,10 +252,10 @@ static int qe_sdma_init(void)
/* allocate 2 internal temporary buffers (512 bytes size each) for
* the SDMA */
sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
- if (IS_MURAM_ERR(sdma_buf_offset))
+ if (IS_ERR_VALUE(sdma_buf_offset))
return -ENOMEM;
- out_be32(&sdma->sdebcr, sdma_buf_offset & QE_SDEBCR_BA_MASK);
+ out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
(0x1 << QE_SDMR_CEN_SHIFT)));
@@ -291,33 +291,32 @@ static void qe_muram_init(void)
if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) {
address = *of_get_address(np, 0, &size, &flags);
of_node_put(np);
- rh_attach_region(&qe_muram_info,
- (void *)address, (int)size);
+ rh_attach_region(&qe_muram_info, address, (int) size);
}
}
/* This function returns an index into the MURAM area.
*/
-u32 qe_muram_alloc(u32 size, u32 align)
+unsigned long qe_muram_alloc(int size, int align)
{
- void *start;
+ unsigned long start;
unsigned long flags;
spin_lock_irqsave(&qe_muram_lock, flags);
start = rh_alloc_align(&qe_muram_info, size, align, "QE");
spin_unlock_irqrestore(&qe_muram_lock, flags);
- return (u32) start;
+ return start;
}
EXPORT_SYMBOL(qe_muram_alloc);
-int qe_muram_free(u32 offset)
+int qe_muram_free(unsigned long offset)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&qe_muram_lock, flags);
- ret = rh_free(&qe_muram_info, (void *)offset);
+ ret = rh_free(&qe_muram_info, offset);
spin_unlock_irqrestore(&qe_muram_lock, flags);
return ret;
@@ -325,16 +324,16 @@ int qe_muram_free(u32 offset)
EXPORT_SYMBOL(qe_muram_free);
/* not sure if this is ever needed */
-u32 qe_muram_alloc_fixed(u32 offset, u32 size)
+unsigned long qe_muram_alloc_fixed(unsigned long offset, int size)
{
- void *start;
+ unsigned long start;
unsigned long flags;
spin_lock_irqsave(&qe_muram_lock, flags);
- start = rh_alloc_fixed(&qe_muram_info, (void *)offset, size, "commproc");
+ start = rh_alloc_fixed(&qe_muram_info, offset, size, "commproc");
spin_unlock_irqrestore(&qe_muram_lock, flags);
- return (u32) start;
+ return start;
}
EXPORT_SYMBOL(qe_muram_alloc_fixed);
@@ -344,7 +343,7 @@ void qe_muram_dump(void)
}
EXPORT_SYMBOL(qe_muram_dump);
-void *qe_muram_addr(u32 offset)
+void *qe_muram_addr(unsigned long offset)
{
return (void *)&qe_immr->muram[offset];
}
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 66137bf2dfb..9143236853f 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
#include <asm/io.h>
#include <asm/immap_qe.h>
@@ -268,7 +269,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
/* Allocate memory for Tx Virtual Fifo */
uccf->ucc_fast_tx_virtual_fifo_base_offset =
qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
- if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
+ if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__);
uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
ucc_fast_free(uccf);
@@ -280,7 +281,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc
qe_muram_alloc(uf_info->urfs +
UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
- if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
+ if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__);
uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
ucc_fast_free(uccf);
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index b930d686a4d..1f65c26ce63 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
#include <asm/io.h>
#include <asm/immap_qe.h>
@@ -175,7 +176,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
/* Get PRAM base */
uccs->us_pram_offset =
qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
- if (IS_MURAM_ERR(uccs->us_pram_offset)) {
+ if (IS_ERR_VALUE(uccs->us_pram_offset)) {
printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__);
ucc_slow_free(uccs);
return -ENOMEM;
@@ -210,7 +211,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
uccs->rx_base_offset =
qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
QE_ALIGNMENT_OF_BD);
- if (IS_MURAM_ERR(uccs->rx_base_offset)) {
+ if (IS_ERR_VALUE(uccs->rx_base_offset)) {
printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__);
uccs->rx_base_offset = 0;
ucc_slow_free(uccs);
@@ -220,7 +221,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
uccs->tx_base_offset =
qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
QE_ALIGNMENT_OF_BD);
- if (IS_MURAM_ERR(uccs->tx_base_offset)) {
+ if (IS_ERR_VALUE(uccs->tx_base_offset)) {
printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__);
uccs->tx_base_offset = 0;
ucc_slow_free(uccs);
diff --git a/arch/powerpc/sysdev/rom.c b/arch/powerpc/sysdev/rom.c
deleted file mode 100644
index c855a3b298a..00000000000
--- a/arch/powerpc/sysdev/rom.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * ROM device registration
- *
- * (C) 2006 MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/kernel.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
-
-static int __init powerpc_flash_init(void)
-{
- struct device_node *node = NULL;
-
- /*
- * Register all the devices which type is "rom"
- */
- while ((node = of_find_node_by_type(node, "rom")) != NULL) {
- if (node->name == NULL) {
- printk(KERN_WARNING "powerpc_flash_init: found 'rom' "
- "device, but with no name, skipping...\n");
- continue;
- }
- of_platform_device_create(node, node->name, NULL);
- }
- return 0;
-}
-
-arch_initcall(powerpc_flash_init);
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 337039ee51e..7d3b09b7d54 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -107,8 +107,9 @@ static int __init tsi108_eth_of_init(void)
goto err;
}
- mac_addr = of_get_property(np, "address", NULL);
- memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
+ mac_addr = of_get_mac_address(np);
+ if (mac_addr)
+ memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
@@ -129,6 +130,8 @@ static int __init tsi108_eth_of_init(void)
tsi_eth_data.phyregs = res.start;
tsi_eth_data.phy = *phy_id;
tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
+ if (of_device_is_compatible(phy, "bcm54xx"))
+ tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
of_node_put(phy);
ret =
platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 58b9e7f8abf..2153163fa59 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -35,6 +35,7 @@
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
#include <asm/tsi108.h>
+#include <asm/tsi108_pci.h>
#include <asm/tsi108_irq.h>
#include <asm/prom.h>
@@ -49,6 +50,7 @@
((((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)) + tsi108_pci_cfg_base)
u32 tsi108_pci_cfg_base;
+static u32 tsi108_pci_cfg_phys;
u32 tsi108_csr_vir_base;
static struct device_node *pci_irq_node;
static struct irq_host *pci_irq_host;
@@ -185,7 +187,7 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
void tsi108_clear_pci_cfg_error(void)
{
- tsi108_clear_pci_error(TSI108_PCI_CFG_BASE_PHYS);
+ tsi108_clear_pci_error(tsi108_pci_cfg_phys);
}
static struct pci_ops tsi108_direct_pci_ops = {
@@ -193,17 +195,17 @@ static struct pci_ops tsi108_direct_pci_ops = {
tsi108_direct_write_config
};
-int __init tsi108_setup_pci(struct device_node *dev)
+int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
{
int len;
struct pci_controller *hose;
struct resource rsrc;
const int *bus_range;
- int primary = 0, has_address = 0;
+ int has_address = 0;
/* PCI Config mapping */
- tsi108_pci_cfg_base = (u32)ioremap(TSI108_PCI_CFG_BASE_PHYS,
- TSI108_PCI_CFG_SIZE);
+ tsi108_pci_cfg_base = (u32)ioremap(cfg_phys, TSI108_PCI_CFG_SIZE);
+ tsi108_pci_cfg_phys = cfg_phys;
DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
tsi108_pci_cfg_base);
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 968fb40af9d..89059895a20 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -221,7 +221,7 @@ static struct uic * __init uic_init_one(struct device_node *node)
const u32 *indexp, *dcrreg;
int len;
- BUG_ON(! device_is_compatible(node, "ibm,uic"));
+ BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
uic = alloc_bootmem(sizeof(*uic));
if (! uic)