Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / arch / mips / tx4927 / common / tx4927_irq.c
index 14591d1..cd176f6 100644 (file)
@@ -23,7 +23,6 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
@@ -37,7 +36,7 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/irq.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -48,8 +47,6 @@
 /*
  * DEBUG
  */
-#define TX4927_IRQ_CHECK_CP0
-#define TX4927_IRQ_CHECK_PIC
 
 #undef TX4927_IRQ_DEBUG
 
@@ -145,11 +142,11 @@ static void tx4927_irq_pic_end(unsigned int irq);
  * Kernel structs for all pic's
  */
 
-static spinlock_t tx4927_cp0_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t tx4927_pic_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(tx4927_cp0_lock);
+static DEFINE_SPINLOCK(tx4927_pic_lock);
 
 #define TX4927_CP0_NAME "TX4927-CP0"
-static struct hw_interrupt_type tx4927_irq_cp0_type = {
+static struct irq_chip tx4927_irq_cp0_type = {
        .typename       = TX4927_CP0_NAME,
        .startup        = tx4927_irq_cp0_startup,
        .shutdown       = tx4927_irq_cp0_shutdown,
@@ -161,7 +158,7 @@ static struct hw_interrupt_type tx4927_irq_cp0_type = {
 };
 
 #define TX4927_PIC_NAME "TX4927-PIC"
-static struct hw_interrupt_type tx4927_irq_pic_type = {
+static struct irq_chip tx4927_irq_pic_type = {
        .typename       = TX4927_PIC_NAME,
        .startup        = tx4927_irq_pic_startup,
        .shutdown       = tx4927_irq_pic_shutdown,
@@ -172,7 +169,7 @@ static struct hw_interrupt_type tx4927_irq_pic_type = {
        .set_affinity   = NULL
 };
 
-#define TX4927_PIC_ACTION(s) { no_action, 0, 0, s, NULL, NULL }
+#define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL }
 static struct irqaction tx4927_irq_pic_action =
 TX4927_PIC_ACTION(TX4927_PIC_NAME);
 
@@ -229,7 +226,7 @@ static void __init tx4927_irq_cp0_init(void)
                irq_desc[i].status = IRQ_DISABLED;
                irq_desc[i].action = 0;
                irq_desc[i].depth = 1;
-               irq_desc[i].handler = &tx4927_irq_cp0_type;
+               irq_desc[i].chip = &tx4927_irq_cp0_type;
        }
 
        return;
@@ -239,16 +236,6 @@ static unsigned int tx4927_irq_cp0_startup(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_STARTUP, "irq=%d \n", irq);
 
-#ifdef TX4927_IRQ_CHECK_CP0
-       {
-               if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        tx4927_irq_cp0_enable(irq);
 
        return (0);
@@ -258,16 +245,6 @@ static void tx4927_irq_cp0_shutdown(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_SHUTDOWN, "irq=%d \n", irq);
 
-#ifdef TX4927_IRQ_CHECK_CP0
-       {
-               if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        tx4927_irq_cp0_disable(irq);
 
        return;
@@ -279,16 +256,6 @@ static void tx4927_irq_cp0_enable(unsigned int irq)
 
        TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENABLE, "irq=%d \n", irq);
 
-#ifdef TX4927_IRQ_CHECK_CP0
-       {
-               if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        spin_lock_irqsave(&tx4927_cp0_lock, flags);
 
        tx4927_irq_cp0_modify(CCP0_STATUS, 0, tx4927_irq_cp0_mask(irq));
@@ -304,16 +271,6 @@ static void tx4927_irq_cp0_disable(unsigned int irq)
 
        TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_DISABLE, "irq=%d \n", irq);
 
-#ifdef TX4927_IRQ_CHECK_CP0
-       {
-               if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        spin_lock_irqsave(&tx4927_cp0_lock, flags);
 
        tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0);
@@ -327,16 +284,6 @@ static void tx4927_irq_cp0_mask_and_ack(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_MASK, "irq=%d \n", irq);
 
-#ifdef TX4927_IRQ_CHECK_CP0
-       {
-               if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        tx4927_irq_cp0_disable(irq);
 
        return;
@@ -346,16 +293,6 @@ static void tx4927_irq_cp0_end(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq);
 
-#ifdef TX4927_IRQ_CHECK_CP0
-       {
-               if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
                tx4927_irq_cp0_enable(irq);
        }
@@ -497,7 +434,7 @@ static void __init tx4927_irq_pic_init(void)
                irq_desc[i].status = IRQ_DISABLED;
                irq_desc[i].action = 0;
                irq_desc[i].depth = 2;
-               irq_desc[i].handler = &tx4927_irq_pic_type;
+               irq_desc[i].chip = &tx4927_irq_pic_type;
        }
 
        setup_irq(TX4927_IRQ_NEST_PIC_ON_CP0, &tx4927_irq_pic_action);
@@ -516,16 +453,6 @@ static unsigned int tx4927_irq_pic_startup(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_STARTUP, "irq=%d\n", irq);
 
-#ifdef TX4927_IRQ_CHECK_PIC
-       {
-               if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        tx4927_irq_pic_enable(irq);
 
        return (0);
@@ -535,16 +462,6 @@ static void tx4927_irq_pic_shutdown(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_SHUTDOWN, "irq=%d\n", irq);
 
-#ifdef TX4927_IRQ_CHECK_PIC
-       {
-               if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        tx4927_irq_pic_disable(irq);
 
        return;
@@ -556,16 +473,6 @@ static void tx4927_irq_pic_enable(unsigned int irq)
 
        TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENABLE, "irq=%d\n", irq);
 
-#ifdef TX4927_IRQ_CHECK_PIC
-       {
-               if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        spin_lock_irqsave(&tx4927_pic_lock, flags);
 
        tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), 0,
@@ -582,16 +489,6 @@ static void tx4927_irq_pic_disable(unsigned int irq)
 
        TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_DISABLE, "irq=%d\n", irq);
 
-#ifdef TX4927_IRQ_CHECK_PIC
-       {
-               if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        spin_lock_irqsave(&tx4927_pic_lock, flags);
 
        tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq),
@@ -606,16 +503,6 @@ static void tx4927_irq_pic_mask_and_ack(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_MASK, "irq=%d\n", irq);
 
-#ifdef TX4927_IRQ_CHECK_PIC
-       {
-               if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        tx4927_irq_pic_disable(irq);
 
        return;
@@ -625,16 +512,6 @@ static void tx4927_irq_pic_end(unsigned int irq)
 {
        TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq);
 
-#ifdef TX4927_IRQ_CHECK_PIC
-       {
-               if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) {
-                       TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR,
-                                          "bad irq=%d \n", irq);
-                       panic("\n");
-               }
-       }
-#endif
-
        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
                tx4927_irq_pic_enable(irq);
        }
@@ -647,8 +524,6 @@ static void tx4927_irq_pic_end(unsigned int irq)
  */
 void __init tx4927_irq_init(void)
 {
-       extern asmlinkage void tx4927_irq_handler(void);
-
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n");
 
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n");
@@ -657,16 +532,12 @@ void __init tx4927_irq_init(void)
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n");
        tx4927_irq_pic_init();
 
-       TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT,
-                          "=Calling set_except_vector(tx4927_irq_handler)\n");
-       set_except_vector(0, tx4927_irq_handler);
-
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
 
        return;
 }
 
-int tx4927_irq_nested(void)
+static int tx4927_irq_nested(void)
 {
        int sw_irq = 0;
        u32 level2;
@@ -704,3 +575,25 @@ int tx4927_irq_nested(void)
 
        return (sw_irq);
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP7)                      /* cpu timer */
+               do_IRQ(TX4927_IRQ_CPU_TIMER, regs);
+       else if (pending & STATUSF_IP2) {               /* tx4927 pic */
+               unsigned int irq = tx4927_irq_nested();
+
+               if (unlikely(irq == 0)) {
+                       spurious_interrupt(regs);
+                       return;
+               }
+               do_IRQ(irq, regs);
+       } else if (pending & STATUSF_IP0)               /* user line 0 */
+               do_IRQ(TX4927_IRQ_USER0, regs);
+       else if (pending & STATUSF_IP1)                 /* user line 1 */
+               do_IRQ(TX4927_IRQ_USER1, regs);
+       else
+               spurious_interrupt(regs);
+}