linux-mips
[Top] [All Lists]

[PATCH v2] Alchemy: fix gpio_to_irq().

To: Linux-MIPS <linux-mips@linux-mips.org>
Subject: [PATCH v2] Alchemy: fix gpio_to_irq().
From: Manuel Lauss <mano@roarinelk.homelinux.net>
Date: Tue, 23 Dec 2008 20:59:24 +0100
Cc: Manuel Lauss <mano@roarinelk.homelinux.net>
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
It's not as easy as it is currently implemented:  Not all GPIOs are
irq-capable and every CPU model has them wired up differently.

Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net>
---
This update removes all but one EINVAL.

 arch/mips/alchemy/common/gpio.c          |   88 +++++++++++++++++++++++++++---
 arch/mips/include/asm/mach-au1x00/gpio.h |    7 ++-
 2 files changed, 84 insertions(+), 11 deletions(-)

diff --git a/arch/mips/alchemy/common/gpio.c b/arch/mips/alchemy/common/gpio.c
index e660ddd..7bac8f7 100644
--- a/arch/mips/alchemy/common/gpio.c
+++ b/arch/mips/alchemy/common/gpio.c
@@ -40,27 +40,27 @@ static struct au1x00_gpio2 *const gpio2 = (struct 
au1x00_gpio2 *) GPIO2_BASE;
 
 static int au1xxx_gpio2_read(unsigned gpio)
 {
-       gpio -= AU1XXX_GPIO_BASE;
+       gpio -= AU1XXX_GPIO2_BASE;
        return ((gpio2->pinstate >> gpio) & 0x01);
 }
 
 static void au1xxx_gpio2_write(unsigned gpio, int value)
 {
-       gpio -= AU1XXX_GPIO_BASE;
+       gpio -= AU1XXX_GPIO2_BASE;
 
        gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << 
gpio);
 }
 
 static int au1xxx_gpio2_direction_input(unsigned gpio)
 {
-       gpio -= AU1XXX_GPIO_BASE;
+       gpio -= AU1XXX_GPIO2_BASE;
        gpio2->dir &= ~(0x01 << gpio);
        return 0;
 }
 
 static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
 {
-       gpio -= AU1XXX_GPIO_BASE;
+       gpio -= AU1XXX_GPIO2_BASE;
        gpio2->dir |= 0x01 << gpio;
        gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << 
gpio);
        return 0;
