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 / jmr3927 / rbhma3100 / irq.c
index 4ab85b5..7221744 100644 (file)
@@ -29,7 +29,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/init.h>
 
 #include <linux/errno.h>
@@ -45,8 +44,8 @@
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/bitops.h>
 
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
@@ -77,8 +76,6 @@ static int jmr3927_gen_iack(void)
 }
 #endif
 
-extern asmlinkage void jmr3927_IRQ(void);
-
 #define irc_dlevel     0
 #define irc_elevel     1
 
@@ -89,38 +86,10 @@ static unsigned char irc_level[TX3927_NUM_IR] = {
        6, 6, 6                 /* TMR */
 };
 
-static inline void mask_irq(unsigned int irq_nr)
-{
-       struct tb_irq_space* sp;
-       for (sp = tb_irq_spaces; sp; sp = sp->next) {
-               if (sp->start_irqno <= irq_nr &&
-                   irq_nr < sp->start_irqno + sp->nr_irqs) {
-                       if (sp->mask_func)
-                               sp->mask_func(irq_nr - sp->start_irqno,
-                                             sp->space_id);
-                       break;
-               }
-       }
-}
-
-static inline void unmask_irq(unsigned int irq_nr)
-{
-       struct tb_irq_space* sp;
-       for (sp = tb_irq_spaces; sp; sp = sp->next) {
-               if (sp->start_irqno <= irq_nr &&
-                   irq_nr < sp->start_irqno + sp->nr_irqs) {
-                       if (sp->unmask_func)
-                               sp->unmask_func(irq_nr - sp->start_irqno,
-                                               sp->space_id);
-                       break;
-               }
-       }
-}
-
 static void jmr3927_irq_disable(unsigned int irq_nr);
 static void jmr3927_irq_enable(unsigned int irq_nr);
 
-static spinlock_t jmr3927_irq_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(jmr3927_irq_lock);
 
 static unsigned int jmr3927_irq_startup(unsigned int irq)
 {
@@ -133,34 +102,52 @@ static unsigned int jmr3927_irq_startup(unsigned int irq)
 
 static void jmr3927_irq_ack(unsigned int irq)
 {
-       if (irq == JMR3927_IRQ_IRC_TMR0) {
+       if (irq == JMR3927_IRQ_IRC_TMR0)
                jmr3927_tmrptr->tisr = 0;       /* ack interrupt */
-       }
 
        jmr3927_irq_disable(irq);
 }
 
 static void jmr3927_irq_end(unsigned int irq)
 {
-       jmr3927_irq_enable(irq);
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               jmr3927_irq_enable(irq);
 }
 
 static void jmr3927_irq_disable(unsigned int irq_nr)
 {
+       struct tb_irq_space* sp;
        unsigned long flags;
 
-       spinlock_irqsave(&jmr3927_irq_lock, flags);
-       mask_irq(irq_nr);
-       spinlock_irqrestore(&jmr3927_irq_lock, flags);
+       spin_lock_irqsave(&jmr3927_irq_lock, flags);
+       for (sp = tb_irq_spaces; sp; sp = sp->next) {
+               if (sp->start_irqno <= irq_nr &&
+                   irq_nr < sp->start_irqno + sp->nr_irqs) {
+                       if (sp->mask_func)
+                               sp->mask_func(irq_nr - sp->start_irqno,
+                                             sp->space_id);
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&jmr3927_irq_lock, flags);
 }
 
 static void jmr3927_irq_enable(unsigned int irq_nr)
 {
+       struct tb_irq_space* sp;
        unsigned long flags;
 
-       spinlock_irqsave(&jmr3927_irq_lock, flags);
-       unmask_irq(irq_nr);
-       spinlock_irqrestore(&jmr3927_irq_lock, flags);
+       spin_lock_irqsave(&jmr3927_irq_lock, flags);
+       for (sp = tb_irq_spaces; sp; sp = sp->next) {
+               if (sp->start_irqno <= irq_nr &&
+                   irq_nr < sp->start_irqno + sp->nr_irqs) {
+                       if (sp->unmask_func)
+                               sp->unmask_func(irq_nr - sp->start_irqno,
+                                               sp->space_id);
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&jmr3927_irq_lock, flags);
 }
 
 /*
@@ -216,7 +203,10 @@ static void mask_irq_irc(int irq_nr, int space_id)
        /* update IRCSR */
        tx3927_ircptr->imr = 0;
        tx3927_ircptr->imr = irc_elevel;
+       /* flush write buffer */
+       (void)tx3927_ircptr->ssr;
 }
+
 static void unmask_irq_irc(int irq_nr, int space_id)
 {
        volatile unsigned long *ilrp = &tx3927_ircptr->ilr[irq_nr / 2];
@@ -269,7 +259,7 @@ void jmr3927_spurious(struct pt_regs *regs)
               regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
 }
 
-void jmr3927_irc_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
        int irq;
 
@@ -287,7 +277,7 @@ void jmr3927_irc_irqdispatch(struct pt_regs *regs)
        do_IRQ(irq + JMR3927_IRQ_IRC, regs);
 }
 
-static void jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR);
        int i;
