#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)
 {
 
 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
  *
 
--- /dev/null
+#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