2 * linux/arch/arm/mach-iop3xx/iq80310-irq.c
4 * IRQ hadling/demuxing for IQ80310 board
6 * Author: Nicolas Pitre
7 * Copyright: (C) 2001 MontaVista Software Inc.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 * Moved demux from asm to C - DS
15 * Fixes for various revision boards - DS
17 #include <linux/init.h>
18 #include <linux/list.h>
21 #include <asm/mach/irq.h>
22 #include <asm/hardware.h>
23 #include <asm/system.h>
25 #include <asm/mach-types.h>
27 extern void iop310_init_irq(void);
28 extern void iop310_irq_demux(unsigned int, struct irqdesc *, struct pt_regs *);
30 static void iq80310_irq_mask(unsigned int irq)
32 *(volatile char *)IQ80310_INT_MASK |= (1 << (irq - IQ80310_IRQ_OFS));
35 static void iq80310_irq_unmask(unsigned int irq)
37 *(volatile char *)IQ80310_INT_MASK &= ~(1 << (irq - IQ80310_IRQ_OFS));
40 static struct irqchip iq80310_irq_chip = {
41 .ack = iq80310_irq_mask,
42 .mask = iq80310_irq_mask,
43 .unmask = iq80310_irq_unmask,
46 extern struct irqchip ext_chip;
49 iq80310_cpld_irq_handler(unsigned int irq, struct irqdesc *desc,
52 unsigned int irq_stat = *(volatile u8*)IQ80310_INT_STAT;
53 unsigned int irq_mask = *(volatile u8*)IQ80310_INT_MASK;
54 unsigned int i, handled = 0;
60 * Mask out the interrupts which aren't enabled.
62 irq_stat &= 0x1f & ~irq_mask;
65 * Test each IQ80310 CPLD interrupt
67 for (i = IRQ_IQ80310_TIMER, d = irq_desc + IRQ_IQ80310_TIMER;
68 irq_stat; i++, d++, irq_stat >>= 1)
70 d->handle(i, d, regs);
75 * If running on a board later than REV D.1, we can
76 * decode the PCI interrupt status.
79 irq_stat = *((volatile u8*)IQ80310_PCI_INT_STAT) & 7;
81 for (i = IRQ_IQ80310_INTA, d = irq_desc + IRQ_IQ80310_INTA;
82 irq_stat; i++, d++, irq_stat >>= 1)
84 d->handle(i, d, regs);
90 * If on a REV D.1 or lower board, we just assumed INTA
91 * since PCI is not routed, and it may actually be an
94 * Note that we're giving on-chip interrupts slightly
95 * higher priority than PCI by handling them first.
97 * On boards later than REV D.1, if we didn't read a
98 * CPLD interrupt, we assume it's from a device on the
101 if (system_rev == 0 || handled == 0)
102 iop310_irq_demux(irq, desc, regs);
104 desc->chip->unmask(irq);
107 void __init iq80310_init_irq(void)
109 volatile char *mask = (volatile char *)IQ80310_INT_MASK;
115 * Setup PIRSR to route PCI interrupts into xs80200
117 *IOP310_PIRSR = 0xff;
120 * Setup the IRQs in the FE820000/FE860000 registers
122 for (i = IQ80310_IRQ_OFS; i <= IRQ_IQ80310_INTD; i++) {
123 set_irq_chip(i, &iq80310_irq_chip);
124 set_irq_handler(i, do_level_IRQ);
125 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
131 for (i = IRQ_IQ80310_INTA; i < IRQ_IQ80310_INTC; i++) {
132 set_irq_chip(i, &ext_chip);
133 set_irq_handler(i, do_level_IRQ);
134 set_irq_flags(i, IRQF_VALID);
137 *mask = 0xff; /* mask all sources */
139 set_irq_chained_handler(IRQ_XS80200_EXTIRQ,
140 &iq80310_cpld_irq_handler);