From 42efed6130c8fcf7da881385b5427065d2801757 Mon Sep 17 00:00:00 2001
From: Michal Simek <monstr@monstr.eu>
Date: Mon, 7 May 2007 17:22:25 +0200
Subject: [PATCH] fix: interrupt handler for multiple sources

---
 cpu/microblaze/interrupts.c              | 19 ++++++++++++-------
 cpu/microblaze/timer.c                   |  4 +---
 include/asm-microblaze/microblaze_intc.h |  2 ++
 3 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/cpu/microblaze/interrupts.c b/cpu/microblaze/interrupts.c
index 2db847cd02..115e58d7f0 100644
--- a/cpu/microblaze/interrupts.c
+++ b/cpu/microblaze/interrupts.c
@@ -27,6 +27,7 @@
 #include <common.h>
 #include <command.h>
 #include <asm/microblaze_intc.h>
+#include <asm/asm.h>
 
 #undef DEBUG_INT
 
@@ -106,7 +107,6 @@ void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
 		act->count = 0;
 		enable_one_interrupt (irq);
 	} else {		/* disable */
-
 		act->handler = (interrupt_handler_t *) def_hdlr;
 		act->arg = (void *)irq;
 		disable_one_interrupt (irq);
@@ -147,12 +147,13 @@ int interrupts_init (void)
 
 void interrupt_handler (void)
 {
-	int irqs;
-	irqs = (intc->isr & intc->ier);	/* find active interrupt */
-
+	int irqs = (intc->isr & intc->ier);	/* find active interrupt */
+	int i = 1;
 #ifdef DEBUG_INT
+	int value;
 	printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
 		intc->iar, intc->mer);
+	R14(value);
 	printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
 #endif
 	struct irq_action *act = vecs;
@@ -165,15 +166,19 @@ void interrupt_handler (void)
 #endif
 			act->handler (act->arg);
 			act->count++;
+			intc->iar = i;
+			return;
 		}
 		irqs >>= 1;
 		act++;
+		i <<= 1;
 	}
-	intc->iar = 0xFFFFFFFF;	/* erase all events */
-#ifdef DEBUG
+
+#ifdef DEBUG_INT
 	printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
 		intc->ier, intc->iar, intc->mer);
-	printf ("Interrupt handler on %x line, r14\n", irqs);
+	R14(value);
+	printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
 #endif
 }
 #endif
diff --git a/cpu/microblaze/timer.c b/cpu/microblaze/timer.c
index be4fd57cc4..ab1cb12749 100644
--- a/cpu/microblaze/timer.c
+++ b/cpu/microblaze/timer.c
@@ -24,6 +24,7 @@
 
 #include <common.h>
 #include <asm/microblaze_timer.h>
+#include <asm/microblaze_intc.h>
 
 volatile int timestamp = 0;
 
@@ -44,9 +45,6 @@ void set_timer (ulong t)
 
 #ifdef CFG_INTC_0
 #ifdef CFG_TIMER_0
-extern void install_interrupt_handler (int irq, interrupt_handler_t * hdlr,
-				       void *arg);
-
 microblaze_timer_t *tmr = (microblaze_timer_t *) (CFG_TIMER_0_ADDR);
 
 void timer_isr (void *arg)
diff --git a/include/asm-microblaze/microblaze_intc.h b/include/asm-microblaze/microblaze_intc.h
index 73f732c566..4c385aa24f 100644
--- a/include/asm-microblaze/microblaze_intc.h
+++ b/include/asm-microblaze/microblaze_intc.h
@@ -39,3 +39,5 @@ struct irq_action {
 	int count; /* number of interrupt */
 };
 
+void install_interrupt_handler (int irq, interrupt_handler_t * hdlr,
+				       void *arg);
-- 
2.39.5