@@ -97,7 +97,7 @@ static int au1xxx_gpio1_direction_output(unsigned gpio, int 
value)
 
 int au1xxx_gpio_get_value(unsigned gpio)
 {
-       if (gpio >= AU1XXX_GPIO_BASE)
+       if (gpio >= AU1XXX_GPIO2_BASE)
 #if defined(CONFIG_SOC_AU1000)
                return 0;
 #else
@@ -110,7 +110,7 @@ EXPORT_SYMBOL(au1xxx_gpio_get_value);
 
 void au1xxx_gpio_set_value(unsigned gpio, int value)
 {
-       if (gpio >= AU1XXX_GPIO_BASE)
+       if (gpio >= AU1XXX_GPIO2_BASE)
 #if defined(CONFIG_SOC_AU1000)
                ;
 #else
@@ -123,7 +123,7 @@ EXPORT_SYMBOL(au1xxx_gpio_set_value);
 
 int au1xxx_gpio_direction_input(unsigned gpio)
 {
-       if (gpio >= AU1XXX_GPIO_BASE)
+       if (gpio >= AU1XXX_GPIO2_BASE)
 #if defined(CONFIG_SOC_AU1000)
                return -ENODEV;
 #else
@@ -136,7 +136,7 @@ EXPORT_SYMBOL(au1xxx_gpio_direction_input);
 
 int au1xxx_gpio_direction_output(unsigned gpio, int value)
 {
-       if (gpio >= AU1XXX_GPIO_BASE)
+       if (gpio >= AU1XXX_GPIO2_BASE)
 #if defined(CONFIG_SOC_AU1000)
                return -ENODEV;
 #else
@@ -146,3 +146,75 @@ int au1xxx_gpio_direction_output(unsigned gpio, int value)
        return au1xxx_gpio1_direction_output(gpio, value);
 }
 EXPORT_SYMBOL(au1xxx_gpio_direction_output);
+
+#define GPIO2(x)               (AU1XXX_GPIO2_BASE + (x))
+#define MAKE_IRQ(intc, off)    (AU1000_INTC##intc##_INT_BASE + (off))
+#define MAKE_GPIO2_IRQ(intc, base, gpio)       \
+               MAKE_IRQ(intc, (base) + (gpio) - AU1XXX_GPIO2_BASE)
+
+int au1xxx_gpio_to_irq(unsigned int gpio)
+{
+#ifdef CONFIG_SOC_AU1000
+
+       if ((gpio >= 0) && (gpio <= 31))
+               return MAKE_IRQ(1, gpio);
+
+#elif defined(CONFIG_SOC_AU1100)
+
+       if (gpio >= AU1XXX_GPIO2_BASE) {
+               if ((gpio >= GPIO2(8)) && (gpio <= GPIO2(15)))
+                       return MAKE_IRQ(0, 29);
+       } else
+               return MAKE_IRQ(1, gpio);
+
+#elif defined(CONFIG_SOC_AU1500)
+
+       if (gpio >= AU1XXX_GPIO2_BASE) {
+               if ((gpio >= GPIO2(0)) && (gpio <= GPIO2(3)))
+                       return MAKE_GPIO2_IRQ(1, 16, gpio);
+               else if ((gpio >= GPIO2(4)) && (gpio <= GPIO2(5)))
+                       return MAKE_GPIO2_IRQ(1, 21, gpio - 4);
+               else if ((gpio >= GPIO2(6)) && (gpio <= GPIO2(7)))
+                       return MAKE_GPIO2_IRQ(1, 29, gpio - 6);
+       } else {
+               if (((gpio >= 0) && (gpio <= 15)) || (gpio == 20) ||
+                   ((gpio >= 23) && (gpio <= 28)))
+                       return MAKE_IRQ(1, gpio);
+       }
+
+#elif defined(CONFIG_SOC_AU1550)
+
+       if (gpio >= AU1XXX_GPIO2_BASE) {
+               if (gpio == GPIO2(0))
+                       return MAKE_IRQ(1, 16);
+               else if ((gpio >= GPIO2(1)) && (gpio <= GPIO2(5)))
+                       return MAKE_IRQ(1, 17);
+               else if ((gpio >= GPIO2(6)) && (gpio <= GPIO2(7)))
+                       return MAKE_GPIO2_IRQ(1, 29, gpio - 6);
+               else if ((gpio >= GPIO2(8)) && (gpio <= GPIO2(15)))
+                       return MAKE_IRQ(1, 31)
+       } else {
+               if (((gpio >= 0) && (gpio <= 15)) ||
+                   ((gpio >= 20) && (gpio <= 28)))
+                       return MAKE_IRQ(1, gpio);
+               else if ((gpio >= 16) && (gpio <= 17))
+                       return MAKE_IRQ(1, gpio + 2);
+       }
+
+#elif defined(CONFIG_SOC_AU1200)
+
+       if (gpio >= AU1XXX_GPIO2_BASE) {
+               if ((gpio >= GPIO2(0)) && (gpio <= GPIO2(2)))
+                       return MAKE_GPIO2_IRQ(0, 5, gpio);
+               else if (gpio == GPIO2(3))
+                       return MAKE_IRQ(0, 22);
+               else if ((gpio >= GPIO2(4)) && (gpio <= GPIO2(7)))
+                       return MAKE_GPIO2_IRQ(0, 24, gpio - 4);
+               else if ((gpio >= GPIO2(8)) && (gpio <= GPIO2(15)))
+                       return MAKE_IRQ(0, 28);
+       } else
+               return MAKE_IRQ(1, gpio);
+#endif
+       return -EINVAL;
+}
+EXPORT_SYMBOL(au1xxx_gpio_to_irq);
diff --git a/arch/mips/include/asm/mach-au1x00/gpio.h 
b/arch/mips/include/asm/mach-au1x00/gpio.h
index 2dc61e0..08060ab 100644
--- a/arch/mips/include/asm/mach-au1x00/gpio.h
+++ b/arch/mips/include/asm/mach-au1x00/gpio.h
@@ -3,7 +3,7 @@
 
 #include <linux/types.h>
 
-#define AU1XXX_GPIO_BASE       200
+#define AU1XXX_GPIO2_BASE      200
 
 struct au1x00_gpio2 {
        u32     dir;
@@ -18,6 +18,7 @@ extern int au1xxx_gpio_get_value(unsigned gpio);
 extern void au1xxx_gpio_set_value(unsigned gpio, int value);
 extern int au1xxx_gpio_direction_input(unsigned gpio);
 extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
+extern int au1xxx_gpio_to_irq(unsigned int gpio);
 
 
 /* Wrappers for the arch-neutral GPIO API */
@@ -55,12 +56,12 @@ static inline void gpio_set_value(unsigned gpio, int value)
 
 static inline int gpio_to_irq(unsigned gpio)
 {
-       return gpio;
+       return au1xxx_gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned irq)
 {
-       return irq;
+       return -EINVAL;
 }
 
 /* For cansleep */
-- 
1.6.0.4


<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH v2] Alchemy: fix gpio_to_irq()., Manuel Lauss <=