Pull bugzilla-5452 into release branch
[pandora-kernel.git] / arch / mips / au1000 / common / irq.c
index 6a25677..afe05ec 100644 (file)
@@ -66,9 +66,9 @@
 #define EXT_INTC1_REQ1 5 /* IP 5 */
 #define MIPS_TIMER_IP  7 /* IP 7 */
 
-extern asmlinkage void au1000_IRQ(void);
 extern void set_debug_traps(void);
 extern irq_cpustat_t irq_stat [NR_CPUS];
+extern void mips_timer_interrupt(struct pt_regs *regs);
 
 static void setup_local_irq(unsigned int irq, int type, int int_req);
 static unsigned int startup_irq(unsigned int irq);
@@ -83,7 +83,7 @@ inline void local_disable_irq(unsigned int irq_nr);
 void   (*board_init_irq)(void);
 
 #ifdef CONFIG_PM
-extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
+extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
 #endif
 
 static DEFINE_SPINLOCK(irq_lock);
@@ -293,29 +293,31 @@ static struct hw_interrupt_type level_irq_type = {
 };
 
 #ifdef CONFIG_PM
-void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *))
+void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *))
 {
-       static struct irqaction action;
-       /* This is a big problem.... since we didn't use request_irq
-          when kernel/irq.c calls probe_irq_xxx this interrupt will
-          be probed for usage. This will end up disabling the device :(
+       struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT];
 
-       Give it a bogus "action" pointer -- this will keep it from
-          getting auto-probed!
+       static struct irqaction action;
+       memset(&action, 0, sizeof(struct irqaction));
 
-       By setting the status to match that of request_irq() we
-       can avoid it.  --cgray
+       /* This is a big problem.... since we didn't use request_irq
+        * when kernel/irq.c calls probe_irq_xxx this interrupt will
+        * be probed for usage. This will end up disabling the device :(
+        * Give it a bogus "action" pointer -- this will keep it from
+        * getting auto-probed!
+        *
+        * By setting the status to match that of request_irq() we
+        * can avoid it.  --cgray
        */
        action.dev_id = handler;
-       action.flags = 0;
-       action.mask = 0;
+       action.flags = SA_INTERRUPT;
+       cpus_clear(action.mask);
        action.name = "Au1xxx TOY";
        action.handler = handler;
        action.next = NULL;
 
-       irq_desc[AU1000_TOY_MATCH2_INT].action = &action; 
-       irq_desc[AU1000_TOY_MATCH2_INT].status 
-                &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
+       desc->action = &action;
+       desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
 
        local_enable_irq(AU1000_TOY_MATCH2_INT);
 }
@@ -444,8 +446,6 @@ void __init arch_init_irq(void)
        extern int au1xxx_ic0_nr_irqs;
 
        cp0_status = read_c0_status();
-       memset(irq_desc, 0, sizeof(irq_desc));
-       set_except_vector(0, au1000_IRQ);
 
        /* Initialize interrupt controllers to a safe state.
        */
@@ -660,3 +660,21 @@ restore_au1xxx_intctl(void)
        au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
 }
 #endif /* CONFIG_PM */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+       if (pending & CAUSEF_IP7)
+               mips_timer_interrupt(regs);
+       else if (pending & CAUSEF_IP2)
+               intc0_req0_irqdispatch(regs);
+       else if (pending & CAUSEF_IP3)
+               intc0_req1_irqdispatch(regs);
+       else if (pending & CAUSEF_IP4)
+               intc1_req0_irqdispatch(regs);
+       else if (pending  & CAUSEF_IP5)
+               intc1_req1_irqdispatch(regs);
+       else
+               spurious_interrupt(regs);
+}