fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / mips / pmc-sierra / yosemite / irq.c
index e8b7ed6..adb0485 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright (C) 2003 PMC-Sierra Inc.
  * Author: Manish Lachwani (lachwani@pmc-sierra.com)
  *
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
  *  Free Software Foundation;  either version 2 of the  License, or (at your
@@ -24,7 +26,6 @@
  *
  * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
  */
-
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/irq.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #define HYPERTRANSPORT_INTC     0x7a           /* INTC# */
 #define HYPERTRANSPORT_INTD     0x7b           /* INTD# */
 
-extern asmlinkage void titan_handle_int(void);
-extern void jaguar_mailbox_irq(struct pt_regs *);
-
-/* 
+/*
  * Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
  * For interprocessor interrupts, the best thing to do is to use the INTMSG
  * register. We use the same external interrupt line, i.e. INTB3 and monitor
  * another status bit
  */
-asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs)
+static void ll_ht_smp_irq_handler(int irq)
 {
-        u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
+       u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
 
        /* Ack all the bits that correspond to the interrupt sources */
        if (status != 0)
-               OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
+               OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
 
        status = OCD_READ(RM9000x2_OCD_INTP1STATUS4);
        if (status != 0)
-                OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
+               OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
 
 #ifdef CONFIG_HT_LEVEL_TRIGGER
        /*
@@ -106,51 +105,59 @@ asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs)
        }
 #endif /* CONFIG_HT_LEVEL_TRIGGER */
 
-       do_IRQ(irq, regs);
+       do_IRQ(irq);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+       unsigned int cause = read_c0_cause();
+       unsigned int status = read_c0_status();
+       unsigned int pending = cause & status;
+
+       if (pending & STATUSF_IP7) {
+               do_IRQ(7);
+       } else if (pending & STATUSF_IP2) {
+#ifdef CONFIG_HYPERTRANSPORT
+               ll_ht_smp_irq_handler(2);
+#else
+               do_IRQ(2);
+#endif
+       } else if (pending & STATUSF_IP3) {
+               do_IRQ(3);
+       } else if (pending & STATUSF_IP4) {
+               do_IRQ(4);
+       } else if (pending & STATUSF_IP5) {
+#ifdef CONFIG_SMP
+               titan_mailbox_irq();
+#else
+               do_IRQ(5);
+#endif
+       } else if (pending & STATUSF_IP6) {
+               do_IRQ(4);
+       }
 }
 
 #ifdef CONFIG_KGDB
 extern void init_second_port(void);
-extern void breakpoint(void);
-extern void set_debug_traps(void);
 #endif
 
 /*
  * Initialize the next level interrupt handler
  */
-void __init init_IRQ(void)
+void __init arch_init_irq(void)
 {
        clear_c0_status(ST0_IM);
 
-       set_except_vector(0, titan_handle_int);
-       init_generic_irq();
        mips_cpu_irq_init(0);
        rm7k_cpu_irq_init(8);
+       rm9k_cpu_irq_init(12);
 
 #ifdef CONFIG_KGDB
        /* At this point, initialize the second serial port */
        init_second_port();
-       printk("Start kgdb ... \n");
-       set_debug_traps();
-       breakpoint();
 #endif
 
 #ifdef CONFIG_GDB_CONSOLE
        register_gdb_console();
 #endif
 }
-
-#ifdef CONFIG_KGDB
-/*
- * The 16550 DUART has two ports, but is allocated one IRQ
- * for the serial console. Hence, a generic framework for
- * serial IRQ routing in place. Currently, just calls the
- * do_IRQ fuction. But, going in the future, need to check
- * DUART registers for channel A and B, then decide the
- * appropriate action
- */
-asmlinkage void yosemite_kgdb_irq(int irq, struct pt_regs *regs)
-{
-       do_IRQ(irq, regs);
-}
-#endif