summaryrefslogtreecommitdiffstats
path: root/include/asm-arm/arch-ebsa285/irq.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
commit86464aed71025541805e7b1515541aee89879e33 (patch)
treee01a457a4912a8553bc65524aa3125d51f29f810 /include/asm-arm/arch-ebsa285/irq.h
parent88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff)
Merge with Linux 2.2.1.
Diffstat (limited to 'include/asm-arm/arch-ebsa285/irq.h')
-rw-r--r--include/asm-arm/arch-ebsa285/irq.h111
1 files changed, 108 insertions, 3 deletions
diff --git a/include/asm-arm/arch-ebsa285/irq.h b/include/asm-arm/arch-ebsa285/irq.h
index 029b1b1a6..74bc33c58 100644
--- a/include/asm-arm/arch-ebsa285/irq.h
+++ b/include/asm-arm/arch-ebsa285/irq.h
@@ -5,7 +5,9 @@
*
* Changelog:
* 22-08-1998 RMK Restructured IRQ routines
+ * 03-09-1998 PJB Merged CATS support
*/
+#include <linux/config.h>
static void ebsa285_mask_irq(unsigned int irq)
{
@@ -16,7 +18,73 @@ static void ebsa285_unmask_irq(unsigned int irq)
{
*CSR_IRQ_ENABLE = 1 << irq;
}
+
+#ifdef CONFIG_CATS
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int isa_irq_mask = 0xffff;
+
+#define cached_21 (isa_irq_mask & 0xff)
+#define cached_A1 ((isa_irq_mask >> 8) & 0xff)
+
+#define update_8259(_irq) \
+ if ((_irq) & 8) \
+ outb(cached_A1, 0xa1); \
+ else \
+ outb(cached_21, 0x21);
+
+static void isa_interrupt(int irq, void *h, struct pt_regs *regs)
+{
+ asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+ unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0;
+ irqbits &= ~(1<<2); /* don't try to service the cascade */
+ while (irqbits) {
+ if (irqbits & 1)
+ do_IRQ(32 + irqnr, regs);
+ irqbits >>= 1;
+ irqnr++;
+ }
+}
+
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+static struct irqaction irq_isa =
+ { isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL };
+static struct irqaction irq_cascade =
+ { no_action, 0, 0, "cascade", NULL, NULL };
+
+static void cats_mask_and_ack_isa_irq(unsigned int irq)
+{
+ isa_irq_mask |= (1 << (irq - 32));
+ update_8259(irq);
+ if (irq & 8) {
+ inb(0xA1); /* DUMMY */
+ outb(cached_A1,0xA1);
+ outb(0x62,0x20); /* Specific EOI to cascade */
+ outb(0x20,0xA0);
+ } else {
+ inb(0x21); /* DUMMY */
+ outb(cached_21,0x21);
+ outb(0x20,0x20);
+ }
+}
+
+static void cats_mask_isa_irq(unsigned int irq)
+{
+ isa_irq_mask |= (1 << (irq - 32));
+ update_8259(irq);
+}
+
+static void cats_unmask_isa_irq(unsigned int irq)
+{
+ isa_irq_mask &= ~(1 << (irq - 32));
+ update_8259(irq);
+}
+#endif
+
static __inline__ void irq_init_irq(void)
{
int irq;
@@ -27,8 +95,45 @@ static __inline__ void irq_init_irq(void)
for (irq = 0; irq < NR_IRQS; irq++) {
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 1;
- irq_desc[irq].mask_ack = ebsa285_mask_irq;
- irq_desc[irq].mask = ebsa285_mask_irq;
- irq_desc[irq].unmask = ebsa285_unmask_irq;
+#ifdef CONFIG_CATS
+ if (machine_is_cats() && IRQ_IS_ISA(irq)) {
+ irq_desc[irq].mask_ack = cats_mask_and_ack_isa_irq;
+ irq_desc[irq].mask = cats_mask_isa_irq;
+ irq_desc[irq].unmask = cats_unmask_isa_irq;
+ } else
+#endif
+ {
+ irq_desc[irq].mask_ack = ebsa285_mask_irq;
+ irq_desc[irq].mask = ebsa285_mask_irq;
+ irq_desc[irq].unmask = ebsa285_unmask_irq;
+ }
+ }
+
+#ifdef CONFIG_CATS
+ if (machine_is_cats()) {
+ request_region(0x20, 2, "pic1");
+ request_region(0xa0, 2, "pic2");
+
+ /* set up master 8259 */
+ outb(0x11, 0x20);
+ outb(0, 0x21);
+ outb(1<<2, 0x21);
+ outb(0x1, 0x21);
+ outb(0xff, 0x21);
+ outb(0x68, 0x20);
+ outb(0xa, 0x20);
+
+ /* set up slave 8259 */
+ outb(0x11, 0xa0);
+ outb(0, 0xa1);
+ outb(2, 0xa1);
+ outb(0x1, 0xa1);
+ outb(0xff, 0xa1);
+ outb(0x68, 0xa0);
+ outb(0xa, 0xa0);
+
+ setup_arm_irq(IRQ_ISA_PIC, &irq_isa);
+ setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
}
+#endif
}