--- linux-2.6.16-git20/include/asm-arm/arch-s3c2410/entry-macro.S	2006-03-20 05:53:29.000000000 +0000
+++ linux-2.6.16-git20-bjd4/include/asm-arm/arch-s3c2410/entry-macro.S	2006-04-01 18:26:38.000000000 +0100
@@ -6,116 +6,83 @@
  * This file is licensed under  the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
+*/
+
+/* We have a problem that the INTOFFSET register does not always
+ * show one interrupt. Occasionally we get two interrupts through
+ * the prioritiser, and this causes the INTOFFSET register to show
+ * what looks like the logical-or of the two interrupt numbers.
+ *
+ * Thanks to Klaus, Shannon, et al for helping to debug this problem
+*/
+
+#define INTPND		(0x10)	
+#define INTOFFSET	(0x14)
+#define EXTINTPEND	(0xa8)
+#define EXTINTMASK	(0xa4)
 
- * Modifications:
- *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
- */
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
 
-
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 
-		mov	\tmp, #S3C24XX_VA_IRQ
-		ldr	\irqnr, [ \tmp, #0x14 ]		@ get irq no
-30000:
-		teq	\irqnr, #4
-		teqne	\irqnr, #5
-		beq	1002f				@ external irq reg
-
-		@ debug check to see if interrupt reported is the same
-		@ as the offset....
-
-		teq	\irqnr, #0
-		beq	20002f
-		ldr	\irqstat, [ \tmp, #0x10 ]	@ INTPND
-		mov	\irqstat, \irqstat, lsr \irqnr
-		tst	\irqstat, #1
-		bne	20002f
-
-		/* debug/warning if we get an invalud response from the
-		 * INTOFFSET register */
-#if 1
-		stmfd	r13!, { r0 - r4 , r8-r12, r14 }
-		ldr	r1,	[ \tmp, #0x14 ]		@ INTOFFSET
-		ldr	r2,	[ \tmp, #0x10 ]		@ INTPND
-		ldr	r3,	[ \tmp, #0x00 ]		@ SRCPND
-		adr	r0, 20003f
-		bl	printk
-		b	20004f
-
-20003:
-		.ascii	"<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
-		.byte	0
-		.align	4
-20004:
-		mov	r1, #1
-		mov	\tmp, #S3C24XX_VA_IRQ
-		ldmfd	r13!, { r0 - r4 , r8-r12, r14 }
-#endif
-
-		@ try working out interrupt number for ourselves
-		mov	\irqnr, #0
-		ldr	\irqstat, [ \tmp, #0x10 ]	@ INTPND
-10021:
-		movs	\irqstat, \irqstat, lsr#1
-		bcs	30000b		@ try and re-start the proccess
-		add	\irqnr, \irqnr, #1
-		cmp	\irqnr, #32
-		ble	10021b
-
-		@ found no interrupt, set Z flag and leave
-		movs	\irqnr, #0
-		b	1001f
-
-20005:
-20002:		@ exit
-		@ we base the s3c2410x interrupts at 16 and above to allow
-		@ isa peripherals to have their standard interrupts, also
-		@ ensure that Z flag is un-set on exit
-
-		@ note, we cannot be sure if we get IRQ_EINT0 (0) that
-		@ there is simply no interrupt pending, so in all other
-		@ cases we jump to say we have found something, otherwise
-		@ we check to see if the interrupt really is assrted
-		adds	\irqnr, \irqnr, #IRQ_EINT0
-		teq	\irqnr, #IRQ_EINT0
-		bne	1001f				@ exit
-		ldr	\irqstat, [ \tmp, #0x10 ]	@ INTPND
-		teq	\irqstat, #0
-		moveq	\irqnr, #0
-		b	1001f
-
-		@ we get here from no main or external interrupts pending
-1002:
-		add	\tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
-		ldr	\irqstat, [ \tmp, # 0xa8 ]	@ EXTINTPEND
-		ldr	\irqnr, [ \tmp, # 0xa4 ]	@ EXTINTMASK
-
-		bic	\irqstat, \irqstat, \irqnr	@ clear masked irqs
-
-		mov	\irqnr, #IRQ_EINT4		@ start extint nos
-		mov	\irqstat, \irqstat, lsr#4	@ ignore bottom 4 bits
-10021:
-		movs	\irqstat, \irqstat, lsr#1
-		bcs	1004f
-		add	\irqnr, \irqnr, #1
-		cmp	\irqnr, #IRQ_EINT23
-		ble	10021b
-
-		@ found no interrupt, set Z flag and leave
-		movs	\irqnr, #0
-
-1004:		@ ensure Z flag clear in case our MOVS shifted out the last bit
-		teq	\irqnr, #0
-1001:
-		@ exit irq routine
-		.endm
+		mov	\base, #S3C24XX_VA_IRQ
 
+		ldr	\irqstat, [ \base, #INTPND]		
+		bics	\irqnr, \irqstat, #3<<4		@@ only an GPIO IRQ
+		beq	2000f
+
+		@@ try the interrupt offset register, since it is there
+
+		ldr	\irqnr, [ \base, #INTOFFSET ]
+		mov	\tmp, #1
+		tst	\irqstat, \tmp, lsl \irqnr
+		addne	\irqnr, \irqnr, #IRQ_EINT0
+		bne	1001f
+
+		@@ the number specified is not a valid irq, so try
+		@@ and work it out for ourselves
+		
+		mov	\irqnr, #IRQ_EINT0		@@ start here
+		b	3000f
+
+2000:
+		@@ load the GPIO interrupt register, and check it
+
+		add	\tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
+		ldr	\irqstat, [ \tmp, # EXTINTPEND ]
+		ldr	\irqnr,   [ \tmp, # EXTINTMASK ]
+		bics	\irqstat, \irqstat, \irqnr
+		beq	1001f
+
+		mov	\irqnr, #(IRQ_EINT4 - 4)
+		
+		@@ work out which irq (if any) we got
+3000:
+		movs	\tmp, \irqstat, lsl#16
+		addeq	\irqnr, \irqnr, #16
+		moveq	\irqstat, \irqstat, lsr#16
+		tst	\irqstat, #0xff
+		addeq	\irqnr, \irqnr, #8
+		moveq	\irqstat, \irqstat, lsr#8
+		tst	\irqstat, #0xf
+		addeq	\irqnr, \irqnr, #4
+		moveq	\irqstat, \irqstat, lsr#4
+		tst	\irqstat, #0x3
+		addeq	\irqnr, \irqnr, #2
+		moveq	\irqstat, \irqstat, lsr#2
+		tst	\irqstat, #0x1
+		addeq	\irqnr, \irqnr, #1
+
+		@@ we have the value
+		movs	\irqnr, \irqnr
+		
+1001:	
+		@@ exit here, Z flag unset if IRQ
+
+	.endm	
 
 		/* currently don't need an disable_fiq macro */
 
 		.macro	disable_fiq
 		.endm
-
-

