[ARM] pxa: move IRQ handling of GPIO 0 and 1 outside of gpio.c
authorEric Miao <eric.miao@marvell.com>
Tue, 6 Jan 2009 09:37:37 +0000 (17:37 +0800)
committerEric Miao <eric.miao@marvell.com>
Mon, 9 Mar 2009 13:22:37 +0000 (21:22 +0800)
This is part of the work making gpio.c generic enough, the changes
include:

1. move IRQ handling of GPIO 0 and 1 outside (and back into irq.c)

2. pxa_init_gpio() accepts a range for muxed GPIO IRQs, and an IRQ
   number for the muxed GPIOs

3. __gpio_is_occupied() and __gpio_is_inverted() are made inline,
   and are moved into <mach/gpio.h> instead of generic gpio.c

Signed-off-by: Eric Miao <eric.miao@marvell.com>
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/gpio.c
arch/arm/mach-pxa/include/mach/gpio.h
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa3xx.c

index dc876a8e6668a048b1176ede5e4378ce86bd67b4..bc12c9421ceff138c6d28f1b3c43980da3640e11 100644 (file)
@@ -9,13 +9,11 @@
  * published by the Free Software Foundation.
  */
 
-typedef int (*set_wake_t)(unsigned int, unsigned int);
-
 struct sys_timer;
 
 extern struct sys_timer pxa_timer;
-extern void __init pxa_init_irq(int irq_nr, set_wake_t fn);
-extern void __init pxa_init_gpio(int gpio_nr, set_wake_t fn);
+extern void __init pxa_init_irq(int irq_nr,
+                               int (*set_wake)(unsigned int, unsigned int));
 extern void __init pxa25x_init_irq(void);
 extern void __init pxa27x_init_irq(void);
 extern void __init pxa3xx_init_irq(void);
index 5fec1e479cb30e5f757ec08364bf7dc345bae06c..198246019028db2c48c4fef78c40d984cbb06828 100644 (file)
@@ -45,18 +45,6 @@ struct pxa_gpio_chip {
 
 int pxa_last_gpio;
 
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static int __gpio_is_inverted(unsigned gpio)
-{
-       return cpu_is_pxa25x() && gpio > 85;
-}
-#else
-#define __gpio_is_inverted(gpio)       (0)
-#endif
-
 /*
  * Configure pins for GPIO or other functions
  */
@@ -185,6 +173,20 @@ static struct pxa_gpio_chip pxa_gpio_chip[] = {
 #endif
 };
 
+static void __init pxa_init_gpio_chip(int gpio_nr)
+{
+       int i, gpio;
+
+       /* add a GPIO chip for each register bank.
+        * the last PXA25x register only contains 21 GPIOs
+        */
+       for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) {
+               if (gpio + 32 > gpio_nr)
+                       pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio;
+               gpiochip_add(&pxa_gpio_chip[i].chip);
+       }
+}
+
 /*
  * PXA GPIO edge detection for IRQs:
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
@@ -195,27 +197,6 @@ static unsigned long GPIO_IRQ_rising_edge[4];
 static unsigned long GPIO_IRQ_falling_edge[4];
 static unsigned long GPIO_IRQ_mask[4];
 
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static int __gpio_is_occupied(unsigned gpio)
-{
-       if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
-               int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
-               int dir = GPDR(gpio) & GPIO_bit(gpio);
-
-               if (__gpio_is_inverted(gpio))
-                       return af != 1 || dir == 0;
-               else
-                       return af != 0 || dir != 0;
-       }
-
-       return 0;
-}
-
 static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
 {
        int gpio, idx;
@@ -261,33 +242,6 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
        return 0;
 }
 
-/*
- * GPIO IRQs must be acknowledged.  This is for GPIO 0 and 1.
- */
-
-static void pxa_ack_low_gpio(unsigned int irq)
-{
-       GEDR0 = (1 << (irq - IRQ_GPIO0));
-}
-
-static void pxa_mask_low_gpio(unsigned int irq)
-{
-       ICMR &= ~(1 << (irq - PXA_IRQ(0)));
-}
-
-static void pxa_unmask_low_gpio(unsigned int irq)
-{
-       ICMR |= 1 << (irq - PXA_IRQ(0));
-}
-
-static struct irq_chip pxa_low_gpio_chip = {
-       .name           = "GPIO-l",
-       .ack            = pxa_ack_low_gpio,
-       .mask           = pxa_mask_low_gpio,
-       .unmask         = pxa_unmask_low_gpio,
-       .set_type       = pxa_gpio_irq_type,
-};
-
 /*
  * Demux handler for GPIO>=2 edge detect interrupts
  */
