[ARM] pxa: generalize the muxed gpio IRQ handling code with loop and ffs()
authoreric miao <eric.miao@marvell.com>
Tue, 4 Mar 2008 02:57:18 +0000 (10:57 +0800)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 19 Apr 2008 10:29:03 +0000 (11:29 +0100)
1. As David Brownell suggests, using ffs() is going to make the loop
   a bit faster (by avoiding unnecessary shift and iteration)

2. Russell suggested find_{first,next}_bit() being used with the
   gedr[] array

Signed-off-by: eric miao <eric.miao@marvell.com>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-pxa/irq.c

index 36c6a68beca26e1fa895d6ebb2373bd4bdd0eed6..381fde66aeeb54498d91d7b71eb0395746068e89 100644 (file)
@@ -178,73 +178,31 @@ static struct irq_chip pxa_low_gpio_chip = {
  * Demux handler for GPIO>=2 edge detect interrupts
  */
 
+#define GEDR_BITS      (sizeof(gedr) * BITS_PER_BYTE)
+
 static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
 {
-       unsigned int mask;
-       int loop;
+       int loop, bit, n;
+       unsigned long gedr[4];
 
        do {
-               loop = 0;
+               gedr[0] = GEDR0 & GPIO_IRQ_mask[0] & ~3;
+               gedr[1] = GEDR1 & GPIO_IRQ_mask[1];
+               gedr[2] = GEDR2 & GPIO_IRQ_mask[2];
+               gedr[3] = GEDR3 & GPIO_IRQ_mask[3];
 
-               mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
-               if (mask) {
-                       GEDR0 = mask;
-                       irq = IRQ_GPIO(2);
-                       desc = irq_desc + irq;
-                       mask >>= 2;
-                       do {
-                               if (mask & 1)
-                                       desc_handle_irq(irq, desc);
-                               irq++;
-                               desc++;
-                               mask >>= 1;
-                       } while (mask);
-                       loop = 1;
-               }
+               GEDR0 = gedr[0]; GEDR1 = gedr[1];
+               GEDR2 = gedr[2]; GEDR3 = gedr[3];
 
-               mask = GEDR1 & GPIO_IRQ_mask[1];
-               if (mask) {
-                       GEDR1 = mask;
-                       irq = IRQ_GPIO(32);
-                       desc = irq_desc + irq;
-                       do {
-                               if (mask & 1)
-                                       desc_handle_irq(irq, desc);
-                               irq++;
-                               desc++;
-                               mask >>= 1;
-                       } while (mask);
+               loop = 0;
+               bit = find_first_bit(gedr, GEDR_BITS);
+               while (bit < GEDR_BITS) {
                        loop = 1;
-               }
 
-               mask = GEDR2 & GPIO_IRQ_mask[2];
-               if (mask) {
-                       GEDR2 = mask;
-                       irq = IRQ_GPIO(64);
-                       desc = irq_desc + irq;
-                       do {
-                               if (mask & 1)
-                                       desc_handle_irq(irq, desc);
-                               irq++;
-                               desc++;
-                               mask >>= 1;
-                       } while (mask);
-                       loop = 1;
-               }
+                       n = PXA_GPIO_IRQ_BASE + bit;
+                       desc_handle_irq(n, irq_desc + n);
 
-               mask = GEDR3 & GPIO_IRQ_mask[3];
-               if (mask) {
-                       GEDR3 = mask;
-                       irq = IRQ_GPIO(96);
-                       desc = irq_desc + irq;
-                       do {
-                               if (mask & 1)
-                                       desc_handle_irq(irq, desc);
-                               irq++;
-                               desc++;
-                               mask >>= 1;
-                       } while (mask);
-                       loop = 1;
+                       bit = find_next_bit(gedr, GEDR_BITS, bit + 1);
                }
        } while (loop);
 }