Subject: [@num@/@total@] i.MX2 family: Add GPIO handling support
From: Juergen Beisert <j.beisert@pengutronix.de>

This patch adds GPIO handling support for the mx2 family of procesors.

Things happend since last review:
 - ran checkpatch on it

TODO:
 - get a sign from freescale for the patch

Signed-off-by: Juergen Beisert <j.beisert@pengutronix.de>

---
 arch/arm/mach-mx2/gpio_mux.c         |  265 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-mx2/gpio_mux.h         |   52 ++++++
 include/asm-arm/arch-mxc/gpio.h      |   77 ++++++++++
 include/asm-arm/arch-mxc/mx27_pins.h |  222 +++++++++++++++++++++++++++++
 4 files changed, 616 insertions(+)

Index: include/asm-arm/arch-mxc/mx27_pins.h
===================================================================
--- /dev/null
+++ include/asm-arm/arch-mxc/mx27_pins.h
@@ -0,0 +1,222 @@
+/*
+ * linux/arch/arm/mach-mx2/gpio.c
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_MX27_PINS_H__
+#define __ASM_ARCH_MXC_MX27_PINS_H__
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Starting bit position within each entry of iomux_pins to represent the
+ * gpio port number (0-based) for that pin. For non-gpio pins, the bits will
+ * be all 1's for error checking in the functions. (gpio port 7 is invalid)
+ */
+#define MUX_IO_P	29
+
+/*
+ * Starting bit position within each entry of iomux_pins to represent the
+ * gpio offset bit (0-based) for that pin. For non-gpio pins, the bits will
+ * be all 0's since they are don't cares. So for port 2 pin 21, bit 31-24
+ * will be (1 << MUX_IO_P) | (21 << MUX_IO_I).
+ */
+#define MUX_IO_I	24
+
+#define _MX27_BUILD_PIN(gp, gi) (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I))
+
+enum iomux_pins {
+	MX27_PIN_USBH2_CLK = _MX27_BUILD_PIN(0, 0),
+	MX27_PIN_USBH2_DIR = _MX27_BUILD_PIN(0, 1),
+	MX27_PIN_USBH2_DATA7 = _MX27_BUILD_PIN(0, 2),
+	MX27_PIN_USBH2_NXT = _MX27_BUILD_PIN(0, 3),
+	MX27_PIN_USBH2_STP = _MX27_BUILD_PIN(0, 4),
+	MX27_PIN_LSCLK = _MX27_BUILD_PIN(0, 5),
+	MX27_PIN_LD0 = _MX27_BUILD_PIN(0, 6),
+	MX27_PIN_LD1 = _MX27_BUILD_PIN(0, 7),
+	MX27_PIN_LD2 = _MX27_BUILD_PIN(0, 8),
+	MX27_PIN_LD3 = _MX27_BUILD_PIN(0, 9),
+	MX27_PIN_LD4 = _MX27_BUILD_PIN(0, 10),
+	MX27_PIN_LD5 = _MX27_BUILD_PIN(0, 11),
+	MX27_PIN_LD6 = _MX27_BUILD_PIN(0, 12),
+	MX27_PIN_LD7 = _MX27_BUILD_PIN(0, 13),
+	MX27_PIN_LD8 = _MX27_BUILD_PIN(0, 14),
+	MX27_PIN_LD9 = _MX27_BUILD_PIN(0, 15),
+	MX27_PIN_LD10 = _MX27_BUILD_PIN(0, 16),
+	MX27_PIN_LD11 = _MX27_BUILD_PIN(0, 17),
+	MX27_PIN_LD12 = _MX27_BUILD_PIN(0, 18),
+	MX27_PIN_LD13 = _MX27_BUILD_PIN(0, 19),
+	MX27_PIN_LD14 = _MX27_BUILD_PIN(0, 20),
+	MX27_PIN_LD15 = _MX27_BUILD_PIN(0, 21),
+	MX27_PIN_LD16 = _MX27_BUILD_PIN(0, 22),
+	MX27_PIN_LD17 = _MX27_BUILD_PIN(0, 23),
+	MX27_PIN_REV = _MX27_BUILD_PIN(0, 24),
+	MX27_PIN_CLS = _MX27_BUILD_PIN(0, 25),
+	MX27_PIN_PS = _MX27_BUILD_PIN(0, 26),
+	MX27_PIN_SPL_SPR = _MX27_BUILD_PIN(0, 27),
+	MX27_PIN_HSYNC = _MX27_BUILD_PIN(0, 28),
+	MX27_PIN_VSYNC = _MX27_BUILD_PIN(0, 29),
+	MX27_PIN_CONTRAST = _MX27_BUILD_PIN(0, 30),
+	MX27_PIN_OE_ACD = _MX27_BUILD_PIN(0, 31),
+
+	MX27_PIN_SD2_D0 = _MX27_BUILD_PIN(1, 4),
+	MX27_PIN_SD2_D1 = _MX27_BUILD_PIN(1, 5),
+	MX27_PIN_SD2_D2 = _MX27_BUILD_PIN(1, 6),
+	MX27_PIN_SD2_D3 = _MX27_BUILD_PIN(1, 7),
+	MX27_PIN_SD2_CMD = _MX27_BUILD_PIN(1, 8),
+	MX27_PIN_SD2_CLK = _MX27_BUILD_PIN(1, 9),
+	MX27_PIN_CSI_D0 = _MX27_BUILD_PIN(1, 10),
+	MX27_PIN_CSI_D1 = _MX27_BUILD_PIN(1, 11),
+	MX27_PIN_CSI_D2 = _MX27_BUILD_PIN(1, 12),
+	MX27_PIN_CSI_D3 = _MX27_BUILD_PIN(1, 13),
+	MX27_PIN_CSI_D4 = _MX27_BUILD_PIN(1, 14),
+	MX27_PIN_CSI_MCLK = _MX27_BUILD_PIN(1, 15),
+	MX27_PIN_CSI_PIXCLK = _MX27_BUILD_PIN(1, 16),
+	MX27_PIN_CSI_D5 = _MX27_BUILD_PIN(1, 17),
+	MX27_PIN_CSI_D6 = _MX27_BUILD_PIN(1, 18),
+	MX27_PIN_CSI_D7 = _MX27_BUILD_PIN(1, 19),
+	MX27_PIN_CSI_VSYNC = _MX27_BUILD_PIN(1, 20),
+	MX27_PIN_CSI_HSYNC = _MX27_BUILD_PIN(1, 21),
+	MX27_PIN_USBH1_SUSP = _MX27_BUILD_PIN(1, 22),
+	MX27_PIN_USB_PWR = _MX27_BUILD_PIN(1, 23),
+	MX27_PIN_USB_OC_B = _MX27_BUILD_PIN(1, 24),
+	MX27_PIN_USBH1_RCV = _MX27_BUILD_PIN(1, 25),
+	MX27_PIN_USBH1_FS = _MX27_BUILD_PIN(1, 26),
+	MX27_PIN_USBH1_OE_B = _MX27_BUILD_PIN(1, 27),
+	MX27_PIN_USBH1_TXDM = _MX27_BUILD_PIN(1, 28),
+	MX27_PIN_USBH1_TXDP = _MX27_BUILD_PIN(1, 29),
+	MX27_PIN_USBH1_RXDM = _MX27_BUILD_PIN(1, 30),
+	MX27_PIN_USBH1_RXDP = _MX27_BUILD_PIN(1, 31),
+
+	MX27_PIN_I2C2_SDA = _MX27_BUILD_PIN(2, 5),
+	MX27_PIN_I2C2_SCL = _MX27_BUILD_PIN(2, 6),
+	MX27_PIN_USBOTG_DATA5 = _MX27_BUILD_PIN(2, 7),
+	MX27_PIN_USBOTG_DATA6 = _MX27_BUILD_PIN(2, 8),
+	MX27_PIN_USBOTG_DATA0 = _MX27_BUILD_PIN(2, 9),
+	MX27_PIN_USBOTG_DATA2 = _MX27_BUILD_PIN(2, 10),
+	MX27_PIN_USBOTG_DATA1 = _MX27_BUILD_PIN(2, 11),
+	MX27_PIN_USBOTG_DATA4 = _MX27_BUILD_PIN(2, 12),
+	MX27_PIN_USBOTG_DATA3 = _MX27_BUILD_PIN(2, 13),
+	MX27_PIN_TOUT = _MX27_BUILD_PIN(2, 14),
+	MX27_PIN_TIN = _MX27_BUILD_PIN(2, 15),
+	MX27_PIN_SSI4_FS = _MX27_BUILD_PIN(2, 16),
+	MX27_PIN_SSI4_RXDAT = _MX27_BUILD_PIN(2, 17),
+	MX27_PIN_SSI4_TXDAT = _MX27_BUILD_PIN(2, 18),
+	MX27_PIN_SSI4_CLK = _MX27_BUILD_PIN(2, 19),
+	MX27_PIN_SSI1_FS = _MX27_BUILD_PIN(2, 20),
+	MX27_PIN_SSI1_RXDAT = _MX27_BUILD_PIN(2, 21),
+	MX27_PIN_SSI1_TXDAT = _MX27_BUILD_PIN(2, 22),
+	MX27_PIN_SSI1_CLK = _MX27_BUILD_PIN(2, 23),
+	MX27_PIN_SSI2_FS = _MX27_BUILD_PIN(2, 24),
+	MX27_PIN_SSI2_RXDAT = _MX27_BUILD_PIN(2, 25),
+	MX27_PIN_SSI2_TXDAT = _MX27_BUILD_PIN(2, 26),
+	MX27_PIN_SSI2_CLK = _MX27_BUILD_PIN(2, 27),
+	MX27_PIN_SSI3_FS = _MX27_BUILD_PIN(2, 28),
+	MX27_PIN_SSI3_RXDAT = _MX27_BUILD_PIN(2, 29),
+	MX27_PIN_SSI3_TXDAT = _MX27_BUILD_PIN(2, 30),
+	MX27_PIN_SSI3_CLK = _MX27_BUILD_PIN(2, 31),
+
+	MX27_PIN_SD3_CMD = _MX27_BUILD_PIN(3, 0),
+	MX27_PIN_SD3_CLK = _MX27_BUILD_PIN(3, 1),
+	MX27_PIN_ATA_DATA0 = _MX27_BUILD_PIN(3, 2),
+	MX27_PIN_ATA_DATA1 = _MX27_BUILD_PIN(3, 3),
+	MX27_PIN_ATA_DATA2 = _MX27_BUILD_PIN(3, 4),
+	MX27_PIN_ATA_DATA3 = _MX27_BUILD_PIN(3, 5),
+	MX27_PIN_ATA_DATA4 = _MX27_BUILD_PIN(3, 6),
+	MX27_PIN_ATA_DATA5 = _MX27_BUILD_PIN(3, 7),
+	MX27_PIN_ATA_DATA6 = _MX27_BUILD_PIN(3, 8),
+	MX27_PIN_ATA_DATA7 = _MX27_BUILD_PIN(3, 9),
+	MX27_PIN_ATA_DATA8 = _MX27_BUILD_PIN(3, 10),
+	MX27_PIN_ATA_DATA9 = _MX27_BUILD_PIN(3, 11),
+	MX27_PIN_ATA_DATA10 = _MX27_BUILD_PIN(3, 12),
+	MX27_PIN_ATA_DATA11 = _MX27_BUILD_PIN(3, 13),
+	MX27_PIN_ATA_DATA12 = _MX27_BUILD_PIN(3, 14),
+	MX27_PIN_ATA_DATA13 = _MX27_BUILD_PIN(3, 15),
+	MX27_PIN_ATA_DATA14 = _MX27_BUILD_PIN(3, 16),
+	MX27_PIN_I2C_DATA = _MX27_BUILD_PIN(3, 17),
+	MX27_PIN_I2C_CLK = _MX27_BUILD_PIN(3, 18),
+	MX27_PIN_CSPI2_SS2 = _MX27_BUILD_PIN(3, 19),
+	MX27_PIN_CSPI2_SS1 = _MX27_BUILD_PIN(3, 20),
+	MX27_PIN_CSPI2_SS0 = _MX27_BUILD_PIN(3, 21),
+	MX27_PIN_CSPI2_SCLK = _MX27_BUILD_PIN(3, 22),
+	MX27_PIN_CSPI2_MISO = _MX27_BUILD_PIN(3, 23),
+	MX27_PIN_CSPI2_MOSI = _MX27_BUILD_PIN(3, 24),
+	MX27_PIN_CSPI1_RDY = _MX27_BUILD_PIN(3, 25),
+	MX27_PIN_CSPI1_SS2 = _MX27_BUILD_PIN(3, 26),
+	MX27_PIN_CSPI1_SS1 = _MX27_BUILD_PIN(3, 27),
+	MX27_PIN_CSPI1_SS0 = _MX27_BUILD_PIN(3, 28),
+	MX27_PIN_CSPI1_SCLK = _MX27_BUILD_PIN(3, 29),
+	MX27_PIN_CSPI1_MISO = _MX27_BUILD_PIN(3, 30),
+	MX27_PIN_CSPI1_MOSI = _MX27_BUILD_PIN(3, 31),
+
+	MX27_PIN_USBOTG_NXT = _MX27_BUILD_PIN(4, 0),
+	MX27_PIN_USBOTG_STP = _MX27_BUILD_PIN(4, 1),
+	MX27_PIN_USBOTG_DIR = _MX27_BUILD_PIN(4, 2),
+	MX27_PIN_UART2_CTS = _MX27_BUILD_PIN(4, 3),
+	MX27_PIN_UART2_RTS = _MX27_BUILD_PIN(4, 4),
+	MX27_PIN_PWMO = _MX27_BUILD_PIN(4, 5),
+	MX27_PIN_UART2_TXD = _MX27_BUILD_PIN(4, 6),
+	MX27_PIN_UART2_RXD = _MX27_BUILD_PIN(4, 7),
+	MX27_PIN_UART3_TXD = _MX27_BUILD_PIN(4, 8),
+	MX27_PIN_UART3_RXD = _MX27_BUILD_PIN(4, 9),
+	MX27_PIN_UART3_CTS = _MX27_BUILD_PIN(4, 10),
+	MX27_PIN_UART3_RTS = _MX27_BUILD_PIN(4, 11),
+	MX27_PIN_UART1_TXD = _MX27_BUILD_PIN(4, 12),
+	MX27_PIN_UART1_RXD = _MX27_BUILD_PIN(4, 13),
+	MX27_PIN_UART1_CTS = _MX27_BUILD_PIN(4, 14),
+	MX27_PIN_UART1_RTS = _MX27_BUILD_PIN(4, 15),
+	MX27_PIN_RTCK = _MX27_BUILD_PIN(4, 16),
+	MX27_PIN_RESET_OUT_B = _MX27_BUILD_PIN(4, 17),
+	MX27_PIN_SD1_D0 = _MX27_BUILD_PIN(4, 18),
+	MX27_PIN_SD1_D1 = _MX27_BUILD_PIN(4, 19),
+	MX27_PIN_SD1_D2 = _MX27_BUILD_PIN(4, 20),
+	MX27_PIN_SD1_D3 = _MX27_BUILD_PIN(4, 21),
+	MX27_PIN_SD1_CMD = _MX27_BUILD_PIN(4, 22),
+	MX27_PIN_SD1_CLK = _MX27_BUILD_PIN(4, 23),
+	MX27_PIN_USBOTG_CLK = _MX27_BUILD_PIN(4, 24),
+	MX27_PIN_USBOTG_DATA7 = _MX27_BUILD_PIN(4, 25),
+
+	MX27_PIN_NFRB = _MX27_BUILD_PIN(5, 0),
+	MX27_PIN_NFCLE = _MX27_BUILD_PIN(5, 1),
+	MX27_PIN_NFWP_B = _MX27_BUILD_PIN(5, 2),
+	MX27_PIN_NFCE_B = _MX27_BUILD_PIN(5, 3),
+	MX27_PIN_NFALE = _MX27_BUILD_PIN(5, 4),
+	MX27_PIN_NFRE_B = _MX27_BUILD_PIN(5, 5),
+	MX27_PIN_NFWE_B = _MX27_BUILD_PIN(5, 6),
+	MX27_PIN_PC_POE = _MX27_BUILD_PIN(5, 7),
+	MX27_PIN_PC_RW_B = _MX27_BUILD_PIN(5, 8),
+	MX27_PIN_IOIS16 = _MX27_BUILD_PIN(5, 9),
+	MX27_PIN_PC_RST = _MX27_BUILD_PIN(5, 10),
+	MX27_PIN_PC_BVD2 = _MX27_BUILD_PIN(5, 11),
+	MX27_PIN_PC_BVD1 = _MX27_BUILD_PIN(5, 12),
+	MX27_PIN_PC_VS2 = _MX27_BUILD_PIN(5, 13),
+	MX27_PIN_PC_VS1 = _MX27_BUILD_PIN(5, 14),
+	MX27_PIN_CLKO = _MX27_BUILD_PIN(5, 15),
+	MX27_PIN_PC_PWRON = _MX27_BUILD_PIN(5, 16),
+	MX27_PIN_PC_READY = _MX27_BUILD_PIN(5, 17),
+	MX27_PIN_PC_WAIT_B = _MX27_BUILD_PIN(5, 18),
+	MX27_PIN_PC_CD2_B = _MX27_BUILD_PIN(5, 19),
+	MX27_PIN_PC_CD1_B = _MX27_BUILD_PIN(5, 20),
+	MX27_PIN_CS4_B = _MX27_BUILD_PIN(5, 21),
+	MX27_PIN_CS5_B = _MX27_BUILD_PIN(5, 22),
+	MX27_PIN_ATA_DATA15 = _MX27_BUILD_PIN(5, 23),
+};
+
+#endif	/* __ASSEMBLY__ */
+#endif	/* __ASM_ARCH_MXC_MX27_PINS_H__ */
Index: arch/arm/mach-mx2/gpio_mux.c
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/gpio_mux.c
@@ -0,0 +1,265 @@
+/*
+ * linux/arch/arm/mach-mx2/gpio_mux.c
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/cache.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/gpio.h>
+#include "gpio_mux.h"
+
+/* This structure defines the offset of registers in gpio module */
+enum gpio_reg {
+	GPIO_GIUS = 0x20,
+	GPIO_GPR = 0x38,
+	GPIO_PUEN = 0x40,
+	GPIO_DDIR = 0x00,
+	GPIO_OCR1 = 0x04,
+	GPIO_OCR2 = 0x08,
+	GPIO_ICONFA1 = 0x0C,
+	GPIO_ICONFA2 = 0x10,
+	GPIO_ICONFB1 = 0x14,
+	GPIO_ICONFB2 = 0x18,
+};
+
+/* This enumeration data type defines the configuration for input mode */
+enum gpio_input_cfg {
+	GPIO_INPUT_GPIO = 0x00,
+	GPIO_INPUT_INTR = 0x01,
+	GPIO_INPUT_LOW = 0x02,
+	GPIO_INPUT_HIGH = 0x03
+};
+
+/* This enumeration data type defines the configuration for output mode */
+enum gpio_output_cfg {
+	GPIO_OUTPUT_A = 0x00,
+	GPIO_OUTPUT_B = 0x01,
+	GPIO_OUTPUT_C = 0x02,
+	GPIO_OUTPUT_DR = 0x03
+};
+
+extern struct mxc_gpio_port mxc_gpio_ports[];
+
+/* protect gpio pin configuration accesses */
+DEFINE_SPINLOCK(gpio_mux_lock);
+
+/* Enable or disable the pullup feature to the pin */
+static inline void _gpio_set_puen(struct mxc_gpio_port *port, u32 index,
+					bool en)
+{
+	u32 reg;
+
+	reg = __raw_readl(port->base + GPIO_PUEN);
+	if (en)
+		reg |= 1 << index;
+	else
+		reg &= ~(1 << index);
+	__raw_writel(reg, port->base + GPIO_PUEN);
+}
+
+/* Set the input configuration A */
+static inline void _gpio_set_iconfa(struct mxc_gpio_port *port, u32 index,
+				    enum gpio_input_cfg config)
+{
+	u32 reg, val;
+	u32 mask;
+
+	mask = 0x3 << ((index % 16) << 1);
+
+	if (index >= 16) {
+		reg = port->base + GPIO_ICONFA2;
+		val = config << ((index - 16) * 2);
+	} else {
+		reg = port->base + GPIO_ICONFA1;
+		val = config << (index * 2);
+	}
+	val |= __raw_readl(reg) & ~(mask);
+	__raw_writel(val, reg);
+}
+
+/* Set the input configuration B */
+static inline void _gpio_set_iconfb(struct mxc_gpio_port *port, u32 index,
+				    enum gpio_input_cfg config)
+{
+	u32 reg, val;
+	u32 mask;
+
+	mask = 0x3 << ((index % 16) << 1);
+
+	if (index >= 16) {
+		reg = port->base + GPIO_ICONFB2;
+		val = config << ((index - 16) * 2);
+	} else {
+		reg = port->base + GPIO_ICONFB1;
+		val = config << (index * 2);
+	}
+	val |= __raw_readl(reg) & (~mask);
+	__raw_writel(val, reg);
+}
+
+/* Set the output configuration */
+static inline void _gpio_set_ocr(struct mxc_gpio_port *port, u32 index,
+				 enum gpio_output_cfg config)
+{
+	u32 reg, val;
+	u32 mask;
+
+	mask = 0x3 << ((index % 16) << 1);
+	if (index >= 16) {
+		reg = port->base + GPIO_OCR2;
+		val = config << ((index - 16) * 2);
+	} else {
+		reg = port->base + GPIO_OCR1;
+		val = config << (index * 2);
+	}
+	val |= __raw_readl(reg) & (~mask);
+	__raw_writel(val, reg);
+}
+
+/**
+ * gpio_config_mux - just configure the mode of the gpio pin.
+ * @pin: A pin number as defined in enum iomux_pins
+ * @mode: A module as define in enum gpio_mux_mode;
+ *
+ * GPIO_MUX_PRIMARY set pin to work as primary function.
+ * GPIO_MUX_ALT set pin to work as alternate function.
+ * GPIO_MUX_GPIO set pin to work as output function based the data register
+ * GPIO_MUX_INPUT1 set pin to work as input function connected with  A_OUT
+ * GPIO_MUX_INPUT2 set pin to work as input function connected with B_OUT
+ * GPIO_MUX_OUTPUT1 set pin to work as output function connected with A_IN
+ * GPIO_MUX_OUTPUT2 set pin to work as output function connected with B_IN
+ * GPIO_MUX_OUTPUT3 set pin to work as output function connected with C_IN
+ */
+int gpio_config_mux(enum iomux_pins pin, enum gpio_mux_mode mode)
+{
+	unsigned long lock_flags;
+	u32 gius_reg, gpr_reg;
+	struct mxc_gpio_port *port;
+	u32 index, gpio = IOMUX_TO_GPIO(pin);
+
+	port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]);
+	index = GPIO_TO_INDEX(gpio);
+
+	pr_debug("%s: Configuring PORT %c, bit %d\n",
+		 __func__, port->num + 'A', index);
+
+	spin_lock_irqsave(&gpio_mux_lock, lock_flags);
+
+	gius_reg = __raw_readl(port->base + GPIO_GIUS);
+	gpr_reg = __raw_readl(port->base + GPIO_GPR);
+
+	switch (mode) {
+	case GPIO_MUX_PRIMARY:
+		gius_reg &= ~(1L << index);
+		gpr_reg &= ~(1L << index);
+		break;
+	case GPIO_MUX_ALT:
+		gius_reg &= ~(1L << index);
+		gpr_reg |= (1L << index);
+		break;
+	case GPIO_MUX_GPIO:
+		gius_reg |= (1L << index);
+		_gpio_set_ocr(port, index, GPIO_OUTPUT_DR);
+		break;
+	case GPIO_MUX_INPUT1:
+		gius_reg |= (1L << index);
+		_gpio_set_iconfa(port, index, GPIO_INPUT_GPIO);
+		break;
+	case GPIO_MUX_INPUT2:
+		gius_reg |= (1L << index);
+		_gpio_set_iconfb(port, index, GPIO_INPUT_GPIO);
+		break;
+	case GPIO_MUX_OUTPUT1:
+		gius_reg |= (1L << index);
+		_gpio_set_ocr(port, index, GPIO_OUTPUT_A);
+		break;
+	case GPIO_MUX_OUTPUT2:
+		gius_reg |= (1L << index);
+		_gpio_set_ocr(port, index, GPIO_OUTPUT_B);
+		break;
+	case GPIO_MUX_OUTPUT3:
+		gius_reg |= (1L << index);
+		_gpio_set_ocr(port, index, GPIO_OUTPUT_C);
+		break;
+	default:
+		spin_unlock_irqrestore(&gpio_mux_lock, lock_flags);
+		return -1;
+	}
+
+	__raw_writel(gius_reg, port->base + GPIO_GIUS);
+	__raw_writel(gpr_reg, port->base + GPIO_GPR);
+
+	spin_unlock_irqrestore(&gpio_mux_lock, lock_flags);
+	return 0;
+}
+
+/**
+ * gpio_set_puen - Enable or disable the pull up feature
+ * @pin: A pin number as defined in enum iomux_pins
+ * @en: 0 if disable, Non-zero enable
+ */
+int gpio_set_puen(enum iomux_pins pin, bool en)
+{
+	unsigned long lock_flags;
+
+	struct mxc_gpio_port *port;
+	u32 index, gpio = IOMUX_TO_GPIO(pin);
+
+	port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]);
+	index = GPIO_TO_INDEX(gpio);
+
+	pr_debug("%s: Configuring output mode of PORT %c, bit %d\n",
+		 __func__, port->num + 'A', index);
+
+	spin_lock_irqsave(&gpio_mux_lock, lock_flags);
+
+	_gpio_set_puen(port, index, en);
+	spin_unlock_irqrestore(&gpio_mux_lock, lock_flags);
+	return 0;
+
+}
+
+/**
+ * gpio_request_mux- Request a pin and configure it
+ * @pin: A pin number as defined in enum iomux_pins
+ * @mode: A module as define in enum gpio_mux_mode;
+ */
+int gpio_request_mux(enum iomux_pins pin, enum gpio_mux_mode mode)
+{
+	int ret;
+	ret = mxc_request_gpio(pin);
+	if (ret == 0) {
+		ret = gpio_config_mux(pin, mode);
+		if (ret)
+			mxc_free_gpio(pin);
+	}
+	return ret;
+}
+
+/**
+ * gpio_free_mux - Release a pin.
+ * @pin: A pin number as defined in enum iomux_pins
+ */
+void gpio_free_mux(enum iomux_pins pin)
+{
+	mxc_free_gpio(pin);
+}
Index: arch/arm/mach-mx2/gpio_mux.h
===================================================================
--- /dev/null
+++ arch/arm/mach-mx2/gpio_mux.h
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/arm/mach-mx2/gpio_mux.h
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARCH_ARM_MACH_MX2_GPIO_MUX_H__
+#define __ARCH_ARM_MACH_MX2_GPIO_MUX_H__
+
+/*
+ * This enumeration data type defines the modes of the pin.
+ *	GPIO_MUX_PRIMARY is the primary mode.
+ *	GPIO_MUX_ALT is the alternate mode.
+ *	GPIO_MUX_GPIO is the output mode and the signal source is data register.
+ *	GPIO_MUX_INPUT1 is the input mode and the signal destination is A_OUT.
+ *	GPIO_MUX_INPUT2 is the input mode and the signal destination is B_OUT.
+ *	GPIO_MUX_OUTPUT1 is the output mode and the signal destination is A_IN.
+ *	GPIO_MUX_OUTPUT2 is the output mode and the signal destination is B_IN.
+ *	GPIO_MUX_OUTPUT3 is the output mode and the signal destination is C_IN.
+ */
+enum gpio_mux_mode {
+	GPIO_MUX_PRIMARY,
+	GPIO_MUX_ALT,
+	GPIO_MUX_GPIO,
+	GPIO_MUX_INPUT1,
+	GPIO_MUX_INPUT2,
+	GPIO_MUX_OUTPUT1,
+	GPIO_MUX_OUTPUT2,
+	GPIO_MUX_OUTPUT3,
+};
+
+extern int gpio_request_mux(enum iomux_pins pin, enum gpio_mux_mode mode);
+extern int gpio_config_mux(enum iomux_pins pin, enum gpio_mux_mode mode);
+extern int gpio_set_puen(enum iomux_pins pin, bool en);
+extern void gpio_free_mux(enum iomux_pins pin);
+
+#endif /* __ARCH_ARM_MACH_MX2_GPIO_MUX_H__ */
Index: include/asm-arm/arch-mxc/gpio.h
===================================================================
--- /dev/null
+++ include/asm-arm/arch-mxc/gpio.h
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/arm/mach-mx2/gpio.c
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_GPIO_H__
+#define __ASM_ARCH_MXC_GPIO_H__
+
+#include <asm/sizes.h>
+#include <linux/interrupt.h>
+#include <asm/hardware.h>
+
+/* gpio related defines */
+
+/*
+ * There are two queues for registered GPIO ISRs. One is for high priority and
+ * the other is for low priority. The ISRs in the high priority queue will be
+ * called first before the low priority queue if more than one GPIO interrupt
+ * occurs at the same time.
+ */
+enum gpio_prio {
+	GPIO_HIGH_PRIO = 0,	/* high priority queue */
+	GPIO_LOW_PRIO		/* low priority queue */
+};
+
+/*
+ * This enumeration data type defines various different ways for interrupting
+ * the ARM core from GPIO signals. The way to interrupt the core is dictated
+ * by the external hardware.
+ */
+enum gpio_int_cfg {
+#if defined(CONFIG_ARCH_MX2)
+	GPIO_INT_LOW_LEV = 0x3,		/* low level sensitive */
+	GPIO_INT_HIGH_LEV = 0x2,	/* high level sensitive */
+	GPIO_INT_RISE_EDGE = 0x0,	/* rising edge sensitive */
+	GPIO_INT_FALL_EDGE = 0x1,	/* falling edge sensitive */
+	GPIO_INT_NONE = 0x4		/* No interrupt */
+#else
+	GPIO_INT_LOW_LEV = 0x0,		/* low level sensitive */
+	GPIO_INT_HIGH_LEV = 0x1,	/* high level sensitive */
+	GPIO_INT_RISE_EDGE = 0x2,	/* rising edge sensitive */
+	GPIO_INT_FALL_EDGE = 0x3,	/* falling edge sensitive */
+	GPIO_INT_NONE = 0x4		/* No interrupt */
+#endif
+};
+
+typedef irqreturn_t(*gpio_irq_handler) (int, void *);
+
+void gpio_config(__u32 port, __u32 sig_no, bool out, enum gpio_int_cfg icr);
+void gpio_set_data(__u32 port, __u32 sig_no, __u32 data);
+__u32 gpio_get_data(__u32 port, __u32 sig_no);
+int gpio_request_irq(__u32 port, __u32 sig_no, enum gpio_prio prio,
+		     gpio_irq_handler handler, __u32 irq_flags,
+		     const char *devname, void *dev_id);
+void gpio_free_irq(__u32 port, __u32 sig_no, enum gpio_prio prio);
+int mxc_request_gpio(enum iomux_pins pin);
+void mxc_set_gpio_direction(enum iomux_pins pin, int is_input);
+void mxc_set_gpio_dataout(enum iomux_pins pin, u32 data);
+int mxc_get_gpio_datain(enum iomux_pins pin);
+void mxc_free_gpio(enum iomux_pins pin);
+#endif	/* __ASM_ARCH_MXC_GPIO_H__ */