@@ -352,48 +306,31 @@ static struct irq_chip pxa_muxed_gpio_chip = {
        .set_type       = pxa_gpio_irq_type,
 };
 
-void __init pxa_init_gpio(int gpio_nr, set_wake_t fn)
+void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
 {
-       int irq, i, gpio;
+       int irq, i;
 
-       pxa_last_gpio = gpio_nr - 1;
+       pxa_last_gpio = end;
 
        /* clear all GPIO edge detects */
-       for (i = 0; i < gpio_nr; i += 32) {
-               GFER(i) = 0;
-               GRER(i) = 0;
-               GEDR(i) = GEDR(i);
+       for (i = start; i <= end; i += 32) {
+               GFER(i) &= ~GPIO_IRQ_mask[i];
+               GRER(i) &= ~GPIO_IRQ_mask[i];
+               GEDR(i) = GPIO_IRQ_mask[i];
        }
 
-       /* GPIO 0 and 1 must have their mask bit always set */
-       GPIO_IRQ_mask[0] = 3;
-
-       for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
-               set_irq_chip(irq, &pxa_low_gpio_chip);
-               set_irq_handler(irq, handle_edge_irq);
-               set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-       }
-
-       for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) {
+       for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
                set_irq_chip(irq, &pxa_muxed_gpio_chip);
                set_irq_handler(irq, handle_edge_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
        }
 
        /* Install handler for GPIO>=2 edge detect interrupts */
-       set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
-
-       pxa_low_gpio_chip.set_wake = fn;
+       set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler);
        pxa_muxed_gpio_chip.set_wake = fn;
 
-       /* add a GPIO chip for each register bank.
-        * the last PXA25x register only contains 21 GPIOs
-        */
-       for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) {
-               if (gpio + 32 > gpio_nr)
-                       pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio;
-               gpiochip_add(&pxa_gpio_chip[i].chip);
-       }
+       /* Initialize GPIO chips */
+       pxa_init_gpio_chip(end + 1);
 }
 
 #ifdef CONFIG_PM
index 2c538d8c362d40bc00e0cc7760c00dffa4fa4b87..c7ac3d62d34d1a004449f3735ce2e25bf96bd770 100644 (file)
@@ -56,10 +56,44 @@ static inline void gpio_set_value(unsigned gpio, int value)
        }
 }
 
-#define gpio_cansleep __gpio_cansleep
-
+#define gpio_cansleep          __gpio_cansleep
 #define gpio_to_irq(gpio)      IRQ_GPIO(gpio)
 #define irq_to_gpio(irq)       IRQ_TO_GPIO(irq)
 
 
+#ifdef CONFIG_CPU_PXA26x
+/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
+ * as well as their Alternate Function value being '1' for GPIO in GAFRx.
+ */
+static inline int __gpio_is_inverted(unsigned gpio)
+{
+       return cpu_is_pxa25x() && gpio > 85;
+}
+#else
+static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
+#endif
+
+/*
+ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
+ * function of a GPIO, and GPDRx cannot be altered once configured. It
+ * is attributed as "occupied" here (I know this terminology isn't
+ * accurate, you are welcome to propose a better one :-)
+ */
+static inline int __gpio_is_occupied(unsigned gpio)
+{
+       if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
+               int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+               int dir = GPDR(gpio) & GPIO_bit(gpio);
+
+               if (__gpio_is_inverted(gpio))
+                       return af != 1 || dir == 0;
+               else
+                       return af != 0 || dir != 0;
+       } else
+               return GPDR(gpio) & GPIO_bit(gpio);
+}
+
+typedef int (*set_wake_t)(unsigned int irq, unsigned int on);
+
+extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
 #endif
index fa69c3a6a38e2f558ca2176fc271f5c031ad413f..d3d40a31f9da3cd41062e4b954504a5d69da846c 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <mach/pxa-regs.h>
+#include <mach/gpio.h>
 
 #include "generic.h"
 
@@ -51,6 +52,72 @@ static struct irq_chip pxa_internal_irq_chip = {
        .unmask         = pxa_unmask_irq,
 };
 
