aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev/mpc8xx_pic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/mpc8xx_pic.c')
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c105
1 files changed, 37 insertions, 68 deletions
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 8c27d261aba..c4828c0be5b 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -1,7 +1,5 @@
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/stddef.h>
-#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/irq.h>
@@ -18,88 +16,57 @@
extern int cpm_get_irq(struct pt_regs *regs);
-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];
+static struct irq_domain *mpc8xx_pic_host;
+static unsigned long mpc8xx_cached_irq_mask;
static sysconf8xx_t __iomem *siu_reg;
-int cpm_get_irq(struct pt_regs *regs);
-
-static void mpc8xx_unmask_irq(unsigned int virq)
+static inline unsigned long mpc8xx_irqd_to_bit(struct irq_data *d)
{
- int bit, word;
- unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
-
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
-
- ppc_cached_irq_mask[word] |= (1 << (31-bit));
- out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+ return 0x80000000 >> irqd_to_hwirq(d);
}
-static void mpc8xx_mask_irq(unsigned int virq)
+static void mpc8xx_unmask_irq(struct irq_data *d)
{
- int bit, word;
- unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
-
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
-
- ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
- out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+ mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
}
-static void mpc8xx_ack(unsigned int virq)
+static void mpc8xx_mask_irq(struct irq_data *d)
{
- int bit;
- unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
-
- bit = irq_nr & 0x1f;
- out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
+ mpc8xx_cached_irq_mask &= ~mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
}
-static void mpc8xx_end_irq(unsigned int virq)
+static void mpc8xx_ack(struct irq_data *d)
{
- int bit, word;
- unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
-
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
-
- ppc_cached_irq_mask[word] |= (1 << (31-bit));
- out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+ out_be32(&siu_reg->sc_sipend, mpc8xx_irqd_to_bit(d));
}
-static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
+static void mpc8xx_end_irq(struct irq_data *d)
{
- struct irq_desc *desc = irq_to_desc(virq);
-
- desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
- desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
- if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
- desc->status |= IRQ_LEVEL;
+ mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
+}
- if (flow_type & IRQ_TYPE_EDGE_FALLING) {
- irq_hw_number_t hw = (unsigned int)irq_map[virq].hwirq;
+static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
+{
+ /* only external IRQ senses are programmable */
+ if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !(irqd_to_hwirq(d) & 1)) {
unsigned int siel = in_be32(&siu_reg->sc_siel);
-
- /* only external IRQ senses are programmable */
- if ((hw & 1) == 0) {
- siel |= (0x80000000 >> hw);
- out_be32(&siu_reg->sc_siel, siel);
- desc->handle_irq = handle_edge_irq;
- }
+ siel |= mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_siel, siel);
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
}
return 0;
}
static struct irq_chip mpc8xx_pic = {
.name = "MPC8XX SIU",
- .unmask = mpc8xx_unmask_irq,
- .mask = mpc8xx_mask_irq,
- .ack = mpc8xx_ack,
- .eoi = mpc8xx_end_irq,
- .set_type = mpc8xx_set_irq_type,
+ .irq_unmask = mpc8xx_unmask_irq,
+ .irq_mask = mpc8xx_mask_irq,
+ .irq_ack = mpc8xx_ack,
+ .irq_eoi = mpc8xx_end_irq,
+ .irq_set_type = mpc8xx_set_irq_type,
};
unsigned int mpc8xx_get_irq(void)
@@ -118,18 +85,18 @@ unsigned int mpc8xx_get_irq(void)
}
-static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
+static int mpc8xx_pic_host_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)\n", virq, hw);
/* Set default irq handle */
- set_irq_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
+ irq_set_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
return 0;
}
-static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+static int mpc8xx_pic_host_xlate(struct irq_domain *h, struct device_node *ct,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_flags)
{
@@ -140,6 +107,9 @@ static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
IRQ_TYPE_EDGE_FALLING,
};
+ if (intspec[0] > 0x1f)
+ return 0;
+
*out_hwirq = intspec[0];
if (intsize > 1 && intspec[1] < 4)
*out_flags = map_pic_senses[intspec[1]];
@@ -150,7 +120,7 @@ static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
}
-static struct irq_host_ops mpc8xx_pic_host_ops = {
+static struct irq_domain_ops mpc8xx_pic_host_ops = {
.map = mpc8xx_pic_host_map,
.xlate = mpc8xx_pic_host_xlate,
};
@@ -173,14 +143,13 @@ int mpc8xx_pic_init(void)
if (ret)
goto out;
- siu_reg = ioremap(res.start, res.end - res.start + 1);
+ siu_reg = ioremap(res.start, resource_size(&res));
if (siu_reg == NULL) {
ret = -EINVAL;
goto out;
}
- mpc8xx_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
- 64, &mpc8xx_pic_host_ops, 64);
+ mpc8xx_pic_host = irq_domain_add_linear(np, 64, &mpc8xx_pic_host_ops, NULL);
if (mpc8xx_pic_host == NULL) {
printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
ret = -ENOMEM;