diff options
Diffstat (limited to 'arch/m68knommu/platform/coldfire/intc-2.c')
-rw-r--r-- | arch/m68knommu/platform/coldfire/intc-2.c | 76 |
1 files changed, 70 insertions, 6 deletions
diff --git a/arch/m68knommu/platform/coldfire/intc-2.c b/arch/m68knommu/platform/coldfire/intc-2.c index 5598c8b8661f..2863285927de 100644 --- a/arch/m68knommu/platform/coldfire/intc-2.c +++ b/arch/m68knommu/platform/coldfire/intc-2.c @@ -39,6 +39,15 @@ static void intc_irq_mask(unsigned int irq) val = __raw_readl(imraddr); __raw_writel(val | imrbit, imraddr); + + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + + u8 epier = __raw_readb(MCFEPORT_EPIER); + epier &= ~(1 << (irq - MCFGPIO_IRQ_VECBASE)); + __raw_writeb(epier, MCFEPORT_EPIER); + } } } @@ -64,13 +73,72 @@ static void intc_irq_unmask(unsigned int irq) val = __raw_readl(imraddr); __raw_writel(val & ~imrbit, imraddr); + + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + + u8 epier = __raw_readb(MCFEPORT_EPIER); + epier |= 1 << (irq - MCFGPIO_IRQ_VECBASE); + __raw_writeb(epier, MCFEPORT_EPIER); + } + } +} + +static void intc_irq_ack(unsigned int irq) +{ + /* only on eport */ + if (irq >= MCFGPIO_IRQ_VECBASE || + irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) { + u8 epfr = __raw_readb(MCFEPORT_EPFR); + epfr |= 1 << (irq - MCFGPIO_IRQ_VECBASE); + __raw_writeb(epfr, MCFEPORT_EPFR); } } +static int intc_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + unsigned shift; + u16 eppar; + + /* only on eport */ + if (irq < MCFGPIO_IRQ_VECBASE || + irq >= (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) + return -EINVAL; + + /* we only support TRIGGER_LOW or either (or both) RISING and FALLING */ + if ((flow_type & IRQF_TRIGGER_HIGH) || + ((flow_type & IRQF_TRIGGER_LOW) && + (flow_type & (IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING)))) + return -EINVAL; + + shift = (irq - MCFGPIO_IRQ_VECBASE) * 2; + + /* default to TRIGGER_LOW */ + eppar = 0; + if (flow_type & IRQF_TRIGGER_RISING) + eppar |= (0x01 << shift); + if (flow_type & IRQF_TRIGGER_FALLING) + eppar |= (0x02 << shift); + + if (eppar) + set_irq_handler(irq, handle_edge_irq); + else + set_irq_handler(irq, handle_level_irq); + + eppar |= (__raw_readw(MCFEPORT_EPPAR) & ~(0x3 << shift)); + __raw_writew(eppar, MCFEPORT_EPPAR); + + return 0; +} + static struct irq_chip intc_irq_chip = { .name = "CF-INTC", .mask = intc_irq_mask, .unmask = intc_irq_unmask, + .ack = intc_irq_ack, + .set_type = intc_irq_set_type, }; void __init init_IRQ(void) @@ -83,11 +151,7 @@ void __init init_IRQ(void) __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL); __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL); - for (irq = 0; (irq < NR_IRQS); irq++) { - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = NULL; - irq_desc[irq].depth = 1; - irq_desc[irq].chip = &intc_irq_chip; - } + for (irq = 0; (irq < NR_IRQS); irq++) + set_irq_chip_and_handler(irq, &intc_irq_chip, handle_level_irq); } |