X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fasm-arm%2Farch-s3c2410%2Fentry-macro.S;fp=include%2Fasm-arm%2Farch-s3c2410%2Fentry-macro.S;h=cc06b1bd37b245a5f030feb3ef5955f18c2863b0;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=e09a6b8ec1535fc8929cd6a0ec4d1a82bc3528f8;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S index e09a6b8ec..cc06b1bd3 100644 --- a/include/asm-arm/arch-s3c2410/entry-macro.S +++ b/include/asm-arm/arch-s3c2410/entry-macro.S @@ -6,67 +6,116 @@ * 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) + * Modifications: + * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + */ #include #include + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov \base, #S3C24XX_VA_IRQ + mov \tmp, #S3C24XX_VA_IRQ + ldr \irqnr, [ \tmp, #0x14 ] @ get irq no +30000: + teq \irqnr, #4 + teqne \irqnr, #5 + beq 1002f @ external irq reg - @@ try the interrupt offset register, since it is there + @ debug check to see if interrupt reported is the same + @ as the offset.... - ldr \irqstat, [ \base, #INTPND ] - teq \irqstat, #0 - beq 1002f - ldr \irqnr, [ \base, #INTOFFSET ] - mov \tmp, #1 - tst \irqstat, \tmp, lsl \irqnr - bne 1001f - - @@ the number specified is not a valid irq, so try - @@ and work it out for ourselves - - mov \irqnr, #0 @@ start here - - @@ work out which irq (if any) we got - - 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 -1001: + 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: - @@ exit here, Z flag unset if IRQ + 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 - .endm /* currently don't need an disable_fiq macro */ .macro disable_fiq .endm + +