aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/sni/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sni/irq.c')
-rw-r--r--arch/mips/sni/irq.c188
1 files changed, 44 insertions, 144 deletions
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
index 039e8e54050..ad5fc471a00 100644
--- a/arch/mips/sni/irq.c
+++ b/arch/mips/sni/irq.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 1992 Linus Torvalds
* Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 2006 Thomas Bogendoerfer
*/
#include <linux/delay.h>
#include <linux/init.h>
@@ -15,152 +16,34 @@
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/sni.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
-static void enable_pciasic_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
-
- *(volatile u8 *) PCIMT_IRQSEL |= mask;
-}
-
-void disable_pciasic_irq(unsigned int irq)
-{
- unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
-
- *(volatile u8 *) PCIMT_IRQSEL &= mask;
-}
+void (*sni_hwint)(void);
-static void end_pciasic_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_pciasic_irq(irq);
-}
-
-static struct irq_chip pciasic_irq_type = {
- .name = "ASIC-PCI",
- .ack = disable_pciasic_irq,
- .mask = disable_pciasic_irq,
- .mask_ack = disable_pciasic_irq,
- .unmask = enable_pciasic_irq,
- .end = end_pciasic_irq,
-};
-
-/*
- * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
- * button interrupts. Later ...
- */
-static void pciasic_hwint0(void)
-{
- panic("Received int0 but no handler yet ...");
-}
-
-/* This interrupt was used for the com1 console on the first prototypes. */
-static void pciasic_hwint2(void)
-{
- /* I think this shouldn't happen on production machines. */
- panic("hwint2 and no handler yet");
-}
-
-/* hwint5 is the r4k count / compare interrupt */
-static void pciasic_hwint5(void)
-{
- panic("hwint5 and no handler yet");
-}
-
-static unsigned int ls1bit8(unsigned int x)
-{
- int b = 7, s;
-
- s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
- s = 2; if ((x & 0x30) == 0) s = 0; b -= s; x <<= s;
- s = 1; if ((x & 0x40) == 0) s = 0; b -= s;
-
- return b;
-}
-
-/*
- * hwint 1 deals with EISA and SCSI interrupts,
- *
- * The EISA_INT bit in CSITPEND is high active, all others are low active.
- */
-static void pciasic_hwint1(void)
+asmlinkage void plat_irq_dispatch(void)
{
- u8 pend = *(volatile char *)PCIMT_CSITPEND;
- unsigned long flags;
-
- if (pend & IT_EISA) {
- int irq;
- /*
- * Note: ASIC PCI's builtin interrupt achknowledge feature is
- * broken. Using it may result in loss of some or all i8259
- * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ...
- */
- irq = i8259_irq();
- if (unlikely(irq < 0))
- return;
-
- do_IRQ(irq);
- }
-
- if (!(pend & IT_SCSI)) {
- flags = read_c0_status();
- clear_c0_status(ST0_IM);
- do_IRQ(PCIMT_IRQ_SCSI);
- write_c0_status(flags);
- }
+ sni_hwint();
}
-/*
- * hwint 3 should deal with the PCI A - D interrupts,
- */
-static void pciasic_hwint3(void)
+/* ISA irq handler */
+static irqreturn_t sni_isa_irq_handler(int dummy, void *p)
{
- u8 pend = *(volatile char *)PCIMT_CSITPEND;
int irq;
- pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD);
- clear_c0_status(IE_IRQ3);
- irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
- do_IRQ(irq);
- set_c0_status(IE_IRQ3);
-}
+ irq = i8259_irq();
+ if (unlikely(irq < 0))
+ return IRQ_NONE;
-/*
- * hwint 4 is used for only the onboard PCnet 32.
- */
-static void pciasic_hwint4(void)
-{
- clear_c0_status(IE_IRQ4);
- do_IRQ(PCIMT_IRQ_ETHERNET);
- set_c0_status(IE_IRQ4);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_status() & read_c0_cause();
- static unsigned char led_cache;
-
- *(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
-
- if (pending & 0x0800)
- pciasic_hwint1();
- else if (pending & 0x4000)
- pciasic_hwint4();
- else if (pending & 0x2000)
- pciasic_hwint3();
- else if (pending & 0x1000)
- pciasic_hwint2();
- else if (pending & 0x8000)
- pciasic_hwint5();
- else if (pending & 0x0400)
- pciasic_hwint0();
+ do_IRQ(irq);
+ return IRQ_HANDLED;
}
-void __init init_pciasic(void)
-{
- * (volatile u8 *) PCIMT_IRQSEL =
- IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
-}
+struct irqaction sni_isa_irq = {
+ .handler = sni_isa_irq_handler,
+ .name = "ISA",
+ .flags = SA_SHIRQ
+};
/*
* On systems with i8259-style interrupt controllers we assume for
@@ -169,14 +52,31 @@ void __init init_pciasic(void)
*/
void __init arch_init_irq(void)
{
- int i;
-
init_i8259_irqs(); /* Integrated i8259 */
- init_pciasic();
-
- /* Actually we've got more interrupts to handle ... */
- for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++)
- set_irq_chip(i, &pciasic_irq_type);
-
- change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4);
+ switch (sni_brd_type) {
+ case SNI_BRD_10:
+ case SNI_BRD_10NEW:
+ case SNI_BRD_TOWER_OASIC:
+ case SNI_BRD_MINITOWER:
+ sni_a20r_irq_init();
+ break;
+
+ case SNI_BRD_PCI_TOWER:
+ sni_pcit_irq_init();
+ break;
+
+ case SNI_BRD_PCI_TOWER_CPLUS:
+ sni_pcit_cplus_irq_init();
+ break;
+
+ case SNI_BRD_RM200:
+ sni_rm200_irq_init();
+ break;
+
+ case SNI_BRD_PCI_MTOWER:
+ case SNI_BRD_PCI_DESKTOP:
+ case SNI_BRD_PCI_MTOWER_CPLUS:
+ sni_pcimt_irq_init();
+ break;
+ }
}