Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26f91fd5 authored by Ben Dooks's avatar Ben Dooks Committed by Russell King
Browse files

[ARM] 3443/1: [S3C2410] Improve IRQ entry code



Patch from Ben Dooks

Remove the old debug from the IRQ entry code,
update the comments on the handling of the
IRQ registers.

The message "bad interrupt offset" is removed
as it is only helpful for debugging, and can
cause printk() flooding when under load.

Make the code to deal with GPIO interrupts
faster, and use the same path to deal with
unexplained results from the IRQ registers.

Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 23759dc6
Loading
Loading
Loading
Loading
+67 −100
Original line number Diff line number Diff line
@@ -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.
*/

 * Modifications:
 *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
/* 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)

#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
		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 irq routine
		.endm
		@@ exit here, Z flag unset if IRQ

	.endm

		/* currently don't need an disable_fiq macro */

		.macro	disable_fiq
		.endm