@@ -298,13 +288,14 @@ static void jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        do_IRQ(irq, regs);
                }
        }
+       return IRQ_HANDLED;
 }
 
 static struct irqaction ioc_action = {
        jmr3927_ioc_interrupt, 0, CPU_MASK_NONE, "IOC", NULL, NULL,
 };
 
-static void jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        unsigned char istat = jmr3927_isac_reg_in(JMR3927_ISAC_INTS2_ADDR);
        int i;
@@ -315,6 +306,7 @@ static void jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        do_IRQ(irq, regs);
                }
        }
+       return IRQ_HANDLED;
 }
 
 static struct irqaction isac_action = {
@@ -322,19 +314,23 @@ static struct irqaction isac_action = {
 };
 
 
-static void jmr3927_isaerr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+static irqreturn_t jmr3927_isaerr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
        printk(KERN_WARNING "ISA error interrupt (irq 0x%x).\n", irq);
+
+       return IRQ_HANDLED;
 }
 static struct irqaction isaerr_action = {
        jmr3927_isaerr_interrupt, 0, CPU_MASK_NONE, "ISA error", NULL, NULL,
 };
 
-static void jmr3927_pcierr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+static irqreturn_t jmr3927_pcierr_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
        printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq);
        printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n",
               tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat);
+
+       return IRQ_HANDLED;
 }
 static struct irqaction pcierr_action = {
        jmr3927_pcierr_interrupt, 0, CPU_MASK_NONE, "PCI error", NULL, NULL,
@@ -343,7 +339,8 @@ static struct irqaction pcierr_action = {
 int jmr3927_ether1_irq = 0;
 
 void jmr3927_irq_init(u32 irq_base);
-void jmr3927_irq_setup(void)
+
+void __init arch_init_irq(void)
 {
        /* look for io board's presence */
        int have_isac = jmr3927_have_isac();
@@ -398,8 +395,6 @@ void jmr3927_irq_setup(void)
 
        jmr3927_irq_init(NR_ISA_IRQS);
 
-       set_except_vector(0, jmr3927_IRQ);
-
        /* setup irq space */
        add_tb_irq_space(&jmr3927_isac_irqspace);
        add_tb_irq_space(&jmr3927_ioc_irqspace);
@@ -421,44 +416,25 @@ void jmr3927_irq_setup(void)
        set_c0_status(ST0_IM);  /* IE bit is still 0. */
 }
 
-void (*irq_setup)(void);
-
-void __init init_IRQ(void)
-{
-
-#ifdef CONFIG_KGDB
-        extern void breakpoint(void);
-        extern void set_debug_traps(void);
-
-        puts("Wait for gdb client connection ...\n");
-        set_debug_traps();
-        breakpoint();
-#endif
-
-        /* invoke board-specific irq setup */
-        irq_setup();
-}
-
-static hw_irq_controller jmr3927_irq_controller = {
-       "jmr3927_irq",
-       jmr3927_irq_startup,
-       jmr3927_irq_shutdown,
-       jmr3927_irq_enable,
-       jmr3927_irq_disable,
-       jmr3927_irq_ack,
-       jmr3927_irq_end,
+static struct irq_chip jmr3927_irq_controller = {
+       .typename = "jmr3927_irq",
+       .startup = jmr3927_irq_startup,
+       .shutdown = jmr3927_irq_shutdown,
+       .enable = jmr3927_irq_enable,
+       .disable = jmr3927_irq_disable,
+       .ack = jmr3927_irq_ack,
+       .end = jmr3927_irq_end,
 };
 
 void jmr3927_irq_init(u32 irq_base)
 {
        u32 i;
 
-       init_generic_irq();
        for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) {
                irq_desc[i].status = IRQ_DISABLED;
                irq_desc[i].action = NULL;
                irq_desc[i].depth = 1;
-               irq_desc[i].handler = &jmr3927_irq_controller;
+               irq_desc[i].chip = &jmr3927_irq_controller;
        }
 
        jmr3927_irq_base = irq_base;