|
@@ -6,116 +6,83 @@
|
|
* This file is licensed under the terms of the GNU General Public
|
|
* This file is licensed under the terms of the GNU General Public
|
|
* License version 2. This program is licensed "as is" without any
|
|
* License version 2. This program is licensed "as is" without any
|
|
* warranty of any kind, whether express or implied.
|
|
* 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/hardware.h>
|
|
#include <asm/arch/irqs.h>
|
|
#include <asm/arch/irqs.h>
|
|
|
|
|
|
-
|
|
|
|
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
|
.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
|
|
|
|
|
|
+ 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:
|
|
1001:
|
|
- @ exit irq routine
|
|
|
|
- .endm
|
|
|
|
|
|
+ @@ exit here, Z flag unset if IRQ
|
|
|
|
|
|
|
|
+ .endm
|
|
|
|
|
|
/* currently don't need an disable_fiq macro */
|
|
/* currently don't need an disable_fiq macro */
|
|
|
|
|
|
.macro disable_fiq
|
|
.macro disable_fiq
|
|
.endm
|
|
.endm
|
|
-
|
|
|
|
-
|
|
|