That looks pretty much like a VIC. Wants to be revisited. Signed-off-by: Thomas Gleixner --- arch/arm/mach-msm/irq.c | 157 +++++++++++++++++------------------------------- 1 file changed, 56 insertions(+), 101 deletions(-) Index: linux-2.6/arch/arm/mach-msm/irq.c =================================================================== --- linux-2.6.orig/arch/arm/mach-msm/irq.c +++ linux-2.6/arch/arm/mach-msm/irq.c @@ -12,140 +12,95 @@ * GNU General Public License for more details. * */ - -#include -#include -#include #include -#include -#include #include #include #include - #include -#define VIC_REG(off) (MSM_VIC_BASE + (off)) - -#define VIC_INT_SELECT0 VIC_REG(0x0000) /* 1: FIQ, 0: IRQ */ -#define VIC_INT_SELECT1 VIC_REG(0x0004) /* 1: FIQ, 0: IRQ */ -#define VIC_INT_EN0 VIC_REG(0x0010) -#define VIC_INT_EN1 VIC_REG(0x0014) -#define VIC_INT_ENCLEAR0 VIC_REG(0x0020) -#define VIC_INT_ENCLEAR1 VIC_REG(0x0024) -#define VIC_INT_ENSET0 VIC_REG(0x0030) -#define VIC_INT_ENSET1 VIC_REG(0x0034) -#define VIC_INT_TYPE0 VIC_REG(0x0040) /* 1: EDGE, 0: LEVEL */ -#define VIC_INT_TYPE1 VIC_REG(0x0044) /* 1: EDGE, 0: LEVEL */ -#define VIC_INT_POLARITY0 VIC_REG(0x0050) /* 1: NEG, 0: POS */ -#define VIC_INT_POLARITY1 VIC_REG(0x0054) /* 1: NEG, 0: POS */ -#define VIC_NO_PEND_VAL VIC_REG(0x0060) -#define VIC_INT_MASTEREN VIC_REG(0x0064) /* 1: IRQ, 2: FIQ */ -#define VIC_PROTECTION VIC_REG(0x006C) /* 1: ENABLE */ -#define VIC_CONFIG VIC_REG(0x0068) /* 1: USE ARM1136 VIC */ -#define VIC_IRQ_STATUS0 VIC_REG(0x0080) -#define VIC_IRQ_STATUS1 VIC_REG(0x0084) -#define VIC_FIQ_STATUS0 VIC_REG(0x0090) -#define VIC_FIQ_STATUS1 VIC_REG(0x0094) -#define VIC_RAW_STATUS0 VIC_REG(0x00A0) -#define VIC_RAW_STATUS1 VIC_REG(0x00A4) -#define VIC_INT_CLEAR0 VIC_REG(0x00B0) -#define VIC_INT_CLEAR1 VIC_REG(0x00B4) -#define VIC_SOFTINT0 VIC_REG(0x00C0) -#define VIC_SOFTINT1 VIC_REG(0x00C4) -#define VIC_IRQ_VEC_RD VIC_REG(0x00D0) /* pending int # */ -#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4) /* pending vector addr */ -#define VIC_IRQ_VEC_WR VIC_REG(0x00D8) -#define VIC_IRQ_IN_SERVICE VIC_REG(0x00E0) -#define VIC_IRQ_IN_STACK VIC_REG(0x00E4) -#define VIC_TEST_BUS_SEL VIC_REG(0x00E8) - -#define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4)) -#define VIC_VECTADDR(n) VIC_REG(0x0400+((n) * 4)) - -static void msm_irq_ack(struct irq_data *d) -{ - void __iomem *reg = VIC_INT_CLEAR0 + ((d->irq & 32) ? 4 : 0); - writel(1 << (d->irq & 31), reg); -} - -static void msm_irq_mask(struct irq_data *d) -{ - void __iomem *reg = VIC_INT_ENCLEAR0 + ((d->irq & 32) ? 4 : 0); - writel(1 << (d->irq & 31), reg); -} - -static void msm_irq_unmask(struct irq_data *d) -{ - void __iomem *reg = VIC_INT_ENSET0 + ((d->irq & 32) ? 4 : 0); - writel(1 << (d->irq & 31), reg); -} +#define VIC_REG_0(off) (MSM_VIC_BASE + (off)) +#define VIC_REG_1(off) (MSM_VIC_BASE + (off)) -static int msm_irq_set_wake(struct irq_data *d, unsigned int on) -{ - return -EINVAL; -} +#define VIC_INT_SELECT0 0x0000 /* 1: FIQ, 0: IRQ */ +#define VIC_INT_EN0 0x0010 +#define VIC_INT_ENCLEAR0 0x0020 +#define VIC_INT_ENSET0 0x0030 +#define VIC_INT_TYPE0 0x0040 /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_POLARITY0 0x0050 /* 1: NEG, 0: POS */ +#define VIC_INT_MASTEREN 0x0064 /* 1: IRQ, 2: FIQ */ +#define VIC_CONFIG 0x0068 /* 1: USE ARM1136 VIC */ +#define VIC_INT_CLEAR0 0x00B0 static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type) { - void __iomem *treg = VIC_INT_TYPE0 + ((d->irq & 32) ? 4 : 0); - void __iomem *preg = VIC_INT_POLARITY0 + ((d->irq & 32) ? 4 : 0); - int b = 1 << (d->irq & 31); - - if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) - writel(readl(preg) | b, preg); - if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) - writel(readl(preg) & (~b), preg); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - gc->irq_base); + + if (flow_type & (IRQF_TRIGGER_LOW | IRQF_TRIGGER_FALLING)) + gc->polarity_cache |= mask; + else + gc->polarity_cache &= ~mask; + writel(gc->polarity_cache, gc->reg_base + gc->chip_types->regs.type); if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { - writel(readl(treg) | b, treg); + gc->type_cache |= mask; __irq_set_handler_locked(d->irq, handle_edge_irq); - } - if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) { - writel(readl(treg) & (~b), treg); + } else { + gc->type_cache &= ~mask; __irq_set_handler_locked(d->irq, handle_level_irq); } + writel(gc->type_cache, gc->reg_base + gc->chip_types->regs.polarity); return 0; } -static struct irq_chip msm_irq_chip = { - .name = "msm", - .irq_ack = msm_irq_ack, - .irq_mask = msm_irq_mask, - .irq_unmask = msm_irq_unmask, - .irq_set_wake = msm_irq_set_wake, - .irq_set_type = msm_irq_set_type, -}; +static __init void msm_init_gc(void __iomem *base, unsigned int irq_start) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + gc = irq_alloc_generic_chip("msm", 1, irq_start, base, handle_level_irq); + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_ack; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; + ct->chip.irq_set_type = msm_irq_set_type, + ct->regs.ack = VIC_INT_CLEAR0; + ct->regs.disable = VIC_INT_ENCLEAR0; + ct->regs.enable = VIC_INT_ENSET0; + ct->regs.type = VIC_INT_TYPE0; + ct->regs.polarity = VIC_INT_POLARITY0; + + irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_NOREQUEST | IRQ_NOPROBE, 0); +} void __init msm_init_irq(void) { - unsigned n; + void __iomem *reg_base = MSM_VIC_BASE; + unsigned int irq; /* select level interrupts */ - writel(0, VIC_INT_TYPE0); - writel(0, VIC_INT_TYPE1); + writel(0, VIC_REG_0(VIC_INT_TYPE0)); + writel(0, VIC_REG_1(VIC_INT_TYPE0)); /* select highlevel interrupts */ - writel(0, VIC_INT_POLARITY0); - writel(0, VIC_INT_POLARITY1); + writel(0, VIC_REG_0(VIC_INT_POLARITY0)); + writel(0, VIC_REG_1(VIC_INT_POLARITY0)); /* select IRQ for all INTs */ - writel(0, VIC_INT_SELECT0); - writel(0, VIC_INT_SELECT1); + writel(0, VIC_REG_0(VIC_INT_SELECT0)); + writel(0, VIC_REG_1(VIC_INT_SELECT0)); /* disable all INTs */ - writel(0, VIC_INT_EN0); - writel(0, VIC_INT_EN1); + writel(0, VIC_REG_0(VIC_INT_EN0)); + writel(0, VIC_REG_1(VIC_INT_EN0)); /* don't use 1136 vic */ - writel(0, VIC_CONFIG); + writel(0, VIC_REG_0(VIC_CONFIG)); /* enable interrupt controller */ - writel(1, VIC_INT_MASTEREN); + writel(1, VIC_REG_0(VIC_INT_MASTEREN)); - for (n = 0; n < NR_MSM_IRQS; n++) { - irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq); - set_irq_flags(n, IRQF_VALID); - } + for (irq = 0; irq < NR_MSM_IRQS; irq += 32, reg_base += 4) + msm_init_gc(reg_base, irq); }