+/*
+ * GPIO IRQs for GPIO 0 and 1
+ */
+static int pxa_set_low_gpio_type(unsigned int irq, unsigned int type)
+{
+       int gpio = irq - IRQ_GPIO0;
+
+       if (__gpio_is_occupied(gpio)) {
+               pr_err("%s failed: GPIO is configured\n", __func__);
+               return -EINVAL;
+       }
+
+       if (type & IRQ_TYPE_EDGE_RISING)
+               GRER0 |= GPIO_bit(gpio);
+       else
+               GRER0 &= ~GPIO_bit(gpio);
+
+       if (type & IRQ_TYPE_EDGE_FALLING)
+               GFER0 |= GPIO_bit(gpio);
+       else
+               GFER0 &= ~GPIO_bit(gpio);
+
+       return 0;
+}
+
+static void pxa_ack_low_gpio(unsigned int irq)
+{
+       GEDR0 = (1 << (irq - IRQ_GPIO0));
+}
+
+static void pxa_mask_low_gpio(unsigned int irq)
+{
+       ICMR &= ~(1 << (irq - PXA_IRQ(0)));
+}
+
+static void pxa_unmask_low_gpio(unsigned int irq)
+{
+       ICMR |= 1 << (irq - PXA_IRQ(0));
+}
+
+static struct irq_chip pxa_low_gpio_chip = {
+       .name           = "GPIO-l",
+       .ack            = pxa_ack_low_gpio,
+       .mask           = pxa_mask_low_gpio,
+       .unmask         = pxa_unmask_low_gpio,
+       .set_type       = pxa_set_low_gpio_type,
+};
+
+static void __init pxa_init_low_gpio_irq(set_wake_t fn)
+{
+       int irq;
+
+       /* clear edge detection on GPIO 0 and 1 */
+       GFER0 &= ~0x3;
+       GRER0 &= ~0x3;
+       GEDR0 = 0x3;
+
+       for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
+               set_irq_chip(irq, &pxa_low_gpio_chip);
+               set_irq_handler(irq, handle_edge_irq);
+               set_irq_flags(irq, IRQF_VALID);
+       }
+
+       pxa_low_gpio_chip.set_wake = fn;
+}
+
 void __init pxa_init_irq(int irq_nr, set_wake_t fn)
 {
        int irq;
@@ -72,6 +139,7 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn)
        }
 
        pxa_internal_irq_chip.set_wake = fn;
+       pxa_init_low_gpio_irq(fn);
 }
 
 #ifdef CONFIG_PM
index 2332e2dc35040778a9abe36f5fce441df58c2cce..77c2693cfeef4c811ea553322a32a3e4086245ea 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/gpio.h>
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/pm.h>
@@ -308,14 +309,14 @@ set_pwer:
 void __init pxa25x_init_irq(void)
 {
        pxa_init_irq(32, pxa25x_set_wake);
-       pxa_init_gpio(85, pxa25x_set_wake);
+       pxa_init_gpio(IRQ_GPIO_2_x, 2, 84, pxa25x_set_wake);
 }
 
 #ifdef CONFIG_CPU_PXA26x
 void __init pxa26x_init_irq(void)
 {
        pxa_init_irq(32, pxa25x_set_wake);
-       pxa_init_gpio(90, pxa25x_set_wake);
+       pxa_init_gpio(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake);
 }
 #endif
 
index c8b469bbcf3bc14f332c64a97f4d14e79b0bd085..a425ec71e657cb5bd9ed55beb228bf2523b2b653 100644 (file)
@@ -21,6 +21,7 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <mach/irqs.h>
+#include <mach/gpio.h>
 #include <mach/pxa27x.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
@@ -330,7 +331,7 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on)
 void __init pxa27x_init_irq(void)
 {
        pxa_init_irq(34, pxa27x_set_wake);
-       pxa_init_gpio(121, pxa27x_set_wake);
+       pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake);
 }
 
 /*
index e626b79cbee48d84b9b5779446432a8841605df7..b02d4544dc956d98b065760dbd6975208bc527b8 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sysdev.h>
 
 #include <mach/hardware.h>
+#include <mach/gpio.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
@@ -538,7 +539,7 @@ void __init pxa3xx_init_irq(void)
        __asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
 
        pxa_init_irq(56, pxa3xx_set_wake);
-       pxa_init_gpio(128, NULL);
+       pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
 /*