aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Makefile8
-rw-r--r--arch/powerpc/sysdev/commproc.c32
-rw-r--r--arch/powerpc/sysdev/cpm2_common.c2
-rw-r--r--arch/powerpc/sysdev/cpm2_pic.c11
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c4
-rw-r--r--arch/powerpc/sysdev/dcr.c6
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c2
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c127
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h7
-rw-r--r--arch/powerpc/sysdev/i8259.c8
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c4
-rw-r--r--arch/powerpc/sysdev/ipic.c7
-rw-r--r--arch/powerpc/sysdev/ipic.h3
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c23
-rw-r--r--arch/powerpc/sysdev/mpic.c53
-rw-r--r--arch/powerpc/sysdev/mpic.h1
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c13
-rw-r--r--arch/powerpc/sysdev/mpic_u3msi.c36
-rw-r--r--arch/powerpc/sysdev/mv64x60.h1
-rw-r--r--arch/powerpc/sysdev/mv64x60_pic.c12
-rw-r--r--arch/powerpc/sysdev/mv64x60_udbg.c152
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.c7
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.h3
-rw-r--r--arch/powerpc/sysdev/timer.c81
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c16
-rw-r--r--arch/powerpc/sysdev/uic.c75
26 files changed, 432 insertions, 262 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 08ce31e612c..b0ea8e9495e 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -16,15 +16,11 @@ obj-$(CONFIG_FSL_PCI) += fsl_pci.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
mv64x60-$(CONFIG_PCI) += mv64x60_pci.o
-obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o
+obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \
+ mv64x60_udbg.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o
obj-$(CONFIG_AXON_RAM) += axonram.o
-# contains only the suspend handler for time
-ifeq ($(CONFIG_RTC_CLASS),)
-obj-$(CONFIG_PM) += timer.o
-endif
-
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index dd5417aec1b..160a8b49bde 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -45,12 +45,11 @@
#define CPM_MAP_SIZE (0x4000)
static void m8xx_cpm_dpinit(void);
-static uint host_buffer; /* One page of host buffer */
-static uint host_end; /* end + 1 */
-cpm8xx_t *cpmp; /* Pointer to comm processor space */
-cpic8xx_t *cpic_reg;
+static uint host_buffer; /* One page of host buffer */
+static uint host_end; /* end + 1 */
+cpm8xx_t *cpmp; /* Pointer to comm processor space */
+cpic8xx_t *cpic_reg;
-static struct device_node *cpm_pic_node;
static struct irq_host *cpm_pic_host;
static void cpm_mask_irq(unsigned int irq)
@@ -95,11 +94,6 @@ int cpm_get_irq(void)
return irq_linear_revmap(cpm_pic_host, cpm_vec);
}
-static int cpm_pic_host_match(struct irq_host *h, struct device_node *node)
-{
- return cpm_pic_node == node;
-}
-
static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
@@ -115,7 +109,7 @@ static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
* and return. This is a no-op function so we don't need any special
* tests in the interrupt handler.
*/
-static irqreturn_t cpm_error_interrupt(int irq, void *dev)
+static irqreturn_t cpm_error_interrupt(int irq, void *dev)
{
return IRQ_HANDLED;
}
@@ -127,7 +121,6 @@ static struct irqaction cpm_error_irqaction = {
};
static struct irq_host_ops cpm_pic_host_ops = {
- .match = cpm_pic_host_match,
.map = cpm_pic_host_map,
};
@@ -165,9 +158,8 @@ unsigned int cpm_pic_init(void)
out_be32(&cpic_reg->cpic_cimr, 0);
- cpm_pic_node = of_node_get(np);
-
- cpm_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm_pic_host_ops, 64);
+ cpm_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
+ 64, &cpm_pic_host_ops, 64);
if (cpm_pic_host == NULL) {
printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
sirq = NO_IRQ;
@@ -181,7 +173,7 @@ unsigned int cpm_pic_init(void)
printk(KERN_ERR "CPM PIC init: can not find cpm node\n");
goto end;
}
- eirq= irq_of_parse_and_map(np, 0);
+ eirq = irq_of_parse_and_map(np, 0);
if (eirq == NO_IRQ)
goto end;
@@ -197,15 +189,15 @@ end:
void cpm_reset(void)
{
- cpm8xx_t *commproc;
- sysconf8xx_t *siu_conf;
+ cpm8xx_t *commproc;
+ sysconf8xx_t *siu_conf;
commproc = (cpm8xx_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
#ifdef CONFIG_UCODE_PATCH
/* Perform a reset.
*/
- out_be16(&commproc->cp_cpcr, CPM_CR_RST | CPM_CR_FLG);
+ out_be16(&commproc->cp_cpcr, CPM_CR_RST | CPM_CR_FLG);
/* Wait for it.
*/
@@ -307,7 +299,7 @@ static rh_block_t cpm_boot_dpmem_rh_block[16];
static rh_info_t cpm_dpmem_info;
#define CPM_DPMEM_ALIGNMENT 8
-static u8* dpram_vbase;
+static u8 *dpram_vbase;
static uint dpram_pbase;
void m8xx_cpm_dpinit(void)
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index c827715a509..3bf89b32476 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -201,7 +201,7 @@ int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
}
if (mode == CPM_CLK_RX)
- shift +=3;
+ shift += 3;
for (i=0; i<24; i++) {
if (clk_map[i][0] == target && clk_map[i][1] == clock) {
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index eabfe06fe05..d5b36e0ecbd 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -50,7 +50,6 @@
static intctl_cpm2_t *cpm2_intctl;
-static struct device_node *cpm2_pic_node;
static struct irq_host *cpm2_pic_host;
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
@@ -206,11 +205,6 @@ unsigned int cpm2_get_irq(void)
return irq_linear_revmap(cpm2_pic_host, irq);
}
-static int cpm2_pic_host_match(struct irq_host *h, struct device_node *node)
-{
- return cpm2_pic_node == node;
-}
-
static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
@@ -234,7 +228,6 @@ static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct,
}
static struct irq_host_ops cpm2_pic_host_ops = {
- .match = cpm2_pic_host_match,
.map = cpm2_pic_host_map,
.xlate = cpm2_pic_host_xlate,
};
@@ -273,8 +266,8 @@ void cpm2_pic_init(struct device_node *node)
out_be32(&cpm2_intctl->ic_scprrl, 0x05309770);
/* create a legacy host */
- cpm2_pic_node = of_node_get(node);
- cpm2_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm2_pic_host_ops, 64);
+ cpm2_pic_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+ 64, &cpm2_pic_host_ops, 64);
if (cpm2_pic_host == NULL) {
printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
return;
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index a1d2042bb30..e0e24b01e3a 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -204,7 +204,7 @@ static void dart_free(struct iommu_table *tbl, long index, long npages)
}
-static int dart_init(struct device_node *dart_node)
+static int __init dart_init(struct device_node *dart_node)
{
unsigned int i;
unsigned long tmp, base, size;
@@ -313,7 +313,7 @@ static void pci_dma_bus_setup_dart(struct pci_bus *bus)
PCI_DN(dn)->iommu_table = &iommu_table_dart;
}
-void iommu_init_early_dart(void)
+void __init iommu_init_early_dart(void)
{
struct device_node *dn;
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index 574b6ef44e0..ab11c0b2902 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -33,6 +33,7 @@ unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
return dr[index * 2];
}
+EXPORT_SYMBOL_GPL(dcr_resource_start);
unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
{
@@ -44,6 +45,7 @@ unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
return dr[index * 2 + 1];
}
+EXPORT_SYMBOL_GPL(dcr_resource_len);
#ifndef CONFIG_PPC_DCR_NATIVE
@@ -102,7 +104,7 @@ u64 of_translate_dcr_address(struct device_node *dev,
dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
unsigned int dcr_c)
{
- dcr_host_t ret = { .token = NULL, .stride = 0 };
+ dcr_host_t ret = { .token = NULL, .stride = 0, .base = dcr_n };
u64 addr;
pr_debug("dcr_map(%s, 0x%x, 0x%x)\n",
@@ -122,6 +124,7 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
ret.token -= dcr_n * ret.stride;
return ret;
}
+EXPORT_SYMBOL_GPL(dcr_map);
void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c)
{
@@ -133,5 +136,6 @@ void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c)
iounmap(h.token);
h.token = NULL;
}
+EXPORT_SYMBOL_GPL(dcr_unmap);
#endif /* !defined(CONFIG_PPC_DCR_NATIVE) */
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 114c90f8f56..34cad96e0de 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -255,5 +255,7 @@ DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533E, quirk_fsl_pcie_transpare
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8533, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544E, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8544, quirk_fsl_pcie_transparent);
+DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572E, quirk_fsl_pcie_transparent)
+DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8572, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_transparent);
DECLARE_PCI_FIXUP_EARLY(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_transparent);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 1cf29c9d440..d028e8da027 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
+#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
#include <linux/fs_uart_pd.h>
@@ -52,13 +53,13 @@ phys_addr_t get_immrbase(void)
soc = of_find_node_by_type(NULL, "soc");
if (soc) {
- unsigned int size;
+ int size;
const void *prop = of_get_property(soc, "reg", &size);
if (prop)
immrbase = of_translate_address(soc, prop);
of_node_put(soc);
- };
+ }
return immrbase;
}
@@ -76,16 +77,23 @@ u32 get_brgfreq(void)
if (brgfreq != -1)
return brgfreq;
- node = of_find_node_by_type(NULL, "cpm");
+ node = of_find_compatible_node(NULL, NULL, "fsl,cpm1");
+ if (!node)
+ node = of_find_compatible_node(NULL, NULL, "fsl,cpm2");
+ if (!node)
+ node = of_find_node_by_type(NULL, "cpm");
if (node) {
- unsigned int size;
- const unsigned int *prop = of_get_property(node,
- "brg-frequency", &size);
+ int size;
+ const unsigned int *prop;
- if (prop)
+ prop = of_get_property(node, "fsl,brg-frequency", &size);
+ if (!prop)
+ prop = of_get_property(node, "brg-frequency", &size);
+ if (prop && size == 4)
brgfreq = *prop;
+
of_node_put(node);
- };
+ }
return brgfreq;
}
@@ -103,14 +111,14 @@ u32 get_baudrate(void)
node = of_find_node_by_type(NULL, "serial");
if (node) {
- unsigned int size;
+ int size;
const unsigned int *prop = of_get_property(node,
"current-speed", &size);
if (prop)
fs_baudrate = *prop;
of_node_put(node);
- };
+ }
return fs_baudrate;
}
@@ -321,21 +329,26 @@ static struct i2c_driver_device i2c_devices[] __initdata = {
{"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
};
-static int __init of_find_i2c_driver(struct device_node *node, struct i2c_board_info *info)
+static int __init of_find_i2c_driver(struct device_node *node,
+ struct i2c_board_info *info)
{
int i;
for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
if (!of_device_is_compatible(node, i2c_devices[i].of_device))
continue;
- strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN);
- strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE);
+ if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
+ KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
+ strlcpy(info->type, i2c_devices[i].i2c_type,
+ I2C_NAME_SIZE) >= I2C_NAME_SIZE)
+ return -ENOMEM;
return 0;
}
return -ENODEV;
}
-static void __init of_register_i2c_devices(struct device_node *adap_node, int bus_num)
+static void __init of_register_i2c_devices(struct device_node *adap_node,
+ int bus_num)
{
struct device_node *node = NULL;
@@ -1187,3 +1200,89 @@ err:
arch_initcall(cpm_smc_uart_of_init);
#endif /* CONFIG_8xx */
+
+int __init fsl_spi_init(struct spi_board_info *board_infos,
+ unsigned int num_board_infos,
+ void (*activate_cs)(u8 cs, u8 polarity),
+ void (*deactivate_cs)(u8 cs, u8 polarity))
+{
+ struct device_node *np;
+ unsigned int i;
+ const u32 *sysclk;
+
+ np = of_find_node_by_type(NULL, "qe");
+ if (!np)
+ return -ENODEV;
+
+ sysclk = of_get_property(np, "bus-frequency", NULL);
+ if (!sysclk)
+ return -ENODEV;
+
+ for (np = NULL, i = 1;
+ (np = of_find_compatible_node(np, "spi", "fsl_spi")) != NULL;
+ i++) {
+ int ret = 0;
+ unsigned int j;
+ const void *prop;
+ struct resource res[2];
+ struct platform_device *pdev;
+ struct fsl_spi_platform_data pdata = {
+ .activate_cs = activate_cs,
+ .deactivate_cs = deactivate_cs,
+ };
+
+ memset(res, 0, sizeof(res));
+
+ pdata.sysclk = *sysclk;
+
+ prop = of_get_property(np, "reg", NULL);
+ if (!prop)
+ goto err;
+ pdata.bus_num = *(u32 *)prop;
+
+ prop = of_get_property(np, "mode", NULL);
+ if (prop && !strcmp(prop, "cpu-qe"))
+ pdata.qe_mode = 1;
+
+ for (j = 0; j < num_board_infos; j++) {
+ if (board_infos[j].bus_num == pdata.bus_num)
+ pdata.max_chipselect++;
+ }
+
+ if (!pdata.max_chipselect)
+ goto err;
+
+ ret = of_address_to_resource(np, 0, &res[0]);
+ if (ret)
+ goto err;
+
+ ret = of_irq_to_resource(np, 0, &res[1]);
+ if (ret == NO_IRQ)
+ goto err;
+
+ pdev = platform_device_alloc("mpc83xx_spi", i);
+ if (!pdev)
+ goto err;
+
+ ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (ret)
+ goto unreg;
+
+ ret = platform_device_add_resources(pdev, res,
+ ARRAY_SIZE(res));
+ if (ret)
+ goto unreg;
+
+ ret = platform_device_register(pdev);
+ if (ret)
+ goto unreg;
+
+ continue;
+unreg:
+ platform_device_del(pdev);
+err:
+ continue;
+ }
+
+ return spi_register_board_info(board_infos, num_board_infos);
+}
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 04e145b5fc3..618d91d1e10 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -8,5 +8,12 @@ extern phys_addr_t get_immrbase(void);
extern u32 get_brgfreq(void);
extern u32 get_baudrate(void);
+struct spi_board_info;
+
+extern int fsl_spi_init(struct spi_board_info *board_infos,
+ unsigned int num_board_infos,
+ void (*activate_cs)(u8 cs, u8 polarity),
+ void (*deactivate_cs)(u8 cs, u8 polarity));
+
#endif
#endif
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index ad87adc975b..7c1b27ac7d3 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -25,7 +25,6 @@ static unsigned char cached_8259[2] = { 0xff, 0xff };
static DEFINE_SPINLOCK(i8259_lock);
-static struct device_node *i8259_node;
static struct irq_host *i8259_host;
/*
@@ -165,7 +164,7 @@ static struct resource pic_edgectrl_iores = {
static int i8259_host_match(struct irq_host *h, struct device_node *node)
{
- return i8259_node == NULL || i8259_node == node;
+ return h->of_node == NULL || h->of_node == node;
}
static int i8259_host_map(struct irq_host *h, unsigned int virq,
@@ -276,9 +275,8 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
spin_unlock_irqrestore(&i8259_lock, flags);
/* create a legacy host */
- if (node)
- i8259_node = of_node_get(node);
- i8259_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &i8259_host_ops, 0);
+ i8259_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LEGACY,
+ 0, &i8259_host_ops, 0);
if (i8259_host == NULL) {
printk(KERN_ERR "i8259: failed to allocate irq host !\n");
return;
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index 5294560c7b0..b5d068204aa 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -144,8 +144,8 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
static struct pci_ops indirect_pci_ops =
{
- indirect_read_config,
- indirect_write_config
+ .read = indirect_read_config,
+ .write = indirect_write_config,
};
void __init
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 473c415e9e2..05a56e55804 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -511,10 +511,8 @@ static struct irq_chip ipic_irq_chip = {
static int ipic_host_match(struct irq_host *h, struct device_node *node)
{
- struct ipic *ipic = h->host_data;
-
/* Exact match, unless ipic node is NULL */
- return ipic->of_node == NULL || ipic->of_node == node;
+ return h->of_node == NULL || h->of_node == node;
}
static int ipic_host_map(struct irq_host *h, unsigned int virq,
@@ -568,9 +566,8 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
return NULL;
memset(ipic, 0, sizeof(struct ipic));
- ipic->of_node = of_node_get(node);
- ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+ ipic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
NR_IPIC_INTS,
&ipic_host_ops, 0);
if (ipic->irqhost == NULL) {
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index c28e589877e..bb309a501b2 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -48,9 +48,6 @@ struct ipic {
/* The "linux" controller struct */
struct irq_chip hc_irq;
-
- /* The device node of the interrupt controller */
- struct device_node *of_node;
};
struct ipic_info {
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 2fc2bcd79b5..565156ae65b 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -19,7 +19,6 @@
extern int cpm_get_irq(struct pt_regs *regs);
-static struct device_node *mpc8xx_pic_node;
static struct irq_host *mpc8xx_pic_host;
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
@@ -120,11 +119,6 @@ unsigned int mpc8xx_get_irq(void)
}
-static int mpc8xx_pic_host_match(struct irq_host *h, struct device_node *node)
-{
- return mpc8xx_pic_node == node;
-}
-
static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
@@ -158,7 +152,6 @@ static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
static struct irq_host_ops mpc8xx_pic_host_ops = {
- .match = mpc8xx_pic_host_match,
.map = mpc8xx_pic_host_map,
.xlate = mpc8xx_pic_host_xlate,
};
@@ -176,22 +169,24 @@ int mpc8xx_pic_init(void)
return -ENOMEM;
}
- mpc8xx_pic_node = of_node_get(np);
-
ret = of_address_to_resource(np, 0, &res);
- of_node_put(np);
if (ret)
- return ret;
+ goto out;
siu_reg = (void *)ioremap(res.start, res.end - res.start + 1);
- if (siu_reg == NULL)
- return -EINVAL;
+ if (siu_reg == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
- mpc8xx_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &mpc8xx_pic_host_ops, 64);
+ mpc8xx_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
+ 64, &mpc8xx_pic_host_ops, 64);
if (mpc8xx_pic_host == NULL) {
printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
ret = -ENOMEM;
}
+out:
+ of_node_put(np);
return ret;
}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 74c64c0d3b7..893e65439e8 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -156,8 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_read(rb->dhost,
- rb->dbase + reg + rb->doff);
+ return dcr_read(rb->dhost, rb->dhost.base + reg);
#endif
case mpic_access_mmio_be:
return in_be32(rb->base + (reg >> 2));
@@ -174,8 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_write(rb->dhost,
- rb->dbase + reg + rb->doff, value);
+ return dcr_write(rb->dhost, rb->dhost.base + reg, value);
#endif
case mpic_access_mmio_be:
return out_be32(rb->base + (reg >> 2), value);
@@ -228,8 +226,13 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne
unsigned int isu = src_no >> mpic->isu_shift;
unsigned int idx = src_no & mpic->isu_mask;
- return _mpic_read(mpic->reg_type, &mpic->isus[isu],
- reg + (idx * MPIC_INFO(IRQ_STRIDE)));
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ if (reg == 0)
+ return mpic->isu_reg0_shadow[idx];
+ else
+#endif
+ return _mpic_read(mpic->reg_type, &mpic->isus[isu],
+ reg + (idx * MPIC_INFO(IRQ_STRIDE)));
}
static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
@@ -240,6 +243,11 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
_mpic_write(mpic->reg_type, &mpic->isus[isu],
reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
+
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ if (reg == 0)
+ mpic->isu_reg0_shadow[idx] = value;
+#endif
}
#define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r))
@@ -269,9 +277,11 @@ static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr,
static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
unsigned int offset, unsigned int size)
{
- rb->dbase = mpic->dcr_base;
- rb->doff = offset;
- rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size);
+ const u32 *dbasep;
+
+ dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL);
+
+ rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size);
BUG_ON(!DCR_MAP_OK(rb->dhost));
}
@@ -758,7 +768,7 @@ static void mpic_end_ipi(unsigned int irq)
#endif /* CONFIG_SMP */
-static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
{
struct mpic *mpic = mpic_from_irq(irq);
unsigned int src = mpic_irq_to_hw(irq);
@@ -861,10 +871,8 @@ static struct irq_chip mpic_irq_ht_chip = {
static int mpic_host_match(struct irq_host *h, struct device_node *node)
{
- struct mpic *mpic = h->host_data;
-
/* Exact match, unless mpic node is NULL */
- return mpic->of_node == NULL || mpic->of_node == node;
+ return h->of_node == NULL || h->of_node == node;
}
static int mpic_host_map(struct irq_host *h, unsigned int virq,
@@ -985,10 +993,9 @@ struct mpic * __init mpic_alloc(struct device_node *node,
memset(mpic, 0, sizeof(struct mpic));
mpic->name = name;
- mpic->of_node = of_node_get(node);
- mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, isu_size,
- &mpic_host_ops,
+ mpic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+ isu_size, &mpic_host_ops,
flags & MPIC_LARGE_VECTORS ? 2048 : 256);
if (mpic->irqhost == NULL) {
of_node_put(node);
@@ -1068,20 +1075,14 @@ 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 && of_get_property(node, "dcr-reg", NULL) != NULL)
- mpic->flags |= MPIC_USES_DCR;
-
+ if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) {
#ifdef CONFIG_PPC_DCR
- if (mpic->flags & MPIC_USES_DCR) {
- const u32 *dbasep;
- dbasep = of_get_property(node, "dcr-reg", NULL);
- BUG_ON(dbasep == NULL);
- mpic->dcr_base = *dbasep;
+ mpic->flags |= MPIC_USES_DCR;
mpic->reg_type = mpic_access_dcr;
- }
#else
- BUG_ON (mpic->flags & MPIC_USES_DCR);
+ BUG();
#endif /* CONFIG_PPC_DCR */
+ }
/* If the MPIC is not DCR based, and no physical address was passed
* in, try to obtain one
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 3a1c3d2c594..1cb6bd84102 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -34,5 +34,6 @@ 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);
+extern void mpic_set_affinity(unsigned int irq, cpumask_t cpumask);
#endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index b076793033c..d272a52ecd2 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -9,7 +9,6 @@
*/
#include <linux/irq.h>
-#include <linux/bootmem.h>
#include <linux/bitmap.h>
#include <linux/msi.h>
#include <asm/mpic.h>
@@ -117,16 +116,17 @@ 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);
+ p = of_get_property(mpic->irqhost->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);
+ mpic->irqhost->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);
+ "property on %s\n", mpic->irqhost->of_node->full_name);
return -EINVAL;
}
@@ -151,10 +151,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
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);
+ mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);
if (!mpic->hwirq_bitmap) {
pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
index 305b864c25d..1d5a40899b7 100644
--- a/arch/powerpc/sysdev/mpic_u3msi.c
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -40,6 +40,7 @@ static struct irq_chip mpic_u3msi_chip = {
.unmask = mpic_u3msi_unmask_irq,
.eoi = mpic_end_irq,
.set_type = mpic_set_irq_type,
+ .set_affinity = mpic_set_affinity,
.typename = "MPIC-U3MSI",
};
@@ -107,59 +108,46 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
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;
+ u64 addr;
+
+ addr = find_ht_magic_addr(pdev);
+ msg.address_lo = addr & 0xFFFFFFFF;
+ msg.address_hi = addr >> 32;
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;
+ return hwirq;
}
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;
+ return -ENOSPC;
}
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);
+ pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) addr 0x%lx\n",
+ virq, hwirq, addr);
+
+ msg.data = hwirq;
write_msi_msg(virq, &msg);
hwirq++;
}
return 0;
-
- out_free:
- u3msi_teardown_msi_irqs(pdev);
- return rc;
}
int mpic_u3msi_init(struct mpic *mpic)
diff --git a/arch/powerpc/sysdev/mv64x60.h b/arch/powerpc/sysdev/mv64x60.h
index 2ff0b4ef268..4f618fa465c 100644
--- a/arch/powerpc/sysdev/mv64x60.h
+++ b/arch/powerpc/sysdev/mv64x60.h
@@ -7,5 +7,6 @@ extern void __init mv64x60_init_irq(void);
extern unsigned int mv64x60_get_irq(void);
extern void __init mv64x60_pci_init(void);
+extern void __init mv64x60_init_early(void);
#endif /* __MV64X60_H__ */
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
index 01d31628777..19e6ef26379 100644
--- a/arch/powerpc/sysdev/mv64x60_pic.c
+++ b/arch/powerpc/sysdev/mv64x60_pic.c
@@ -202,11 +202,6 @@ static struct irq_chip mv64x60_chip_gpp = {
* mv64x60_host_ops functions
*/
-static int mv64x60_host_match(struct irq_host *h, struct device_node *np)
-{
- return mv64x60_irq_host->host_data == np;
-}
-
static struct irq_chip *mv64x60_chips[] = {
[MV64x60_LEVEL1_LOW] = &mv64x60_chip_low,
[MV64x60_LEVEL1_HIGH] = &mv64x60_chip_high,
@@ -228,7 +223,6 @@ static int mv64x60_host_map(struct irq_host *h, unsigned int virq,
}
static struct irq_host_ops mv64x60_host_ops = {
- .match = mv64x60_host_match,
.map = mv64x60_host_map,
};
@@ -253,14 +247,12 @@ void __init mv64x60_init_irq(void)
np = of_find_compatible_node(NULL, NULL, "marvell,mv64x60-pic");
reg = of_get_property(np, "reg", &size);
paddr = of_translate_address(np, reg);
- of_node_put(np);
mv64x60_irq_reg_base = ioremap(paddr, reg[1]);
- mv64x60_irq_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, MV64x60_NUM_IRQS,
+ mv64x60_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
+ MV64x60_NUM_IRQS,
&mv64x60_host_ops, MV64x60_NUM_IRQS);
- mv64x60_irq_host->host_data = np;
-
spin_lock_irqsave(&mv64x60_lock, flags);
out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK,
mv64x60_cached_gpp_mask);
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
new file mode 100644
index 00000000000..367e7b13ec0
--- /dev/null
+++ b/arch/powerpc/sysdev/mv64x60_udbg.c
@@ -0,0 +1,152 @@
+/*
+ * udbg serial input/output routines for the Marvell MV64x60 (Discovery).
+ *
+ * Author: Dale Farnsworth <dale@farnsworth.org>
+ *
+ * 2007 (c) 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 <asm/io.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+
+#include <sysdev/mv64x60.h>
+
+#define MPSC_0_CR1_OFFSET 0x000c
+
+#define MPSC_0_CR2_OFFSET 0x0010
+#define MPSC_CHR_2_TCS (1 << 9)
+
+#define MPSC_0_CHR_10_OFFSET 0x0030
+
+#define MPSC_INTR_CAUSE_OFF_0 0x0004
+#define MPSC_INTR_CAUSE_OFF_1 0x000c
+#define MPSC_INTR_CAUSE_RCC (1<<6)
+
+static void __iomem *mpsc_base;
+static void __iomem *mpsc_intr_cause;
+
+static void mv64x60_udbg_putc(char c)
+{
+ if (c == '\n')
+ mv64x60_udbg_putc('\r');
+
+ while(in_le32(mpsc_base + MPSC_0_CR2_OFFSET) & MPSC_CHR_2_TCS)
+ ;
+ out_le32(mpsc_base + MPSC_0_CR1_OFFSET, c);
+ out_le32(mpsc_base + MPSC_0_CR2_OFFSET, MPSC_CHR_2_TCS);
+}
+
+static int mv64x60_udbg_testc(void)
+{
+ return (in_le32(mpsc_intr_cause) & MPSC_INTR_CAUSE_RCC) != 0;
+}
+
+static int mv64x60_udbg_getc(void)
+{
+ int cause = 0;
+ int c;
+
+ while (!mv64x60_udbg_testc())
+ ;
+
+ c = in_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2);
+ out_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2, c);
+ out_le32(mpsc_intr_cause, cause & ~MPSC_INTR_CAUSE_RCC);
+ return c;
+}
+
+static int mv64x60_udbg_getc_poll(void)
+{
+ if (!mv64x60_udbg_testc())
+ return -1;
+
+ return mv64x60_udbg_getc();
+}
+
+static void mv64x60_udbg_init(void)
+{
+ struct device_node *np, *mpscintr, *stdout = NULL;
+ const char *path;
+ const phandle *ph;
+ struct resource r[2];
+ const int *block_index;
+ int intr_cause_offset;
+ int err;
+
+ path = of_get_property(of_chosen, "linux,stdout-path", NULL);
+ if (!path)
+ return;
+
+ stdout = of_find_node_by_path(path);
+ if (!stdout)
+ return;
+
+ for (np = NULL;
+ (np = of_find_compatible_node(np, "serial", "marvell,mpsc")); )
+ if (np == stdout)
+ break;
+
+ of_node_put(stdout);
+ if (!np)
+ return;
+
+ block_index = of_get_property(np, "block-index", NULL);
+ if (!block_index)
+ goto error;
+
+ switch (*block_index) {
+ case 0:
+ intr_cause_offset = MPSC_INTR_CAUSE_OFF_0;
+ break;
+ case 1:
+ intr_cause_offset = MPSC_INTR_CAUSE_OFF_1;
+ break;
+ default:
+ goto error;
+ }
+
+ err = of_address_to_resource(np, 0, &r[0]);
+ if (err)
+ goto error;
+
+ ph = of_get_property(np, "mpscintr", NULL);
+ mpscintr = of_find_node_by_phandle(*ph);
+ if (!mpscintr)
+ goto error;
+
+ err = of_address_to_resource(mpscintr, 0, &r[1]);
+ of_node_put(mpscintr);
+ if (err)
+ goto error;
+
+ of_node_put(np);
+
+ mpsc_base = ioremap(r[0].start, r[0].end - r[0].start + 1);
+ if (!mpsc_base)
+ return;
+
+ mpsc_intr_cause = ioremap(r[1].start, r[1].end - r[1].start + 1);
+ if (!mpsc_intr_cause) {
+ iounmap(mpsc_base);
+ return;
+ }
+ mpsc_intr_cause += intr_cause_offset;
+
+ udbg_putc = mv64x60_udbg_putc;
+ udbg_getc = mv64x60_udbg_getc;
+ udbg_getc_poll = mv64x60_udbg_getc_poll;
+
+ return;
+
+error:
+ of_node_put(np);
+}
+
+void mv64x60_init_early(void)
+{
+ mv64x60_udbg_init();
+}
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 4d1dcb45963..55e6f394af8 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -245,10 +245,8 @@ static struct irq_chip qe_ic_irq_chip = {
static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
{
- struct qe_ic *qe_ic = h->host_data;
-
/* Exact match, unless qe_ic node is NULL */
- return qe_ic->of_node == NULL || qe_ic->of_node == node;
+ return h->of_node == NULL || h->of_node == node;
}
static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
@@ -352,9 +350,8 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags)
return;
memset(qe_ic, 0, sizeof(struct qe_ic));
- qe_ic->of_node = of_node_get(node);
- qe_ic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+ qe_ic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
NR_QE_IC_INTS, &qe_ic_host_ops, 0);
if (qe_ic->irqhost == NULL) {
of_node_put(node);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.h b/arch/powerpc/sysdev/qe_lib/qe_ic.h
index 9a631adb189..c1361d005a8 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.h
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.h
@@ -84,9 +84,6 @@ struct qe_ic {
/* The "linux" controller struct */
struct irq_chip hc_irq;
- /* The device node of the interrupt controller */
- struct device_node *of_node;
-
/* VIRQ numbers of QE high/low irqs */
unsigned int virq_high;
unsigned int virq_low;
diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c
deleted file mode 100644
index e81e7ec2e79..00000000000
--- a/arch/powerpc/sysdev/timer.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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);
- cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900,
- cur_rtc_tm.tm_mon + 1,
- cur_rtc_tm.tm_mday,
- cur_rtc_tm.tm_hour,
- cur_rtc_tm.tm_min,
- cur_rtc_tm.tm_sec);
-
- 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);
- suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900,
- suspend_rtc_tm.tm_mon + 1,
- suspend_rtc_tm.tm_mday,
- suspend_rtc_tm.tm_hour,
- suspend_rtc_tm.tm_min,
- suspend_rtc_tm.tm_sec);
-
- 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_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 90db8a720fe..31d3d33d91f 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -52,7 +52,6 @@
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;
extern u32 get_vir_csrbase(void);
@@ -193,8 +192,8 @@ void tsi108_clear_pci_cfg_error(void)
}
static struct pci_ops tsi108_direct_pci_ops = {
- tsi108_direct_read_config,
- tsi108_direct_write_config
+ .read = tsi108_direct_read_config,
+ .write = tsi108_direct_write_config,
};
int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
@@ -405,13 +404,7 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,
return 0;
}
-static int pci_irq_host_match(struct irq_host *h, struct device_node *node)
-{
- return pci_irq_node == node;
-}
-
static struct irq_host_ops pci_irq_host_ops = {
- .match = pci_irq_host_match,
.map = pci_irq_host_map,
.xlate = pci_irq_host_xlate,
};
@@ -433,10 +426,11 @@ void __init tsi108_pci_int_init(struct device_node *node)
{
DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
- pci_irq_node = of_node_get(node);
- pci_irq_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &pci_irq_host_ops, 0);
+ pci_irq_host = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LEGACY,
+ 0, &pci_irq_host_ops, 0);
if (pci_irq_host == NULL) {
printk(KERN_ERR "pci_irq_host: failed to allocate irq host !\n");
+ of_node_put(node);
return;
}
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 89059895a20..5149716c734 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -55,9 +56,6 @@ struct uic {
/* 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)
@@ -142,7 +140,7 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
- if (trigger)
+ if (!trigger)
desc->status |= IRQ_LEVEL;
spin_unlock_irqrestore(&uic->lock, flags);
@@ -159,10 +157,62 @@ static struct irq_chip uic_irq_chip = {
.set_type = uic_set_irq_type,
};
-static int uic_host_match(struct irq_host *h, struct device_node *node)
+/**
+ * handle_uic_irq - irq flow handler for UIC
+ * @irq: the interrupt number
+ * @desc: the interrupt description structure for this irq
+ *
+ * This is modified version of the generic handle_level_irq() suitable
+ * for the UIC. On the UIC, acking (i.e. clearing the SR bit) a level
+ * irq will have no effect if the interrupt is still asserted by the
+ * device, even if the interrupt is already masked. Therefore, unlike
+ * the standard handle_level_irq(), we must ack the interrupt *after*
+ * invoking the ISR (which should have de-asserted the interrupt in
+ * the external source). For edge interrupts we ack at the beginning
+ * instead of the end, to keep the window in which we can miss an
+ * interrupt as small as possible.
+ */
+void fastcall handle_uic_irq(unsigned int irq, struct irq_desc *desc)
{
- struct uic *uic = h->host_data;
- return uic->of_node == node;
+ unsigned int cpu = smp_processor_id();
+ struct irqaction *action;
+ irqreturn_t action_ret;
+
+ spin_lock(&desc->lock);
+ if (desc->status & IRQ_LEVEL)
+ desc->chip->mask(irq);
+ else
+ desc->chip->mask_ack(irq);
+
+ if (unlikely(desc->status & IRQ_INPROGRESS))
+ goto out_unlock;
+ desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+ kstat_cpu(cpu).irqs[irq]++;
+
+ /*
+ * If its disabled or no action available
+ * keep it masked and get out of here
+ */
+ action = desc->action;
+ if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+ desc->status |= IRQ_PENDING;
+ goto out_unlock;
+ }
+
+ desc->status |= IRQ_INPROGRESS;
+ desc->status &= ~IRQ_PENDING;
+ spin_unlock(&desc->lock);
+
+ action_ret = handle_IRQ_event(irq, action);
+
+ spin_lock(&desc->lock);
+ desc->status &= ~IRQ_INPROGRESS;
+ if (desc->status & IRQ_LEVEL)
+ desc->chip->ack(irq);
+ if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+ desc->chip->unmask(irq);
+out_unlock:
+ spin_unlock(&desc->lock);
}
static int uic_host_map(struct irq_host *h, unsigned int virq,
@@ -173,7 +223,7 @@ static int uic_host_map(struct irq_host *h, unsigned int virq,
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_irq_chip_and_handler(virq, &uic_irq_chip, handle_uic_irq);
/* Set default irq type */
set_irq_type(virq, IRQ_TYPE_NONE);
@@ -194,7 +244,6 @@ static int uic_host_xlate(struct irq_host *h, struct device_node *ct,
}
static struct irq_host_ops uic_host_ops = {
- .match = uic_host_match,
.map = uic_host_map,
.xlate = uic_host_xlate,
};
@@ -207,6 +256,9 @@ irqreturn_t uic_cascade(int virq, void *data)
int subvirq;
msr = mfdcr(uic->dcrbase + UIC_MSR);
+ if (!msr) /* spurious interrupt */
+ return IRQ_HANDLED;
+
src = 32 - ffs(msr);
subvirq = irq_linear_revmap(uic->irqhost, src);
@@ -229,7 +281,6 @@ static struct uic * __init uic_init_one(struct device_node *node)
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 "
@@ -246,8 +297,8 @@ static struct uic * __init uic_init_one(struct device_node *node)
}
uic->dcrbase = *dcrreg;
- uic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_UIC_INTS,
- &uic_host_ops, -1);
+ uic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+ NR_UIC_INTS, &uic_host_ops, -1);
if (! uic->irqhost) {
of_node_put(node);
return NULL; /* FIXME: panic? */