Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b3e6a508ed920698d367e5993ed056d70364d91f
Commit:     b3e6a508ed920698d367e5993ed056d70364d91f
Parent:     7dcca30a32aadb0520417521b0c44f42d09fe05c
Author:     Pavel Pisa <[EMAIL PROTECTED]>
AuthorDate: Sat May 12 14:31:17 2007 +0100
Committer:  Russell King <[EMAIL PROTECTED]>
CommitDate: Thu Jul 12 11:11:39 2007 +0100

    [ARM] 4373/1: i.MX/MX1 GPIO support implementation
    
    Support for generic input output for MX1 family.
    The implementation prevents allocation of one pin
    by two users, but does not store pointer to the user
    description permanently, because this solution
    would have bigger memory overhead.
    
    The simple way to integrate code with per BSP
    pins setup and allocation is required else all GPIO
    registration checking is useless. The function
    imx_gpio_setup_multiple_pins() can be used for this
    purpose in future.
    
    Signed-off-by: Pavel Pisa <[EMAIL PROTECTED]>
    Signed-off-by: Russell King <[EMAIL PROTECTED]>
---
 arch/arm/Kconfig                    |    1 +
 arch/arm/mach-imx/generic.c         |  118 +++++++++++++++++++++++++++++++++++
 include/asm-arm/arch-imx/gpio.h     |  102 ++++++++++++++++++++++++++++++
 include/asm-arm/arch-imx/imx-regs.h |    2 +
 4 files changed, 223 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 50d9f3e..8b55395 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -241,6 +241,7 @@ config ARCH_H720X
 
 config ARCH_IMX
        bool "IMX"
+       select GENERIC_GPIO
        help
          Support for Motorola's i.MX family of processors (MX1, MXL).
 
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 1c474cf..a58b678 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -28,12 +28,16 @@
 #include <linux/module.h>
 #include <linux/string.h>
 
+#include <asm/errno.h>
 #include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -95,6 +99,120 @@ void imx_gpio_mode(int gpio_mode)
 
 EXPORT_SYMBOL(imx_gpio_mode);
 
+int imx_gpio_request(unsigned gpio, const char *label)
+{
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+               printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO 
%d for \"%s\"\n",
+                       gpio, label ? label : "?");
+               return -EINVAL;
+
+       if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
+               printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for 
\"%s\" failed\n",
+                       gpio, label ? label : "?");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_request);
+
+void imx_gpio_free(unsigned gpio)
+{
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+               return;
+
+       clear_bit(gpio, imx_gpio_alloc_map);
+}
+
+EXPORT_SYMBOL(imx_gpio_free);
+
+int imx_gpio_direction_input(unsigned gpio)
+{
+       imx_gpio_mode(gpio| GPIO_IN);
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_input);
+
+int imx_gpio_direction_output(unsigned gpio, int value)
+{
+       imx_gpio_set_value(gpio, value);
+       imx_gpio_mode(gpio| GPIO_OUT);
+       return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_output);
+
+int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+                               int alloc_mode, const char *label)
+{
+       const int *p = pin_list;
+       int i;
+       unsigned gpio;
+       unsigned mode;
+
+       for (i = 0; i < count; i++) {
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+               if (gpio >= (GPIO_PORT_MAX + 1) * 32)
+                       goto setup_error;
+
+               if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
+                       imx_gpio_free(gpio);
+               else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
+                       if (imx_gpio_request(gpio, label))
+                               if (!(alloc_mode & 
IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+                                       goto setup_error;
+
+               if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
+                                   IMX_GPIO_ALLOC_MODE_RELEASE)))
+                       imx_gpio_mode(gpio | mode);
+
+               p++;
+       }
+       return 0;
+
+setup_error:
+       if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
+                        IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+               return -EINVAL;
+
+       while (p != pin_list) {
+               p--;
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               imx_gpio_free(gpio);
+       }
+
+       return -EINVAL;
+}
+
+EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
+
+void __imx_gpio_set_value(unsigned gpio, int value)
+{
+       imx_gpio_set_value_inline(gpio, value);
+}
+
+EXPORT_SYMBOL(__imx_gpio_set_value);
+
+int imx_gpio_to_irq(unsigned gpio)
+{
+       return IRQ_GPIOA(0) + gpio;
+}
+
+EXPORT_SYMBOL(imx_gpio_to_irq);
+
+int imx_irq_to_gpio(unsigned irq)
+{
+       if (irq < IRQ_GPIOA(0))
+               return -EINVAL;
+       return irq - IRQ_GPIOA(0);
+}
+
+EXPORT_SYMBOL(imx_irq_to_gpio);
+
 /*
  *  get the system pll clock in Hz
  *
diff --git a/include/asm-arm/arch-imx/gpio.h b/include/asm-arm/arch-imx/gpio.h
new file mode 100644
index 0000000..4860232
--- /dev/null
+++ b/include/asm-arm/arch-imx/gpio.h
@@ -0,0 +1,102 @@
+#ifndef _IMX_GPIO_H
+
+#include <asm/arch/imx-regs.h>
+
+#define IMX_GPIO_ALLOC_MODE_NORMAL     0
+#define IMX_GPIO_ALLOC_MODE_NO_ALLOC   1
+#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC  2
+#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY 4
+#define IMX_GPIO_ALLOC_MODE_RELEASE    8
+
+extern int imx_gpio_request(unsigned gpio, const char *label);
+
+extern void imx_gpio_free(unsigned gpio);
+
+extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+                                       int alloc_mode, const char *label);
+
+extern int imx_gpio_direction_input(unsigned gpio);
+
+extern int imx_gpio_direction_output(unsigned gpio, int value);
+
+extern void __imx_gpio_set_value(unsigned gpio, int value);
+
+static inline int imx_gpio_get_value(unsigned gpio)
+{
+       return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK));
+}
+
+static inline void imx_gpio_set_value_inline(unsigned gpio, int value)
+{
+       unsigned long flags;
+
+       raw_local_irq_save(flags);
+       if(value)
+               DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK));
+       else
+               DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK));
+       raw_local_irq_restore(flags);
+}
+
+static inline void imx_gpio_set_value(unsigned gpio, int value)
+{
+       if(__builtin_constant_p(gpio))
+               imx_gpio_set_value_inline(gpio, value);
+       else
+               __imx_gpio_set_value(gpio, value);
+}
+
+extern int imx_gpio_to_irq(unsigned gpio);
+
+extern int imx_irq_to_gpio(unsigned irq);
+
+/*-------------------------------------------------------------------------*/
+
+/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions
+ * to allow future extension of GPIO logic.
+ */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+       return imx_gpio_request(gpio, label);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+       imx_gpio_free(gpio);
+}
+
+static inline  int gpio_direction_input(unsigned gpio)
+{
+       return imx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+       return imx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+       return imx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       imx_gpio_set_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h>          /* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return imx_gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       return imx_irq_to_gpio(irq);
+}
+
+
+#endif
diff --git a/include/asm-arm/arch-imx/imx-regs.h 
b/include/asm-arm/arch-imx/imx-regs.h
index 30de404..fb9de27 100644
--- a/include/asm-arm/arch-imx/imx-regs.h
+++ b/include/asm-arm/arch-imx/imx-regs.h
@@ -77,6 +77,8 @@
 #define SWR(x)     __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
 #define PUEN(x)    __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
 
+#define GPIO_PORT_MAX  3
+
 #define GPIO_PIN_MASK 0x1f
 #define GPIO_PORT_MASK (0x3 << 5)
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to