summaryrefslogtreecommitdiff
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/dart_iommu.c4
-rw-r--r--arch/powerpc/sysdev/dcr.c14
-rw-r--r--arch/powerpc/sysdev/fsl_pcie.c171
-rw-r--r--arch/powerpc/sysdev/fsl_pcie.h94
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c90
-rw-r--r--arch/powerpc/sysdev/mpic.c32
-rw-r--r--arch/powerpc/sysdev/pmi.c29
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig10
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c4
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_io.c6
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_slow.c4
-rw-r--r--arch/powerpc/sysdev/timer.c71
-rw-r--r--arch/powerpc/sysdev/tsi108_dev.c16
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c2
-rw-r--r--arch/powerpc/sysdev/uic.c342
16 files changed, 784 insertions, 110 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 26ca3ffbc1de..e96ca9618dbb 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -11,12 +11,17 @@ obj-$(CONFIG_PPC_PMI) += pmi.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
+obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
+# contains only the suspend handler for time
+obj-$(CONFIG_PM) += timer.o
+
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_PPC_83xx) += ipic.o
+obj-$(CONFIG_4xx) += uic.o
endif
# Temporary hack until we have migrated to asm-powerpc
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 1488535b0e13..336186dd7f10 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -333,7 +333,7 @@ void iommu_init_early_dart(void)
ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart;
/* Setup pci_dma ops */
- pci_dma_ops = &dma_iommu_ops;
+ set_pci_dma_ops(&dma_iommu_ops);
return;
}
@@ -343,7 +343,7 @@ void iommu_init_early_dart(void)
ppc_md.pci_dma_bus_setup = NULL;
/* Setup pci_dma ops */
- pci_dma_ops = &dma_direct_ops;
+ set_pci_dma_ops(&dma_direct_ops);
}
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index 1fc5819e7d18..574b6ef44e0b 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -26,7 +26,7 @@
unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
{
unsigned int ds;
- const u32 *dr = get_property(np, "dcr-reg", &ds);
+ const u32 *dr = of_get_property(np, "dcr-reg", &ds);
if (dr == NULL || ds & 1 || index >= (ds / 8))
return 0;
@@ -37,7 +37,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
{
unsigned int ds;
- const u32 *dr = get_property(np, "dcr-reg", &ds);
+ const u32 *dr = of_get_property(np, "dcr-reg", &ds);
if (dr == NULL || ds & 1 || index >= (ds / 8))
return 0;
@@ -53,9 +53,9 @@ static struct device_node * find_dcr_parent(struct device_node * node)
const u32 *p;
for (par = of_node_get(node); par;) {
- if (get_property(par, "dcr-controller", NULL))
+ if (of_get_property(par, "dcr-controller", NULL))
break;
- p = get_property(par, "dcr-parent", NULL);
+ p = of_get_property(par, "dcr-parent", NULL);
tmp = par;
if (p == NULL)
par = of_get_parent(par);
@@ -80,13 +80,13 @@ u64 of_translate_dcr_address(struct device_node *dev,
return OF_BAD_ADDR;
/* Stride is not properly defined yet, default to 0x10 for Axon */
- p = get_property(dp, "dcr-mmio-stride", NULL);
+ p = of_get_property(dp, "dcr-mmio-stride", NULL);
stride = (p == NULL) ? 0x10 : *p;
/* XXX FIXME: Which property name is to use of the 2 following ? */
- p = get_property(dp, "dcr-mmio-range", NULL);
+ p = of_get_property(dp, "dcr-mmio-range", NULL);
if (p == NULL)
- p = get_property(dp, "dcr-mmio-space", NULL);
+ p = of_get_property(dp, "dcr-mmio-space", NULL);
if (p == NULL)
return OF_BAD_ADDR;
diff --git a/arch/powerpc/sysdev/fsl_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c
new file mode 100644
index 000000000000..041c07e8b665
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_pcie.c
@@ -0,0 +1,171 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * 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; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * "Temporary" MPC8548 Errata file -
+ * The standard indirect_pci code should work with future silicon versions.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#define PCI_CFG_OUT out_be32
+
+/* ERRATA PCI-Ex 14 PCIE Controller timeout */
+#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff)
+
+
+static int
+indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+ u32 temp;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Possible artifact of CDCpp50937 needs further investigation */
+ if (devfn != 0x0 && bus->number == 0xff)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ PCIE_FIX;
+ if (bus->number == 0xff) {
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | ((offset & 0xf00) << 16) |
+ ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) )));
+ } else {
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000001 | ((offset & 0xf00) << 16) |
+ ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) )));
+ }
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+ cfg_data = hose->cfg_data;
+ PCIE_FIX;
+ temp = in_le32(cfg_data);
+ switch (len) {
+ case 1:
+ *val = (temp >> (((offset & 3))*8)) & 0xff;
+ break;
+ case 2:
+ *val = (temp >> (((offset & 3))*8)) & 0xffff;
+ break;
+ default:
+ *val = temp;
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ volatile void __iomem *cfg_data;
+ u32 temp;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Possible artifact of CDCpp50937 needs further investigation */
+ if (devfn != 0x0 && bus->number == 0xff)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ PCIE_FIX;
+ if (bus->number == 0xff) {
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000000 | ((offset & 0xf00) << 16) |
+ ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) )));
+ } else {
+ PCI_CFG_OUT(hose->cfg_addr,
+ (0x80000001 | ((offset & 0xf00) << 16) |
+ ((bus->number - hose->bus_offset) << 16)
+ | (devfn << 8) | ((offset & 0xfc) )));
+ }
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+ cfg_data = hose->cfg_data;
+ switch (len) {
+ case 1:
+ PCIE_FIX;
+ temp = in_le32(cfg_data);
+ temp = (temp & ~(0xff << ((offset & 3) * 8))) |
+ (val << ((offset & 3) * 8));
+ PCIE_FIX;
+ out_le32(cfg_data, temp);
+ break;
+ case 2:
+ PCIE_FIX;
+ temp = in_le32(cfg_data);
+ temp = (temp & ~(0xffff << ((offset & 3) * 8)));
+ temp |= (val << ((offset & 3) * 8)) ;
+ PCIE_FIX;
+ out_le32(cfg_data, temp);
+ break;
+ default:
+ PCIE_FIX;
+ out_le32(cfg_data, val);
+ break;
+ }
+ PCIE_FIX;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pcie_ops = {
+ indirect_read_config_pcie,
+ indirect_write_config_pcie
+};
+
+void __init
+setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+ void __iomem * cfg_data)
+{
+ hose->cfg_addr = cfg_addr;
+ hose->cfg_data = cfg_data;
+ hose->ops = &indirect_pcie_ops;
+}
+
+void __init
+setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+ unsigned long base = cfg_addr & PAGE_MASK;
+ void __iomem *mbase, *addr, *data;
+
+ mbase = ioremap(base, PAGE_SIZE);
+ addr = mbase + (cfg_addr & ~PAGE_MASK);
+ if ((cfg_data & PAGE_MASK) != base)
+ mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+ data = mbase + (cfg_data & ~PAGE_MASK);
+ setup_indirect_pcie_nomap(hose, addr, data);
+}
diff --git a/arch/powerpc/sysdev/fsl_pcie.h b/arch/powerpc/sysdev/fsl_pcie.h
new file mode 100644
index 000000000000..8d9779c84bea
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_pcie.h
@@ -0,0 +1,94 @@
+/*
+ * MPC85xx/86xx PCI Express structure define
+ *
+ * Copyright 2007 Freescale Semiconductor, Inc
+ *
+ * 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; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __POWERPC_FSL_PCIE_H
+#define __POWERPC_FSL_PCIE_H
+
+/* PCIE Express IO block registers in 85xx/86xx */
+
+struct ccsr_pex {
+ __be32 __iomem pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */
+ __be32 __iomem pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */
+ u8 __iomem res1[4];
+ __be32 __iomem pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */
+ __be32 __iomem pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */
+ u8 __iomem res2[12];
+ __be32 __iomem pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */
+ __be32 __iomem pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */
+ __be32 __iomem pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */
+ __be32 __iomem pex_pmcr; /* 0x.02c - PCI Express power management command register */
+ u8 __iomem res3[3024];
+ __be32 __iomem pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */
+ __be32 __iomem pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/
+ u8 __iomem res4[8];
+ __be32 __iomem pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/
+ u8 __iomem res5[12];
+ __be32 __iomem pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */
+ __be32 __iomem pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/
+ __be32 __iomem pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/
+ u8 __iomem res6[4];
+ __be32 __iomem pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/
+ u8 __iomem res7[12];
+ __be32 __iomem pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */
+ __be32 __iomem pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/
+ __be32 __iomem pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/
+ u8 __iomem res8[4];
+ __be32 __iomem pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/
+ u8 __iomem res9[12];
+ __be32 __iomem pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */
+ __be32 __iomem pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/
+ __be32 __iomem pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/
+ u8 __iomem res10[4];
+ __be32 __iomem pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/
+ u8 __iomem res11[12];
+ __be32 __iomem pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */
+ __be32 __iomem pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/
+ __be32 __iomem pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/
+ u8 __iomem res12[4];
+ __be32 __iomem pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/
+ u8 __iomem res13[12];
+ u8 __iomem res14[256];
+ __be32 __iomem pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */
+ u8 __iomem res15[4];
+ __be32 __iomem pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */
+ __be32 __iomem pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */
+ __be32 __iomem pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */
+ u8 __iomem res16[12];
+ __be32 __iomem pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */
+ u8 __iomem res17[4];
+ __be32 __iomem pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */
+ __be32 __iomem pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */
+ __be32 __iomem pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */
+ u8 __iomem res18[12];
+ __be32 __iomem pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */
+ u8 __iomem res19[4];
+ __be32 __iomem pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */
+ __be32 __iomem pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */
+ __be32 __iomem pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */
+ u8 __iomem res20[12];
+ __be32 __iomem pex_err_dr; /* 0x.e00 - PCI Express error detect register */
+ u8 __iomem res21[4];
+ __be32 __iomem pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */
+ u8 __iomem res22[4];
+ __be32 __iomem pex_err_disr; /* 0x.e10 - PCI Express error disable register */
+ u8 __iomem res23[12];
+ __be32 __iomem pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */
+ u8 __iomem res24[4];
+ __be32 __iomem pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */
+ __be32 __iomem pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */
+ __be32 __iomem pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */
+ __be32 __iomem pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */
+};
+
+#endif /* __POWERPC_FSL_PCIE_H */
+#endif /* __KERNEL__ */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index d20f02927f72..8a123c71449f 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -52,7 +52,7 @@ phys_addr_t get_immrbase(void)
soc = of_find_node_by_type(NULL, "soc");
if (soc) {
unsigned int size;
- const void *prop = get_property(soc, "reg", &size);
+ const void *prop = of_get_property(soc, "reg", &size);
if (prop)
immrbase = of_translate_address(soc, prop);
@@ -78,8 +78,8 @@ u32 get_brgfreq(void)
node = of_find_node_by_type(NULL, "cpm");
if (node) {
unsigned int size;
- const unsigned int *prop = get_property(node, "brg-frequency",
- &size);
+ const unsigned int *prop = of_get_property(node,
+ "brg-frequency", &size);
if (prop)
brgfreq = *prop;
@@ -103,8 +103,8 @@ u32 get_baudrate(void)
node = of_find_node_by_type(NULL, "serial");
if (node) {
unsigned int size;
- const unsigned int *prop = get_property(node, "current-speed",
- &size);
+ const unsigned int *prop = of_get_property(node,
+ "current-speed", &size);
if (prop)
fs_baudrate = *prop;
@@ -153,7 +153,8 @@ static int __init gfar_mdio_of_init(void)
while ((child = of_get_next_child(np, child)) != NULL) {
int irq = irq_of_parse_and_map(child, 0);
if (irq != NO_IRQ) {
- const u32 *id = get_property(child, "reg", NULL);
+ const u32 *id = of_get_property(child,
+ "reg", NULL);
mdio_data.irq[*id] = irq;
}
}
@@ -209,7 +210,7 @@ static int __init gfar_of_init(void)
of_irq_to_resource(np, 0, &r[1]);
- model = get_property(np, "model", NULL);
+ model = of_get_property(np, "model", NULL);
/* If we aren't the FEC we have multiple interrupts */
if (model && strcasecmp(model, "FEC")) {
@@ -253,7 +254,7 @@ static int __init gfar_of_init(void)
FSL_GIANFAR_DEV_HAS_VLAN |
FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
- ph = get_property(np, "phy-handle", NULL);
+ ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
if (phy == NULL) {
@@ -263,7 +264,7 @@ static int __init gfar_of_init(void)
mdio = of_get_parent(phy);
- id = get_property(phy, "reg", NULL);
+ id = of_get_property(phy, "reg", NULL);
ret = of_address_to_resource(mdio, 0, &res);
if (ret) {
of_node_put(phy);
@@ -325,11 +326,11 @@ static int __init fsl_i2c_of_init(void)
}
i2c_data.device_flags = 0;
- flags = get_property(np, "dfsrr", NULL);
+ flags = of_get_property(np, "dfsrr", NULL);
if (flags)
i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
- flags = get_property(np, "fsl5200-clocking", NULL);
+ flags = of_get_property(np, "fsl5200-clocking", NULL);
if (flags)
i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
@@ -374,7 +375,7 @@ static int __init mpc83xx_wdt_init(void)
goto nosoc;
}
- freq = get_property(soc, "bus-frequency", NULL);
+ freq = of_get_property(soc, "bus-frequency", NULL);
if (!freq) {
ret = -ENODEV;
goto err;
@@ -466,15 +467,15 @@ static int __init fsl_usb_of_init(void)
usb_data.operating_mode = FSL_USB2_MPH_HOST;
- prop = get_property(np, "port0", NULL);
+ prop = of_get_property(np, "port0", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
- prop = get_property(np, "port1", NULL);
+ prop = of_get_property(np, "port1", NULL);
if (prop)
usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
- prop = get_property(np, "phy_type", NULL);
+ prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
ret =
@@ -501,7 +502,7 @@ static int __init fsl_usb_of_init(void)
of_irq_to_resource(np, 0, &r[1]);
- prop = get_property(np, "dr_mode", NULL);
+ prop = of_get_property(np, "dr_mode", NULL);
if (!prop || !strcmp(prop, "host")) {
usb_data.operating_mode = FSL_USB2_DR_HOST;
@@ -538,7 +539,7 @@ static int __init fsl_usb_of_init(void)
goto err;
}
- prop = get_property(np, "phy_type", NULL);
+ prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
if (usb_dev_dr_host) {
@@ -633,7 +634,7 @@ static int __init fs_enet_of_init(void)
goto err;
}
- model = get_property(np, "model", NULL);
+ model = of_get_property(np, "model", NULL);
if (model == NULL) {
ret = -ENODEV;
goto unreg;
@@ -643,7 +644,7 @@ static int __init fs_enet_of_init(void)
if (mac_addr)
memcpy(fs_enet_data.macaddr, mac_addr, 6);
- ph = get_property(np, "phy-handle", NULL);
+ ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
if (phy == NULL) {
@@ -651,12 +652,12 @@ static int __init fs_enet_of_init(void)
goto unreg;
}
- phy_addr = get_property(phy, "reg", NULL);
+ phy_addr = of_get_property(phy, "reg", NULL);
fs_enet_data.phy_addr = *phy_addr;
- phy_irq = get_property(phy, "interrupts", NULL);
+ phy_irq = of_get_property(phy, "interrupts", NULL);
- id = get_property(np, "device-id", NULL);
+ id = of_get_property(np, "device-id", NULL);
fs_enet_data.fs_no = *id;
strcpy(fs_enet_data.fs_type, model);
@@ -668,8 +669,10 @@ static int __init fs_enet_of_init(void)
goto unreg;
}
- fs_enet_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
- fs_enet_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
+ fs_enet_data.clk_rx = *((u32 *)of_get_property(np,
+ "rx-clock", NULL));
+ fs_enet_data.clk_tx = *((u32 *)of_get_property(np,
+ "tx-clock", NULL));
if (strstr(model, "FCC")) {
int fcc_index = *id - 1;
@@ -690,7 +693,7 @@ static int __init fs_enet_of_init(void)
fs_enet_data.bus_id = (char*)&bus_id[(*id)];
fs_enet_data.init_ioports = init_fcc_ioports;
- mdio_bb_prop = get_property(phy, "bitbang", NULL);
+ mdio_bb_prop = of_get_property(phy, "bitbang", NULL);
if (mdio_bb_prop) {
struct platform_device *fs_enet_mdio_bb_dev;
struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;
@@ -796,10 +799,10 @@ static int __init cpm_uart_of_init(void)
goto err;
}
- id = get_property(np, "device-id", NULL);
+ id = of_get_property(np, "device-id", NULL);
cpm_uart_data.fs_no = *id;
- model = (char*)get_property(np, "model", NULL);
+ model = of_get_property(np, "model", NULL);
strcpy(cpm_uart_data.fs_type, model);
cpm_uart_data.uart_clk = ppc_proc_freq;
@@ -808,8 +811,10 @@ static int __init cpm_uart_of_init(void)
cpm_uart_data.tx_buf_size = 32;
cpm_uart_data.rx_num_fifo = 4;
cpm_uart_data.rx_buf_size = 32;
- cpm_uart_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
- cpm_uart_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
+ cpm_uart_data.clk_rx = *((u32 *)of_get_property(np,
+ "rx-clock", NULL));
+ cpm_uart_data.clk_tx = *((u32 *)of_get_property(np,
+ "tx-clock", NULL));
ret =
platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
@@ -833,7 +838,7 @@ arch_initcall(cpm_uart_of_init);
#ifdef CONFIG_8xx
extern void init_scc_ioports(struct fs_platform_info*);
-extern int platform_device_skip(char *model, int id);
+extern int platform_device_skip(const char *model, int id);
static int __init fs_enet_mdio_of_init(void)
{
@@ -900,21 +905,22 @@ static int __init fs_enet_of_init(void)
struct resource r[4];
struct device_node *phy = NULL, *mdio = NULL;
struct fs_platform_info fs_enet_data;
- unsigned int *id, *phy_addr;
+ const unsigned int *id;
+ const unsigned int *phy_addr;
void *mac_addr;
- phandle *ph;
- char *model;
+ const phandle *ph;
+ const char *model;
memset(r, 0, sizeof(r));
memset(&fs_enet_data, 0, sizeof(fs_enet_data));
- model = (char *)get_property(np, "model", NULL);
+ model = of_get_property(np, "model", NULL);
if (model == NULL) {
ret = -ENODEV;
goto unreg;
}
- id = (u32 *) get_property(np, "device-id", NULL);
+ id = of_get_property(np, "device-id", NULL);
fs_enet_data.fs_no = *id;
if (platform_device_skip(model, *id))
@@ -929,12 +935,12 @@ static int __init fs_enet_of_init(void)
if (mac_addr)
memcpy(fs_enet_data.macaddr, mac_addr, 6);
- ph = (phandle *) get_property(np, "phy-handle", NULL);
+ ph = of_get_property(np, "phy-handle", NULL);
if (ph != NULL)
phy = of_find_node_by_phandle(*ph);
if (phy != NULL) {
- phy_addr = (u32 *) get_property(phy, "reg", NULL);
+ phy_addr = of_get_property(phy, "reg", NULL);
fs_enet_data.phy_addr = *phy_addr;
fs_enet_data.has_phy = 1;
@@ -947,7 +953,7 @@ static int __init fs_enet_of_init(void)
}
}
- model = (char*)get_property(np, "model", NULL);
+ model = of_get_property(np, "model", NULL);
strcpy(fs_enet_data.fs_type, model);
if (strstr(model, "FEC")) {
@@ -1038,8 +1044,8 @@ static int __init cpm_smc_uart_of_init(void)
i++) {
struct resource r[3];
struct fs_uart_platform_info cpm_uart_data;
- int *id;
- char *model;
+ const int *id;
+ const char *model;
memset(r, 0, sizeof(r));
memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
@@ -1066,10 +1072,10 @@ static int __init cpm_smc_uart_of_init(void)
goto err;
}
- model = (char*)get_property(np, "model", NULL);
+ model = of_get_property(np, "model", NULL);
strcpy(cpm_uart_data.fs_type, model);
- id = (int*)get_property(np, "device-id", NULL);
+ id = of_get_property(np, "device-id", NULL);
cpm_uart_data.fs_no = *id;
cpm_uart_data.uart_clk = ppc_proc_freq;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index bcfb900481f8..0b84b7c775d8 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -304,7 +304,7 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
}
}
-#ifdef CONFIG_MPIC_BROKEN_U3
+#ifdef CONFIG_MPIC_U3_HT_IRQS
/* 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.
@@ -476,7 +476,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
}
}
-#else /* CONFIG_MPIC_BROKEN_U3 */
+#else /* CONFIG_MPIC_U3_HT_IRQS */
static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
{
@@ -487,7 +487,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
{
}
-#endif /* CONFIG_MPIC_BROKEN_U3 */
+#endif /* CONFIG_MPIC_U3_HT_IRQS */
#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
@@ -615,7 +615,7 @@ static void mpic_end_irq(unsigned int irq)
mpic_eoi(mpic);
}
-#ifdef CONFIG_MPIC_BROKEN_U3
+#ifdef CONFIG_MPIC_U3_HT_IRQS
static void mpic_unmask_ht_irq(unsigned int irq)
{
@@ -665,7 +665,7 @@ static void mpic_end_ht_irq(unsigned int irq)
mpic_ht_end_irq(mpic, src);
mpic_eoi(mpic);
}
-#endif /* !CONFIG_MPIC_BROKEN_U3 */
+#endif /* !CONFIG_MPIC_U3_HT_IRQS */
#ifdef CONFIG_SMP
@@ -788,7 +788,7 @@ static struct irq_chip mpic_ipi_chip = {
};
#endif /* CONFIG_SMP */
-#ifdef CONFIG_MPIC_BROKEN_U3
+#ifdef CONFIG_MPIC_U3_HT_IRQS
static struct irq_chip mpic_irq_ht_chip = {
.startup = mpic_startup_ht_irq,
.shutdown = mpic_shutdown_ht_irq,
@@ -797,7 +797,7 @@ static struct irq_chip mpic_irq_ht_chip = {
.eoi = mpic_end_ht_irq,
.set_type = mpic_set_irq_type,
};
-#endif /* CONFIG_MPIC_BROKEN_U3 */
+#endif /* CONFIG_MPIC_U3_HT_IRQS */
static int mpic_host_match(struct irq_host *h, struct device_node *node)
@@ -837,11 +837,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
/* Default chip */
chip = &mpic->hc_irq;
-#ifdef CONFIG_MPIC_BROKEN_U3
+#ifdef CONFIG_MPIC_U3_HT_IRQS
/* Check for HT interrupts, override vecpri */
if (mpic_is_ht_interrupt(mpic, hw))
chip = &mpic->hc_ht_irq;
-#endif /* CONFIG_MPIC_BROKEN_U3 */
+#endif /* CONFIG_MPIC_U3_HT_IRQS */
DBG("mpic: mapping to irq chip @%p\n", chip);
@@ -937,12 +937,12 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic->hc_irq.typename = name;
if (flags & MPIC_PRIMARY)
mpic->hc_irq.set_affinity = mpic_set_affinity;
-#ifdef CONFIG_MPIC_BROKEN_U3
+#ifdef CONFIG_MPIC_U3_HT_IRQS
mpic->hc_ht_irq = mpic_irq_ht_chip;
mpic->hc_ht_irq.typename = name;
if (flags & MPIC_PRIMARY)
mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
-#endif /* CONFIG_MPIC_BROKEN_U3 */
+#endif /* CONFIG_MPIC_U3_HT_IRQS */
#ifdef CONFIG_SMP
mpic->hc_ipi = mpic_ipi_chip;
@@ -970,7 +970,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic->spurious_vec = intvec_top;
/* Check for "big-endian" in device-tree */
- if (node && get_property(node, "big-endian", NULL) != NULL)
+ if (node && of_get_property(node, "big-endian", NULL) != NULL)
mpic->flags |= MPIC_BIG_ENDIAN;
@@ -986,13 +986,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
BUG_ON(paddr == 0 && node == NULL);
/* If no physical address passed in, check if it's dcr based */
- if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL)
+ if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL)
mpic->flags |= MPIC_USES_DCR;
#ifdef CONFIG_PPC_DCR
if (mpic->flags & MPIC_USES_DCR) {
const u32 *dbasep;
- dbasep = get_property(node, "dcr-reg", NULL);
+ dbasep = of_get_property(node, "dcr-reg", NULL);
BUG_ON(dbasep == NULL);
mpic->dcr_base = *dbasep;
mpic->reg_type = mpic_access_dcr;
@@ -1006,7 +1006,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
*/
if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
const u32 *reg;
- reg = get_property(node, "reg", NULL);
+ reg = of_get_property(node, "reg", NULL);
BUG_ON(reg == NULL);
paddr = of_translate_address(node, reg);
BUG_ON(paddr == OF_BAD_ADDR);
@@ -1142,7 +1142,7 @@ 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_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
+ if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY))
mpic_scan_ht_pics(mpic);
for (i = 0; i < mpic->num_sources; i++) {
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index a5282011d39e..85a7c99c1003 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -33,7 +33,7 @@
#include <asm/of_platform.h>
#include <asm/io.h>
#include <asm/pmi.h>
-
+#include <asm/prom.h>
struct pmi_data {
struct list_head handler;
@@ -49,21 +49,6 @@ struct pmi_data {
};
-
-static void __iomem *of_iomap(struct device_node *np)
-{
- struct resource res;
-
- if (of_address_to_resource(np, 0, &res))
- return NULL;
-
- pr_debug("Resource start: 0x%lx\n", res.start);
- pr_debug("Resource end: 0x%lx\n", res.end);
-
- return ioremap(res.start, 1 + res.end - res.start);
-}
-
-
static int pmi_irq_handler(int irq, void *dev_id)
{
struct pmi_data *data;
@@ -118,6 +103,7 @@ out:
static struct of_device_id pmi_match[] = {
{ .type = "ibm,pmi", .name = "ibm,pmi" },
+ { .type = "ibm,pmi" },
{},
};
@@ -153,7 +139,7 @@ static int pmi_of_probe(struct of_device *dev,
goto out;
}
- data->pmi_reg = of_iomap(np);
+ data->pmi_reg = of_iomap(np, 0);
if (!data->pmi_reg) {
printk(KERN_ERR "pmi: invalid register address.\n");
rc = -EFAULT;
@@ -279,6 +265,9 @@ void pmi_register_handler(struct of_device *device,
struct pmi_data *data;
data = device->dev.driver_data;
+ if (!data)
+ return;
+
spin_lock(&data->handler_spinlock);
list_add_tail(&handler->node, &data->handler);
spin_unlock(&data->handler_spinlock);
@@ -289,10 +278,12 @@ void pmi_unregister_handler(struct of_device *device,
struct pmi_handler *handler)
{
struct pmi_data *data;
+ data = device->dev.driver_data;
- pr_debug("pmi: unregistering handler %p\n", handler);
+ if (!data)
+ return;
- data = device->dev.driver_data;
+ pr_debug("pmi: unregistering handler %p\n", handler);
spin_lock(&data->handler_spinlock);
list_del(&handler->node);
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index a725e80befa8..887739f3badc 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -2,11 +2,8 @@
# QE Communication options
#
-menu "QE Options"
- depends on QUICC_ENGINE
-
config UCC_SLOW
- bool "UCC Slow Protocols Support"
+ bool
default n
select UCC
help
@@ -14,10 +11,9 @@ config UCC_SLOW
protocols: UART, BISYNC, QMC
config UCC_FAST
- bool "UCC Fast Protocols Support"
+ bool
default n
select UCC
- select UCC_SLOW
help
This option provides qe_lib support to UCC fast
protocols: HDLC, Ethernet, ATM, transparent
@@ -26,5 +22,3 @@ config UCC
bool
default y if UCC_FAST || UCC_SLOW
-endmenu
-
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 43f6cc9d7ea0..7f4c07543961 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -71,7 +71,7 @@ phys_addr_t get_qe_base(void)
qe = of_find_node_by_type(NULL, "qe");
if (qe) {
unsigned int size;
- const void *prop = get_property(qe, "reg", &size);
+ const void *prop = of_get_property(qe, "reg", &size);
qebase = of_translate_address(qe, prop);
of_node_put(qe);
};
@@ -158,7 +158,7 @@ unsigned int get_brg_clk(void)
qe = of_find_node_by_type(NULL, "qe");
if (qe) {
unsigned int size;
- const u32 *prop = get_property(qe, "brg-frequency", &size);
+ const u32 *prop = of_get_property(qe, "brg-frequency", &size);
brg_clk = *prop;
of_node_put(qe);
};
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index 0afe6bfe3714..e32b45bf9ff5 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -53,7 +53,7 @@ int par_io_init(struct device_node *np)
return ret;
par_io = ioremap(res.start, res.end - res.start + 1);
- num_ports = get_property(np, "num-ports", NULL);
+ num_ports = of_get_property(np, "num-ports", NULL);
if (num_ports)
num_par_io_ports = *num_ports;
@@ -161,7 +161,7 @@ int par_io_of_config(struct device_node *np)
return -1;
}
- ph = get_property(np, "pio-handle", NULL);
+ ph = of_get_property(np, "pio-handle", NULL);
if (ph == 0) {
printk(KERN_ERR "pio-handle not available \n");
return -1;
@@ -169,7 +169,7 @@ int par_io_of_config(struct device_node *np)
pio = of_find_node_by_phandle(*ph);
- pio_map = get_property(pio, "pio-map", &pio_map_len);
+ pio_map = of_get_property(pio, "pio-map", &pio_map_len);
if (pio_map == NULL) {
printk(KERN_ERR "pio-map is not set! \n");
return -1;
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 817df73ecf56..b930d686a4d1 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -187,7 +187,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
/* Init Guemr register */
- if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->regs)))) {
+ if ((ret = ucc_init_guemr((struct ucc_common *) us_regs))) {
printk(KERN_ERR "%s: cannot init GUEMR", __FUNCTION__);
ucc_slow_free(uccs);
return ret;
@@ -195,7 +195,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
/* Set UCC to slow type */
if ((ret = ucc_set_type(us_info->ucc_num,
- (struct ucc_common *) (us_info->regs),
+ (struct ucc_common *) us_regs,
UCC_SPEED_TYPE_SLOW))) {
printk(KERN_ERR "%s: cannot set UCC type", __FUNCTION__);
ucc_slow_free(uccs);
diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c
new file mode 100644
index 000000000000..4a01748b4217
--- /dev/null
+++ b/arch/powerpc/sysdev/timer.c
@@ -0,0 +1,71 @@
+/*
+ * Common code to keep time when machine suspends.
+ *
+ * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPLv2
+ */
+
+#include <linux/time.h>
+#include <linux/sysdev.h>
+#include <asm/rtc.h>
+
+static unsigned long suspend_rtc_time;
+
+/*
+ * Reset the time after a sleep.
+ */
+static int timer_resume(struct sys_device *dev)
+{
+ struct timeval tv;
+ struct timespec ts;
+ struct rtc_time cur_rtc_tm;
+ unsigned long cur_rtc_time, diff;
+
+ /* get current RTC time and convert to seconds */
+ get_rtc_time(&cur_rtc_tm);
+ rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time);
+
+ diff = cur_rtc_time - suspend_rtc_time;
+
+ /* adjust time of day by seconds that elapsed while
+ * we were suspended */
+ do_gettimeofday(&tv);
+ ts.tv_sec = tv.tv_sec + diff;
+ ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC;
+ do_settimeofday(&ts);
+
+ return 0;
+}
+
+static int timer_suspend(struct sys_device *dev, pm_message_t state)
+{
+ struct rtc_time suspend_rtc_tm;
+ WARN_ON(!ppc_md.get_rtc_time);
+
+ get_rtc_time(&suspend_rtc_tm);
+ rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time);
+
+ return 0;
+}
+
+static struct sysdev_class timer_sysclass = {
+ .resume = timer_resume,
+ .suspend = timer_suspend,
+ set_kset_name("timer"),
+};
+
+static struct sys_device device_timer = {
+ .id = 0,
+ .cls = &timer_sysclass,
+};
+
+static int time_init_device(void)
+{
+ int error = sysdev_class_register(&timer_sysclass);
+ if (!error)
+ error = sysdev_register(&device_timer);
+ return error;
+}
+
+device_initcall(time_init_device);
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 97f37ef4bbbf..337039ee51e6 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -48,7 +48,7 @@ phys_addr_t get_csrbase(void)
tsi = of_find_node_by_type(NULL, "tsi-bridge");
if (tsi) {
unsigned int size;
- const void *prop = get_property(tsi, "reg", &size);
+ const void *prop = of_get_property(tsi, "reg", &size);
tsi108_csr_base = of_translate_address(tsi, prop);
of_node_put(tsi);
};
@@ -77,10 +77,10 @@ static int __init tsi108_eth_of_init(void)
struct resource r[2];
struct device_node *phy;
hw_info tsi_eth_data;
- unsigned int *id;
- unsigned int *phy_id;
+ const unsigned int *id;
+ const unsigned int *phy_id;
const void *mac_addr;
- phandle *ph;
+ const phandle *ph;
memset(r, 0, sizeof(r));
memset(&tsi_eth_data, 0, sizeof(tsi_eth_data));
@@ -107,10 +107,10 @@ static int __init tsi108_eth_of_init(void)
goto err;
}
- mac_addr = get_property(np, "address", NULL);
+ mac_addr = of_get_property(np, "address", NULL);
memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
- ph = (phandle *) get_property(np, "phy-handle", NULL);
+ ph = of_get_property(np, "phy-handle", NULL);
phy = of_find_node_by_phandle(*ph);
if (phy == NULL) {
@@ -118,8 +118,8 @@ static int __init tsi108_eth_of_init(void)
goto unreg;
}
- id = (u32 *) get_property(phy, "reg", NULL);
- phy_id = (u32 *) get_property(phy, "phy-id", NULL);
+ id = of_get_property(phy, "reg", NULL);
+ phy_id = of_get_property(phy, "phy-id", NULL);
ret = of_address_to_resource(phy, 0, &res);
if (ret) {
of_node_put(phy);
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index ae249c6bbbcf..58b9e7f8abf2 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -211,7 +211,7 @@ int __init tsi108_setup_pci(struct device_node *dev)
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
/* Get bus range if any */
- bus_range = get_property(dev, "bus-range", &len);
+ bus_range = of_get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
new file mode 100644
index 000000000000..968fb40af9dc
--- /dev/null
+++ b/arch/powerpc/sysdev/uic.c
@@ -0,0 +1,342 @@
+/*
+ * arch/powerpc/sysdev/uic.c
+ *
+ * IBM PowerPC 4xx Universal Interrupt Controller
+ *
+ * Copyright 2007 David Gibson <dwg@au1.ibm.com>, 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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sysdev.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/dcr.h>
+
+#define NR_UIC_INTS 32
+
+#define UIC_SR 0x0
+#define UIC_ER 0x2
+#define UIC_CR 0x3
+#define UIC_PR 0x4
+#define UIC_TR 0x5
+#define UIC_MSR 0x6
+#define UIC_VR 0x7
+#define UIC_VCR 0x8
+
+#define uic_irq_to_hw(virq) (irq_map[virq].hwirq)
+
+struct uic *primary_uic;
+
+struct uic {
+ int index;
+ int dcrbase;
+
+ spinlock_t lock;
+
+ /* The remapper for this UIC */
+ struct irq_host *irqhost;
+
+ /* For secondary UICs, the cascade interrupt's irqaction */
+ struct irqaction cascade;
+
+ /* The device node of the interrupt controller */
+ struct device_node *of_node;
+};
+
+static void uic_unmask_irq(unsigned int virq)
+{
+ struct uic *uic = get_irq_chip_data(virq);
+ unsigned int src = uic_irq_to_hw(virq);
+ unsigned long flags;
+ u32 er;
+
+ spin_lock_irqsave(&uic->lock, flags);
+ er = mfdcr(uic->dcrbase + UIC_ER);
+ er |= 1 << (31 - src);
+ mtdcr(uic->dcrbase + UIC_ER, er);
+ spin_unlock_irqrestore(&uic->lock, flags);
+}
+
+static void uic_mask_irq(unsigned int virq)
+{
+ struct uic *uic = get_irq_chip_data(virq);
+ unsigned int src = uic_irq_to_hw(virq);
+ unsigned long flags;
+ u32 er;
+
+ spin_lock_irqsave(&uic->lock, flags);
+ er = mfdcr(uic->dcrbase + UIC_ER);
+ er &= ~(1 << (31 - src));
+ mtdcr(uic->dcrbase + UIC_ER, er);
+ spin_unlock_irqrestore(&uic->lock, flags);
+}
+
+static void uic_ack_irq(unsigned int virq)
+{
+ struct uic *uic = get_irq_chip_data(virq);
+ unsigned int src = uic_irq_to_hw(virq);
+ unsigned long flags;
+
+ spin_lock_irqsave(&uic->lock, flags);
+ mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
+ spin_unlock_irqrestore(&uic->lock, flags);
+}
+
+static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
+{
+ struct uic *uic = get_irq_chip_data(virq);
+ unsigned int src = uic_irq_to_hw(virq);
+ struct irq_desc *desc = get_irq_desc(virq);
+ unsigned long flags;
+ int trigger, polarity;
+ u32 tr, pr, mask;
+
+ switch (flow_type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_NONE:
+ uic_mask_irq(virq);
+ return 0;
+
+ case IRQ_TYPE_EDGE_RISING:
+ trigger = 1; polarity = 1;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ trigger = 1; polarity = 0;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ trigger = 0; polarity = 1;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ trigger = 0; polarity = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mask = ~(1 << (31 - src));
+
+ spin_lock_irqsave(&uic->lock, flags);
+ tr = mfdcr(uic->dcrbase + UIC_TR);
+ pr = mfdcr(uic->dcrbase + UIC_PR);
+ tr = (tr & mask) | (trigger << (31-src));
+ pr = (pr & mask) | (polarity << (31-src));
+
+ mtdcr(uic->dcrbase + UIC_PR, pr);
+ mtdcr(uic->dcrbase + UIC_TR, tr);
+
+ desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+ desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+ if (trigger)
+ desc->status |= IRQ_LEVEL;
+
+ spin_unlock_irqrestore(&uic->lock, flags);
+
+ return 0;
+}
+
+static struct irq_chip uic_irq_chip = {
+ .typename = " UIC ",
+ .unmask = uic_unmask_irq,
+ .mask = uic_mask_irq,
+/* .mask_ack = uic_mask_irq_and_ack, */
+ .ack = uic_ack_irq,
+ .set_type = uic_set_irq_type,
+};
+
+static int uic_host_match(struct irq_host *h, struct device_node *node)
+{
+ struct uic *uic = h->host_data;
+ return uic->of_node == node;
+}
+
+static int uic_host_map(struct irq_host *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct uic *uic = h->host_data;
+
+ set_irq_chip_data(virq, uic);
+ /* Despite the name, handle_level_irq() works for both level
+ * and edge irqs on UIC. FIXME: check this is correct */
+ set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
+
+ /* Set default irq type */
+ set_irq_type(virq, IRQ_TYPE_NONE);
+
+ return 0;
+}
+
+static int uic_host_xlate(struct irq_host *h, struct device_node *ct,
+ u32 *intspec, unsigned int intsize,
+ irq_hw_number_t *out_hwirq, unsigned int *out_type)
+
+{
+ /* UIC intspecs must have 2 cells */
+ BUG_ON(intsize != 2);
+ *out_hwirq = intspec[0];
+ *out_type = intspec[1];
+ return 0;
+}
+
+static struct irq_host_ops uic_host_ops = {
+ .match = uic_host_match,
+ .map = uic_host_map,
+ .xlate = uic_host_xlate,
+};
+
+irqreturn_t uic_cascade(int virq, void *data)
+{
+ struct uic *uic = data;
+ u32 msr;
+ int src;
+ int subvirq;
+
+ msr = mfdcr(uic->dcrbase + UIC_MSR);
+ src = 32 - ffs(msr);
+
+ subvirq = irq_linear_revmap(uic->irqhost, src);
+ generic_handle_irq(subvirq);
+
+ return IRQ_HANDLED;
+}
+
+static struct uic * __init uic_init_one(struct device_node *node)
+{
+ struct uic *uic;
+ const u32 *indexp, *dcrreg;
+ int len;
+
+ BUG_ON(! device_is_compatible(node, "ibm,uic"));
+
+ uic = alloc_bootmem(sizeof(*uic));
+ if (! uic)
+ return NULL; /* FIXME: panic? */
+
+ memset(uic, 0, sizeof(*uic));
+ spin_lock_init(&uic->lock);
+ uic->of_node = of_node_get(node);
+ indexp = of_get_property(node, "cell-index", &len);
+ if (!indexp || (len != sizeof(u32))) {
+ printk(KERN_ERR "uic: Device node %s has missing or invalid "
+ "cell-index property\n", node->full_name);
+ return NULL;
+ }
+ uic->index = *indexp;
+
+ dcrreg = of_get_property(node, "dcr-reg", &len);
+ if (!dcrreg || (len != 2*sizeof(u32))) {
+ printk(KERN_ERR "uic: Device node %s has missing or invalid "
+ "dcr-reg property\n", node->full_name);
+ return NULL;
+ }
+ uic->dcrbase = *dcrreg;
+
+ uic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_UIC_INTS,
+ &uic_host_ops, -1);
+ if (! uic->irqhost) {
+ of_node_put(node);
+ return NULL; /* FIXME: panic? */
+ }
+
+ uic->irqhost->host_data = uic;
+
+ /* Start with all interrupts disabled, level and non-critical */
+ mtdcr(uic->dcrbase + UIC_ER, 0);
+ mtdcr(uic->dcrbase + UIC_CR, 0);
+ mtdcr(uic->dcrbase + UIC_TR, 0);
+ /* Clear any pending interrupts, in case the firmware left some */
+ mtdcr(uic->dcrbase + UIC_SR, 0xffffffff);
+
+ printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index,
+ NR_UIC_INTS, uic->dcrbase);
+
+ return uic;
+}
+
+void __init uic_init_tree(void)
+{
+ struct device_node *np;
+ struct uic *uic;
+ const u32 *interrupts;
+
+ /* First locate and initialize the top-level UIC */
+
+ np = of_find_compatible_node(NULL, NULL, "ibm,uic");
+ while (np) {
+ interrupts = of_get_property(np, "interrupts", NULL);
+ if (! interrupts)
+ break;
+
+ np = of_find_compatible_node(np, NULL, "ibm,uic");
+ }
+
+ BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the
+ * top-level interrupt controller */
+ primary_uic = uic_init_one(np);
+ if (! primary_uic)
+ panic("Unable to initialize primary UIC %s\n", np->full_name);
+
+ irq_set_default_host(primary_uic->irqhost);
+ of_node_put(np);
+
+ /* The scan again for cascaded UICs */
+ np = of_find_compatible_node(NULL, NULL, "ibm,uic");
+ while (np) {
+ interrupts = of_get_property(np, "interrupts", NULL);
+ if (interrupts) {
+ /* Secondary UIC */
+ int cascade_virq;
+ int ret;
+
+ uic = uic_init_one(np);
+ if (! uic)
+ panic("Unable to initialize a secondary UIC %s\n",
+ np->full_name);
+
+ cascade_virq = irq_of_parse_and_map(np, 0);
+
+ uic->cascade.handler = uic_cascade;
+ uic->cascade.name = "UIC cascade";
+ uic->cascade.dev_id = uic;
+
+ ret = setup_irq(cascade_virq, &uic->cascade);
+ if (ret)
+ printk(KERN_ERR "Failed to setup_irq(%d) for "
+ "UIC%d cascade\n", cascade_virq,
+ uic->index);
+
+ /* FIXME: setup critical cascade?? */
+ }
+
+ np = of_find_compatible_node(np, NULL, "ibm,uic");
+ }
+}
+
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int uic_get_irq(void)
+{
+ u32 msr;
+ int src;
+
+ BUG_ON(! primary_uic);
+
+ msr = mfdcr(primary_uic->dcrbase + UIC_MSR);
+ src = 32 - ffs(msr);
+
+ return irq_linear_revmap(primary_uic->irqhost, src);
+}