diff options
Diffstat (limited to 'arch/powerpc/sysdev/cpm2_pic.c')
| -rw-r--r-- | arch/powerpc/sysdev/cpm2_pic.c | 106 |
1 files changed, 42 insertions, 64 deletions
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 1709ac5aac7..a11bd1d433a 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -27,7 +27,6 @@ */ #include <linux/stddef.h> -#include <linux/init.h> #include <linux/sched.h> #include <linux/signal.h> #include <linux/irq.h> @@ -50,9 +49,8 @@ static intctl_cpm2_t __iomem *cpm2_intctl; -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]; +static struct irq_domain *cpm2_pic_host; +static unsigned long ppc_cached_irq_mask[2]; /* 2 32-bit registers */ static const u_char irq_to_siureg[] = { 1, 1, 1, 1, 1, 1, 1, 1, @@ -78,10 +76,10 @@ static const u_char irq_to_siubit[] = { 24, 25, 26, 27, 28, 29, 30, 31, }; -static void cpm2_mask_irq(unsigned int virq) +static void cpm2_mask_irq(struct irq_data *d) { int bit, word; - unsigned int irq_nr = virq_to_hw(virq); + unsigned int irq_nr = irqd_to_hwirq(d); bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; @@ -90,10 +88,10 @@ static void cpm2_mask_irq(unsigned int virq) out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]); } -static void cpm2_unmask_irq(unsigned int virq) +static void cpm2_unmask_irq(struct irq_data *d) { int bit, word; - unsigned int irq_nr = virq_to_hw(virq); + unsigned int irq_nr = irqd_to_hwirq(d); bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; @@ -102,10 +100,10 @@ static void cpm2_unmask_irq(unsigned int virq) out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]); } -static void cpm2_ack(unsigned int virq) +static void cpm2_ack(struct irq_data *d) { int bit, word; - unsigned int irq_nr = virq_to_hw(virq); + unsigned int irq_nr = irqd_to_hwirq(d); bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; @@ -113,34 +111,27 @@ static void cpm2_ack(unsigned int virq) out_be32(&cpm2_intctl->ic_sipnrh + word, 1 << bit); } -static void cpm2_end_irq(unsigned int virq) +static void cpm2_end_irq(struct irq_data *d) { - struct irq_desc *desc; int bit, word; - unsigned int irq_nr = virq_to_hw(virq); + unsigned int irq_nr = irqd_to_hwirq(d); - desc = irq_to_desc(irq_nr); - if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)) - && desc->action) { - - bit = irq_to_siubit[irq_nr]; - word = irq_to_siureg[irq_nr]; + bit = irq_to_siubit[irq_nr]; + word = irq_to_siureg[irq_nr]; - ppc_cached_irq_mask[word] |= 1 << bit; - out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]); + ppc_cached_irq_mask[word] |= 1 << bit; + out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]); - /* - * Work around large numbers of spurious IRQs on PowerPC 82xx - * systems. - */ - mb(); - } + /* + * Work around large numbers of spurious IRQs on PowerPC 82xx + * systems. + */ + mb(); } -static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) +static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type) { - unsigned int src = virq_to_hw(virq); - struct irq_desc *desc = irq_to_desc(virq); + unsigned int src = irqd_to_hwirq(d); unsigned int vold, vnew, edibit; /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or @@ -162,13 +153,11 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) goto err_sense; } - desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); - desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; - if (flow_type & IRQ_TYPE_LEVEL_LOW) { - desc->status |= IRQ_LEVEL; - desc->handle_irq = handle_level_irq; - } else - desc->handle_irq = handle_edge_irq; + irqd_set_trigger_type(d, flow_type); + if (flow_type & IRQ_TYPE_LEVEL_LOW) + __irq_set_handler_locked(d->irq, handle_level_irq); + else + __irq_set_handler_locked(d->irq, handle_edge_irq); /* internal IRQ senses are LEVEL_LOW * EXT IRQ and Port C IRQ senses are programmable @@ -179,7 +168,8 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) edibit = (31 - (CPM2_IRQ_PORTC0 - src)); else - return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; + return (flow_type & IRQ_TYPE_LEVEL_LOW) ? + IRQ_SET_MASK_OK_NOCOPY : -EINVAL; vold = in_be32(&cpm2_intctl->ic_siexr); @@ -190,7 +180,7 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) if (vold != vnew) out_be32(&cpm2_intctl->ic_siexr, vnew); - return 0; + return IRQ_SET_MASK_OK_NOCOPY; err_sense: pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type); @@ -198,12 +188,13 @@ err_sense: } static struct irq_chip cpm2_pic = { - .name = " CPM2 SIU ", - .mask = cpm2_mask_irq, - .unmask = cpm2_unmask_irq, - .ack = cpm2_ack, - .eoi = cpm2_end_irq, - .set_type = cpm2_set_irq_type, + .name = "CPM2 SIU", + .irq_mask = cpm2_mask_irq, + .irq_unmask = cpm2_unmask_irq, + .irq_ack = cpm2_ack, + .irq_eoi = cpm2_end_irq, + .irq_set_type = cpm2_set_irq_type, + .flags = IRQCHIP_EOI_IF_HANDLED, }; unsigned int cpm2_get_irq(void) @@ -221,31 +212,19 @@ unsigned int cpm2_get_irq(void) return irq_linear_revmap(cpm2_pic_host, irq); } -static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq, +static int cpm2_pic_host_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw); - irq_to_desc(virq)->status |= IRQ_LEVEL; - set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq); - return 0; -} - -static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct, - const u32 *intspec, unsigned int intsize, - irq_hw_number_t *out_hwirq, unsigned int *out_flags) -{ - *out_hwirq = intspec[0]; - if (intsize > 1) - *out_flags = intspec[1]; - else - *out_flags = IRQ_TYPE_NONE; + irq_set_status_flags(virq, IRQ_LEVEL); + irq_set_chip_and_handler(virq, &cpm2_pic, handle_level_irq); return 0; } -static struct irq_host_ops cpm2_pic_host_ops = { +static const struct irq_domain_ops cpm2_pic_host_ops = { .map = cpm2_pic_host_map, - .xlate = cpm2_pic_host_xlate, + .xlate = irq_domain_xlate_onetwocell, }; void cpm2_pic_init(struct device_node *node) @@ -282,8 +261,7 @@ void cpm2_pic_init(struct device_node *node) out_be32(&cpm2_intctl->ic_scprrl, 0x05309770); /* create a legacy host */ - cpm2_pic_host = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, - 64, &cpm2_pic_host_ops, 64); + cpm2_pic_host = irq_domain_add_linear(node, 64, &cpm2_pic_host_ops, NULL); if (cpm2_pic_host == NULL) { printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n"); return; |
