aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/commproc.c20
-rw-r--r--arch/powerpc/sysdev/cpm2_common.c2
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c4
-rw-r--r--arch/powerpc/sysdev/dcr.c4
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c13
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c4
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c4
-rw-r--r--arch/powerpc/sysdev/uic.c66
8 files changed, 94 insertions, 23 deletions
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index 4f67b89ba1d..e8e79f83d19 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -45,10 +45,10 @@
#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;
@@ -115,7 +115,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;
}
@@ -181,7 +181,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 +197,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 +307,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/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..e82d54de8a8 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
@@ -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_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 1cf29c9d440..f3abce11bea 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -321,21 +321,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;
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/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 90db8a720fe..cf0bfbd7340 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -193,8 +193,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)
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 89059895a20..47180b3fca5 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>
@@ -142,7 +143,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,6 +160,64 @@ static struct irq_chip uic_irq_chip = {
.set_type = uic_set_irq_type,
};
+/**
+ * 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)
+{
+ 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_match(struct irq_host *h, struct device_node *node)
{
struct uic *uic = h->host_data;
@@ -173,7 +232,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);
@@ -207,6 +266,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);