]> git.hungrycats.org Git - linux/commitdiff
[ARM PATCH] 2129/1: S3C2410 - fix set_irq_type() for EINT0..EINT3
authorBen Dooks <ben-linux@org.rmk.(none)>
Wed, 6 Oct 2004 22:43:19 +0000 (23:43 +0100)
committerRussell King <rmk@flint.arm.linux.org.uk>
Wed, 6 Oct 2004 22:43:19 +0000 (23:43 +0100)
Patch from Ben Dooks

Fix the set_irq_type() for EINTs 0 through 3

Cleaned up the inital clearing of any pending IRQs

Signed-off-by: Klaus Fetscher
Signed-off-by: Ben Dooks
arch/arm/mach-s3c2410/irq.c

index 35f8072c034b639684f1e8c88c748ba45c38ca14..1951a0323f178b6a66effef6fedb80f93177588f 100644 (file)
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s3c2410/irq.c
  *
  * Copyright (c) 2003,2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ *     Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *
  *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
  *                Addition of ADC/TC demux
- */
+ *
+ *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
+ *               Fix for set_irq_type() on low EINT numbers
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *               Tidy up KF's patch and sort out new release
+*/
 
 
 #include <linux/init.h>
@@ -46,9 +52,6 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
-#if 0
-#include <asm/debug-ll.h>
-#endif
 
 #define irqdbf(x...)
 #define irqdbf2(x...)
@@ -195,13 +198,20 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
        unsigned long gpcon_offset, extint_offset;
        unsigned long newvalue = 0, value;
 
-       if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT7))
+       if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
        {
                gpcon_reg = S3C2410_GPFCON;
                extint_reg = S3C2410_EXTINT0;
                gpcon_offset = (irq - IRQ_EINT0) * 2;
                extint_offset = (irq - IRQ_EINT0) * 4;
        }
+       else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+       {
+               gpcon_reg = S3C2410_GPFCON;
+               extint_reg = S3C2410_EXTINT0;
+               gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+               extint_offset = (irq - (EXTINT_OFF)) * 4;
+       }
        else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
        {
                gpcon_reg = S3C2410_GPGCON;
@@ -269,6 +279,13 @@ static struct irqchip s3c_irqext_chip = {
        .type       = s3c_irqext_type
 };
 
+static struct irqchip s3c_irq_eint0t4 = {
+       .ack       = s3c_irq_ack,
+       .mask      = s3c_irq_mask,
+       .unmask    = s3c_irq_unmask,
+       .type      = s3c_irqext_type
+};
+
 /* mask values for the parent registers for each of the interrupt types */
 
 #define INTMSK_UART0    (1UL << (IRQ_UART0 - IRQ_EINT0))
@@ -549,6 +566,7 @@ s3c_irq_demux_uart2(unsigned int irq,
 void __init s3c2410_init_irq(void)
 {
        unsigned long pend;
+       unsigned long last;
        int irqno;
        int i;
 
@@ -556,48 +574,51 @@ void __init s3c2410_init_irq(void)
 
        /* first, clear all interrupts pending... */
 
+       last = 0;
        for (i = 0; i < 4; i++) {
                pend = __raw_readl(S3C2410_EINTPEND);
-               if (pend == 0)
+
+               if (pend == 0 || pend == last)
                        break;
+
                __raw_writel(pend, S3C2410_EINTPEND);
                printk("irq: clearing pending ext status %08x\n", (int)pend);
+               last = pend;
        }
 
+       last = 0;
        for (i = 0; i < 4; i++) {
                pend = __raw_readl(S3C2410_INTPND);
-               if (pend == 0)
+
+               if (pend == 0 || pend == last)
                        break;
+
                __raw_writel(pend, S3C2410_SRCPND);
                __raw_writel(pend, S3C2410_INTPND);
                printk("irq: clearing pending status %08x\n", (int)pend);
+               last = pend;
        }
 
+       last = 0;
        for (i = 0; i < 4; i++) {
                pend = __raw_readl(S3C2410_SUBSRCPND);
 
-               if (pend == 0)
+               if (pend == 0 || pend == last)
                        break;
 
                printk("irq: clearing subpending status %08x\n", (int)pend);
                __raw_writel(pend, S3C2410_SUBSRCPND);
+               last = pend;
        }
 
        /* register the main interrupts */
 
        irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
-       for (irqno = IRQ_EINT0; irqno <= IRQ_ADCPARENT; irqno++) {
+       for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
                /* set all the s3c2410 internal irqs */
 
                switch (irqno) {
-
-               case IRQ_EINT4t7:
-               case IRQ_EINT8t23:
-                       /* these are already dealt with, so should never
-                        * appear */
-                       break;
-
                        /* deal with the special IRQs (cascaded) */
 
                case IRQ_UART0:
@@ -632,6 +653,13 @@ void __init s3c2410_init_irq(void)
 
        /* external interrupts */
 
+       for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+               irqdbf("registering irq %d (ext int)\n", irqno);
+               set_irq_chip(irqno, &s3c_irq_eint0t4);
+               set_irq_handler(irqno, do_edge_IRQ);
+               set_irq_flags(irqno, IRQF_VALID);
+       }
+
        for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
                irqdbf("registering irq %d (extended s3c irq)\n", irqno);
                set_irq_chip(irqno, &s3c_irqext_chip);