[PATCH 5/5] ARM: pxa: move gpio driver into drivers directory

Haojian Zhuang haojian.zhuang at marvell.com
Thu Sep 29 11:19:06 EDT 2011


Move gpio driver from plat-pxa to drivers/gpio directory. Only leave
gpio number macro in mach/gpio.h.

Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
---
 arch/arm/mach-mmp/Kconfig             |    3 +
 arch/arm/mach-mmp/Makefile            |    2 +-
 arch/arm/mach-mmp/aspenite.c          |    4 +-
 arch/arm/mach-mmp/flint.c             |    4 +-
 arch/arm/mach-mmp/gpio.c              |   89 ++++++
 arch/arm/mach-mmp/gplugd.c            |    2 +-
 arch/arm/mach-mmp/include/mach/gpio.h |   24 +--
 arch/arm/mach-mmp/include/mach/irqs.h |    4 +-
 arch/arm/mach-mmp/mmp2.c              |   17 --
 arch/arm/mach-mmp/pxa168.c            |   17 --
 arch/arm/mach-mmp/pxa910.c            |   17 --
 arch/arm/mach-mmp/tavorevb.c          |    4 +-
 arch/arm/mach-mmp/teton_bga.c         |    2 +-
 arch/arm/mach-mmp/ttc_dkb.c           |    2 +-
 arch/arm/mach-pxa/Kconfig             |    6 +
 arch/arm/mach-pxa/Makefile            |    2 +-
 arch/arm/mach-pxa/gpio.c              |   92 ++++++
 arch/arm/mach-pxa/include/mach/gpio.h |   64 -----
 arch/arm/mach-pxa/pxa25x.c            |    3 -
 arch/arm/mach-pxa/pxa27x.c            |    2 -
 arch/arm/mach-pxa/pxa3xx.c            |    2 -
 arch/arm/mach-pxa/pxa95x.c            |    2 -
 arch/arm/plat-pxa/Makefile            |    1 -
 arch/arm/plat-pxa/gpio.c              |  352 -----------------------
 arch/arm/plat-pxa/include/plat/gpio.h |   65 -----
 drivers/gpio/Kconfig                  |    6 +
 drivers/gpio/Makefile                 |    1 +
 drivers/gpio/gpio-pxa.c               |  500 +++++++++++++++++++++++++++++++++
 include/linux/gpio-pxa.h              |  105 +++++++
 29 files changed, 816 insertions(+), 578 deletions(-)
 create mode 100644 arch/arm/mach-mmp/gpio.c
 create mode 100644 arch/arm/mach-pxa/gpio.c
 delete mode 100644 arch/arm/plat-pxa/gpio.c
 delete mode 100644 arch/arm/plat-pxa/include/plat/gpio.h
 create mode 100644 drivers/gpio/gpio-pxa.c
 create mode 100644 include/linux/gpio-pxa.h

diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 56ef5f6..47810fb 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -89,18 +89,21 @@ endmenu
 config CPU_PXA168
 	bool
 	select CPU_MOHAWK
+	select GPIO_PXA
 	help
 	  Select code specific to PXA168
 
 config CPU_PXA910
 	bool
 	select CPU_MOHAWK
+	select GPIO_PXA
 	help
 	  Select code specific to PXA910
 
 config CPU_MMP2
 	bool
 	select CPU_PJ4
+	select GPIO_PXA
 	help
 	  Select code specific to MMP2. MMP2 is ARMv7 compatible.
 endif
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index b0ac942..5af46eb 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Marvell's PXA168 processors line
 #
 
-obj-y				+= common.o clock.o devices.o time.o
+obj-y				+= common.o clock.o devices.o time.o gpio.o
 
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 6b19812..88770cf 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -119,8 +119,8 @@ static struct resource smc91x_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= pxa_gpio_to_irq(27),
-		.end	= pxa_gpio_to_irq(27),
+		.start	= mmp_gpio_to_irq(27),
+		.end	= mmp_gpio_to_irq(27),
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
 	}
 };
diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c
index f466a2c..19dfdf5 100644
--- a/arch/arm/mach-mmp/flint.c
+++ b/arch/arm/mach-mmp/flint.c
@@ -87,8 +87,8 @@ static struct resource smc91x_resources[] = {
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start  = pxa_gpio_to_irq(155),
-		.end    = pxa_gpio_to_irq(155),
+		.start  = mmp_gpio_to_irq(155),
+		.end    = mmp_gpio_to_irq(155),
 		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
 	}
 };
diff --git a/arch/arm/mach-mmp/gpio.c b/arch/arm/mach-mmp/gpio.c
new file mode 100644
index 0000000..345341d5
--- /dev/null
+++ b/arch/arm/mach-mmp/gpio.c
@@ -0,0 +1,89 @@
+/*
+ *  linux/arch/arm/mach-mmp/gpio.c
+ *
+ *  MMP series specific gpio init
+ *
+ *  Copyright (C) 2011 Marvell International Ltd.
+ *
+ *  Author:
+ *  	Haojian Zhuang <haojian.zhuang at marvell.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/gpio-pxa.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <mach/cputype.h>
+#include <mach/irqs.h>
+#include <mach/regs-apbc.h>
+
+#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
+#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
+
+static struct __initdata pxa_gpio_platform_data mmp_gpio_config;
+
+static struct __initdata resource mmp_resources_gpio[] = {
+	{
+		.start	= 0xd4010000,
+		.end	= 0xd401ffff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_PXA168_GPIOX,
+		.end	= IRQ_PXA168_GPIOX,
+		.name	= "gpio_mux",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mmp_gpio = {
+	.name		= "pxa-gpio",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(mmp_resources_gpio),
+	.resource	= mmp_resources_gpio,
+};
+
+static int __init mmp_gpio_init(void)
+{
+	int size = sizeof(struct pxa_gpio_platform_data);
+	u32 reg_base = GPIO_REGS_VIRT;
+	int i;
+
+	if (cpu_is_pxa168() || cpu_is_pxa910()) {
+		/* enable GPIO clock */
+		__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO);
+		
+		/* unmask GPIO edge detection for all 4 banks - APMASKx */
+		for (i = 0; i < 4; i++)
+			__raw_writel(0xffffffff, APMASK(i));
+		mmp_gpio_config.gpio_type = MMP_GPIO;
+		mmp_gpio_config.gpio_end = 127;
+	} else if (cpu_is_mmp2()) {
+		/* enable GPIO clock */
+		__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO);
+		
+		/* unmask GPIO edge detection for all 6 banks -- APMASKx */
+		for (i = 0; i < 6; i++)
+			__raw_writel(0xffffffff, APMASK(i));
+		mmp_gpio_config.gpio_type = MMP2_GPIO;
+		mmp_gpio_config.gpio_end = 191;
+	} else
+		return 0;
+
+	pxa_gpio_regs.gplr = reg_base + GPLR_OFFSET;
+	pxa_gpio_regs.gpdr = reg_base + GPDR_OFFSET;
+	pxa_gpio_regs.gpsr = reg_base + GPSR_OFFSET;
+	pxa_gpio_regs.gpcr = reg_base + GPCR_OFFSET;
+	pxa_gpio_regs.grer = reg_base + GRER_OFFSET;
+	pxa_gpio_regs.gfer = reg_base + GFER_OFFSET;
+	pxa_gpio_regs.gedr = reg_base + GEDR_OFFSET;
+
+	platform_device_add_data(&mmp_gpio, &mmp_gpio_config, size);
+	platform_device_register(&mmp_gpio);
+	return 0;
+}
+postcore_initcall(mmp_gpio_init);
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index 98e25d9..32776f3 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -9,11 +9,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/gpio.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
 
diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h
index 89d499e..9a2f4e1 100644
--- a/arch/arm/mach-mmp/include/mach/gpio.h
+++ b/arch/arm/mach-mmp/include/mach/gpio.h
@@ -3,31 +3,9 @@
 
 #include <mach/addr-map.h>
 #include <mach/irqs.h>
-#include <asm-generic/gpio.h>
 
-#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
+#define GPIO_REGS_VIRT		(APB_VIRT_BASE + 0x19000)
 
 #define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
 
-#define gpio_to_bank(gpio)	((gpio) >> 5)
-
-#define __gpio_is_inverted(gpio)	(0)
-#define __gpio_is_occupied(gpio)	(0)
-
-/* NOTE: these macros are defined here to make optimization of
- * gpio_{get,set}_value() to work when 'gpio' is a constant.
- * Usage of these macros otherwise is no longer recommended,
- * use generic GPIO API whenever possible.
- */
-#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
-
-#include <plat/gpio.h>
 #endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index 2971a00..6a72198 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -220,8 +220,8 @@
 
 #define IRQ_GPIO_START			128
 #define IRQ_GPIO_NUM			192
-#define pxa_gpio_to_irq(gpio)		(IRQ_GPIO_START + (gpio))
-#define pxa_irq_to_gpio(irq)		((irq) - IRQ_GPIO_START)
+#define mmp_gpio_to_irq(gpio)		(IRQ_GPIO_START + (gpio))
+#define mmp_irq_to_gpio(irq)		((irq) - IRQ_GPIO_START)
 
 #define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
 
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 1935834..5d31333 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -33,8 +33,6 @@
 
 #define MFPR_VIRT_BASE	(APB_VIRT_BASE + 0x1e000)
 
-#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x9c)
-
 static struct mfp_addr_map mmp2_addr_map[] __initdata = {
 
 	MFP_ADDR_X(GPIO0, GPIO58, 0x54),
@@ -94,24 +92,9 @@ void mmp2_clear_pmic_int(void)
 	__raw_writel(data, mfpr_pmic);
 }
 
-static void __init mmp2_init_gpio(void)
-{
-	int i;
-
-	/* enable GPIO clock */
-	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO);
-
-	/* unmask GPIO edge detection for all 6 banks -- APMASKx */
-	for (i = 0; i < 6; i++)
-		__raw_writel(0xffffffff, APMASK(i));
-
-	pxa_init_gpio(IRQ_MMP2_GPIO, 0, 167, NULL);
-}
-
 void __init mmp2_init_irq(void)
 {
 	mmp2_init_icu();
-	mmp2_init_gpio();
 }
 
 static void sdhc_clk_enable(struct clk *clk)
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index e6f6789..630453a 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -43,26 +43,9 @@ static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata =
 	MFP_ADDR_END,
 };
 
-#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
-
-static void __init pxa168_init_gpio(void)
-{
-	int i;
-
-	/* enable GPIO clock */
-	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO);
-
-	/* unmask GPIO edge detection for all 4 banks - APMASKx */
-	for (i = 0; i < 4; i++)
-		__raw_writel(0xffffffff, APMASK(i));
-
-	pxa_init_gpio(IRQ_PXA168_GPIOX, 0, 127, NULL);
-}
-
 void __init pxa168_init_irq(void)
 {
 	icu_init_irq();
-	pxa168_init_gpio();
 }
 
 /* APB peripheral clocks */
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index c70b4dd..19ebfe3 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -77,26 +77,9 @@ static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata =
 	MFP_ADDR_END,
 };
 
-#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c)
-
-static void __init pxa910_init_gpio(void)
-{
-	int i;
-
-	/* enable GPIO clock */
-	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO);
-
-	/* unmask GPIO edge detection for all 4 banks - APMASKx */
-	for (i = 0; i < 4; i++)
-		__raw_writel(0xffffffff, APMASK(i));
-
-	pxa_init_gpio(IRQ_PXA910_AP_GPIO, 0, 127, NULL);
-}
-
 void __init pxa910_init_irq(void)
 {
 	icu_init_irq();
-	pxa910_init_gpio();
 }
 
 /* APB peripheral clocks */
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
index c5e1529..c15fa2b 100644
--- a/arch/arm/mach-mmp/tavorevb.c
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -70,8 +70,8 @@ static struct resource smc91x_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= pxa_gpio_to_irq(80),
-		.end	= pxa_gpio_to_irq(80),
+		.start	= mmp_gpio_to_irq(80),
+		.end	= mmp_gpio_to_irq(80),
 		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
 	}
 };
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
index 79bbbc2..4539fe3 100644
--- a/arch/arm/mach-mmp/teton_bga.c
+++ b/arch/arm/mach-mmp/teton_bga.c
@@ -66,7 +66,7 @@ static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = {
 static struct i2c_board_info teton_bga_i2c_info[] __initdata = {
 	{
 		I2C_BOARD_INFO("ds1337", 0x68),
-		.irq = pxa_gpio_to_irq(RTC_INT_GPIO)
+		.irq = mmp_gpio_to_irq(RTC_INT_GPIO)
 	},
 };
 
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index a420b07..b27e17e 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -136,7 +136,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
 	{
 		.type		= "max7312",
 		.addr		= 0x23,
-		.irq		= pxa_gpio_to_irq(80),
+		.irq		= mmp_gpio_to_irq(80),
 		.platform_data	= &max7312_data,
 	},
 };
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index cd19309..2b81f95 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -604,24 +604,28 @@ endmenu
 config PXA25x
 	bool
 	select CPU_XSCALE
+	select GPIO_PXA
 	help
 	  Select code specific to PXA21x/25x/26x variants
 
 config PXA27x
 	bool
 	select CPU_XSCALE
+	select GPIO_PXA
 	help
 	  Select code specific to PXA27x variants
 
 config CPU_PXA26x
 	bool
 	select PXA25x
+	select GPIO_PXA
 	help
 	  Select code specific to PXA26x (codename Dalhart)
 
 config PXA3xx
 	bool
 	select CPU_XSC3
+	select GPIO_PXA
 	help
 	  Select code specific to PXA3xx variants
 
@@ -647,6 +651,7 @@ config CPU_PXA320
 config CPU_PXA930
 	bool
 	select PXA3xx
+	select GPIO_PXA
 	help
 	  PXA930 (codename Tavor-P)
 
@@ -659,6 +664,7 @@ config CPU_PXA935
 config PXA95x
 	bool
 	select CPU_PJ4
+	select GPIO_PXA
 	help
 	  Select code specific to PXA95x variants
 
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index cc39d17..ab34cae 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support (must be linked before board specific support)
-obj-y				+= clock.o devices.o generic.o irq.o \
+obj-y				+= clock.o devices.o generic.o irq.o gpio.o\
 				   time.o reset.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o
 
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
new file mode 100644
index 0000000..de65c59
--- /dev/null
+++ b/arch/arm/mach-pxa/gpio.c
@@ -0,0 +1,92 @@
+/*
+ *  linux/arch/arm/mach-pxa/gpio.c
+ *
+ *  PXA series specific gpio init
+ *
+ *  Copyright (C) 2011 Marvell International Ltd.
+ *
+ *  Author:
+ *  	Haojian Zhuang <haojian.zhuang at marvell.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/gpio-pxa.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+static struct __initdata pxa_gpio_platform_data pxa_gpio_config;
+
+static struct __initdata resource pxa_resources_gpio[] = {
+	{
+		.start	= 0x40e00000,
+		.end	= 0x40e0ffff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_GPIO0,
+		.end	= IRQ_GPIO0,
+		.name	= "gpio0",
+		.flags	= IORESOURCE_IRQ,
+	}, {
+		.start	= IRQ_GPIO1,
+		.end	= IRQ_GPIO1,
+		.name	= "gpio1",
+		.flags	= IORESOURCE_IRQ,
+	}, {
+		.start	= IRQ_GPIO_2_x,
+		.end	= IRQ_GPIO_2_x,
+		.name	= "gpio_mux",
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pxa_gpio = {
+	.name		= "pxa-gpio",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pxa_resources_gpio),
+	.resource	= pxa_resources_gpio,
+};
+
+static int __init pxa_gpio_init(void)
+{
+	int size = sizeof(struct pxa_gpio_platform_data);
+	u32 reg_base = io_p2v(0x40E00000);
+
+	if (cpu_is_pxa25x()) {
+#ifdef CONFIG_PXA26x
+		pxa_gpio_config.gpio_type = PXA26X_GPIO;
+		pxa_gpio_config.gpio_end = 89;
+#else
+		pxa_gpio_config.gpio_type = PXA25X_GPIO;
+		pxa_gpio_config.gpio_end = 84;
+#endif
+	} else if (cpu_is_pxa27x()) {
+		pxa_gpio_config.gpio_type = PXA27X_GPIO;
+		pxa_gpio_config.gpio_end = 120;
+	} else if (cpu_is_pxa93x() || cpu_is_pxa95x()) {
+		pxa_gpio_config.gpio_type = PXA93X_GPIO;
+		pxa_gpio_config.gpio_end = 191;
+	} else if (cpu_is_pxa3xx()) {
+		pxa_gpio_config.gpio_type = PXA3XX_GPIO;
+		pxa_gpio_config.gpio_end = 127;
+	} else
+		return 0;
+
+	pxa_gpio_regs.gplr = reg_base + GPLR_OFFSET;
+	pxa_gpio_regs.gpdr = reg_base + GPDR_OFFSET;
+	pxa_gpio_regs.gpsr = reg_base + GPSR_OFFSET;
+	pxa_gpio_regs.gpcr = reg_base + GPCR_OFFSET;
+	pxa_gpio_regs.grer = reg_base + GRER_OFFSET;
+	pxa_gpio_regs.gfer = reg_base + GFER_OFFSET;
+	pxa_gpio_regs.gedr = reg_base + GEDR_OFFSET;
+	pxa_gpio_regs.gafr = reg_base + GAFR_OFFSET;
+
+	platform_device_add_data(&pxa_gpio, &pxa_gpio_config, size);
+	platform_device_register(&pxa_gpio);
+	return 0;
+}
+postcore_initcall(pxa_gpio_init);
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index d58efb5..6db7f59 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -25,71 +25,7 @@
 #define __ASM_ARCH_PXA_GPIO_H
 
 #include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <asm-generic/gpio.h>
-
-#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
-
-/* More handy macros.  The argument is a literal GPIO number. */
-
-#define GPIO_bit(x)	(1 << ((x) & 0x1f))
-
-/* GPIO Pin Level Registers */
-#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
-/* GPIO Pin Direction Registers */
-#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
-/* GPIO Pin Output Set Registers */
-#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
-/* GPIO Pin Output Clear Registers */
-#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
-/* GPIO Rising Edge Detect Registers */
-#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
-/* GPIO Falling Edge Detect Registers */
-#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
-/* GPIO Edge Detect Status Registers */
-#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
-/* GPIO Alternate Function Select Registers */
-#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
-
 
 #define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
 
-#define gpio_to_bank(gpio)	((gpio) >> 5)
-
-#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);
-}
-
-#include <plat/gpio.h>
 #endif
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 2ae1739..1c5070d 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -311,14 +311,12 @@ set_pwer:
 void __init pxa25x_init_irq(void)
 {
 	pxa_init_irq(32, 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(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake);
 }
 #endif
 
@@ -368,7 +366,6 @@ static int __init pxa25x_init(void)
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
 		ret = platform_add_devices(pxa25x_devices,
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 03d0728..638edf4 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -385,7 +385,6 @@ static int pxa27x_set_wake(struct irq_data *d, unsigned int on)
 void __init pxa27x_init_irq(void)
 {
 	pxa_init_irq(34, pxa27x_set_wake);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake);
 }
 
 static struct map_desc pxa27x_io_desc[] __initdata = {
@@ -454,7 +453,6 @@ static int __init pxa27x_init(void)
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
 		register_syscore_ops(&pxa2xx_mfp_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa2xx_clock_syscore_ops);
 
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index f18a6eb..fe4db28 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -389,7 +389,6 @@ void __init pxa3xx_init_irq(void)
 
 	pxa_init_irq(56, pxa3xx_set_wake);
 	pxa_init_ext_wakeup_irq(pxa3xx_set_wake);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
 static struct map_desc pxa3xx_io_desc[] __initdata = {
@@ -461,7 +460,6 @@ static int __init pxa3xx_init(void)
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
 		register_syscore_ops(&pxa3xx_mfp_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index de25ceb..b115829 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -235,7 +235,6 @@ static struct clk_lookup pxa95x_clkregs[] = {
 void __init pxa95x_init_irq(void)
 {
 	pxa_init_irq(96, NULL);
-	pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL);
 }
 
 /*
@@ -282,7 +281,6 @@ static int __init pxa95x_init(void)
 			return ret;
 
 		register_syscore_ops(&pxa_irq_syscore_ops);
-		register_syscore_ops(&pxa_gpio_syscore_ops);
 		register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 3aca5ba..f302d04 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -4,7 +4,6 @@
 
 obj-y	:= dma.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
 obj-$(CONFIG_PXA95x)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c
deleted file mode 100644
index d667d8d..0000000
--- a/arch/arm/plat-pxa/gpio.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- *  linux/arch/arm/plat-pxa/gpio.c
- *
- *  Generic PXA GPIO handling
- *
- *  Author:	Nicolas Pitre
- *  Created:	Jun 15, 2001
- *  Copyright:	MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-#include <linux/slab.h>
-
-int pxa_last_gpio;
-
-struct pxa_gpio_chip {
-	struct gpio_chip chip;
-	void __iomem	*regbase;
-	char label[10];
-
-	unsigned long	irq_mask;
-	unsigned long	irq_edge_rise;
-	unsigned long	irq_edge_fall;
-
-#ifdef CONFIG_PM
-	unsigned long	saved_gplr;
-	unsigned long	saved_gpdr;
-	unsigned long	saved_grer;
-	unsigned long	saved_gfer;
-#endif
-};
-
-static DEFINE_SPINLOCK(gpio_lock);
-static struct pxa_gpio_chip *pxa_gpio_chips;
-
-#define for_each_gpio_chip(i, c)			\
-	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
-
-static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
-{
-	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
-}
-
-static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
-{
-	return &pxa_gpio_chips[gpio_to_bank(gpio)];
-}
-
-static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t value, mask = 1 << offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	value = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		value |= mask;
-	else
-		value &= ~mask;
-	__raw_writel(value, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t tmp, mask = 1 << offset;
-	unsigned long flags;
-
-	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	tmp = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		tmp &= ~mask;
-	else
-		tmp |= mask;
-	__raw_writel(tmp, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
-}
-
-static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	__raw_writel(1 << offset, gpio_chip_base(chip) +
-				(value ? GPSR_OFFSET : GPCR_OFFSET));
-}
-
-static int __init pxa_init_gpio_chip(int gpio_end)
-{
-	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
-	struct pxa_gpio_chip *chips;
-
-	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
-	if (chips == NULL) {
-		pr_err("%s: failed to allocate GPIO chips\n", __func__);
-		return -ENOMEM;
-	}
-
-	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
-		struct gpio_chip *c = &chips[i].chip;
-
-		sprintf(chips[i].label, "gpio-%d", i);
-		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
-
-		c->base  = gpio;
-		c->label = chips[i].label;
-
-		c->direction_input  = pxa_gpio_direction_input;
-		c->direction_output = pxa_gpio_direction_output;
-		c->get = pxa_gpio_get;
-		c->set = pxa_gpio_set;
-
-		/* number of GPIOs on last bank may be less than 32 */
-		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
-		gpiochip_add(c);
-	}
-	pxa_gpio_chips = chips;
-	return 0;
-}
-
-/* Update only those GRERx and GFERx edge detection register bits if those
- * bits are set in c->irq_mask
- */
-static inline void update_edge_detect(struct pxa_gpio_chip *c)
-{
-	uint32_t grer, gfer;
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
-	grer |= c->irq_edge_rise & c->irq_mask;
-	gfer |= c->irq_edge_fall & c->irq_mask;
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
-{
-	struct pxa_gpio_chip *c;
-	int gpio = pxa_irq_to_gpio(d->irq);
-	unsigned long gpdr, mask = GPIO_bit(gpio);
-
-	c = gpio_to_pxachip(gpio);
-
-	if (type == IRQ_TYPE_PROBE) {
-		/* Don't mess with enabled GPIOs using preconfigured edges or
-		 * GPIOs set to alternate function or to output during probe
-		 */
-		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
-			return 0;
-
-		if (__gpio_is_occupied(gpio))
-			return 0;
-
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-
-	if (__gpio_is_inverted(gpio))
-		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
-	else
-		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		c->irq_edge_rise |= mask;
-	else
-		c->irq_edge_rise &= ~mask;
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		c->irq_edge_fall |= mask;
-	else
-		c->irq_edge_fall &= ~mask;
-
-	update_edge_detect(c);
-
-	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
-		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
-		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
-	return 0;
-}
-
-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct pxa_gpio_chip *c;
-	int loop, gpio, gpio_base, n;
-	unsigned long gedr;
-
-	do {
-		loop = 0;
-		for_each_gpio_chip(gpio, c) {
-			gpio_base = c->chip.base;
-
-			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
-			gedr = gedr & c->irq_mask;
-			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
-
-			n = find_first_bit(&gedr, BITS_PER_LONG);
-			while (n < BITS_PER_LONG) {
-				loop = 1;
-
-				generic_handle_irq(pxa_gpio_to_irq(gpio_base + n));
-				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
-			}
-		}
-	} while (loop);
-}
-
-static void pxa_ack_muxed_gpio(struct irq_data *d)
-{
-	int gpio = pxa_irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
-}
-
-static void pxa_mask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = pxa_irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-	uint32_t grer, gfer;
-
-	c->irq_mask &= ~GPIO_bit(gpio);
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static void pxa_unmask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = pxa_irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	c->irq_mask |= GPIO_bit(gpio);
-	update_edge_detect(c);
-}
-
-static struct irq_chip pxa_muxed_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= pxa_ack_muxed_gpio,
-	.irq_mask	= pxa_mask_muxed_gpio,
-	.irq_unmask	= pxa_unmask_muxed_gpio,
-	.irq_set_type	= pxa_gpio_irq_type,
-};
-
-void __init pxa_init_gpio(int mux_irq, int start, int end,
-			  int (*fn)(struct irq_data *, unsigned int))
-{
-	struct pxa_gpio_chip *c;
-	int gpio, irq;
-
-	pxa_last_gpio = end;
-
-	/* Initialize GPIO chips */
-	pxa_init_gpio_chip(end);
-
-	/* clear all GPIO edge detects */
-	for_each_gpio_chip(gpio, c) {
-		__raw_writel(0, c->regbase + GFER_OFFSET);
-		__raw_writel(0, c->regbase + GRER_OFFSET);
-		__raw_writel(~0,c->regbase + GEDR_OFFSET);
-	}
-
-#ifdef CONFIG_ARCH_PXA
-	irq = gpio_to_irq(0);
-	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler);
-
-	irq = gpio_to_irq(1);
-	irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-				 handle_edge_irq);
-	set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler);
-#endif
-
-	for (irq  = pxa_gpio_to_irq(start); irq <= pxa_gpio_to_irq(end);
-		irq++) {
-		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* Install handler for GPIO>=2 edge detect interrupts */
-	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
-	pxa_muxed_gpio_chip.irq_set_wake = fn;
-}
-
-#ifdef CONFIG_PM
-static int pxa_gpio_suspend(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
-		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
-		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
-
-		/* Clear GPIO transition detect bits */
-		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
-	}
-	return 0;
-}
-
-static void pxa_gpio_resume(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		/* restore level with set/clear */
-		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
-		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
-
-		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
-		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
-		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
-	}
-}
-#else
-#define pxa_gpio_suspend	NULL
-#define pxa_gpio_resume		NULL
-#endif
-
-struct syscore_ops pxa_gpio_syscore_ops = {
-	.suspend	= pxa_gpio_suspend,
-	.resume		= pxa_gpio_resume,
-};
diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h
deleted file mode 100644
index d31c2a5..0000000
--- a/arch/arm/plat-pxa/include/plat/gpio.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef __PLAT_GPIO_H
-#define __PLAT_GPIO_H
-
-#define __ARM_GPIOLIB_COMPLEX
-
-struct irq_data;
-
-/*
- * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
- * one set of registers. The register offsets are organized below:
- *
- *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
- * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
- * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
- * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
- *
- * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
- * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
- * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
- *
- * NOTE:
- *   BANK 3 is only available on PXA27x and later processors.
- *   BANK 4 and 5 are only available on PXA935
- */
-
-#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
-
-#define GPLR_OFFSET	0x00
-#define GPDR_OFFSET	0x0C
-#define GPSR_OFFSET	0x18
-#define GPCR_OFFSET	0x24
-#define GRER_OFFSET	0x30
-#define GFER_OFFSET	0x3C
-#define GEDR_OFFSET	0x48
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO))
-		return GPLR(gpio) & GPIO_bit(gpio);
-	else
-		return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) {
-		if (value)
-			GPSR(gpio) = GPIO_bit(gpio);
-		else
-			GPCR(gpio) = GPIO_bit(gpio);
-	} else
-		__gpio_set_value(gpio, value);
-}
-
-#define gpio_cansleep		__gpio_cansleep
-
-/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
- * Those cases currently cause holes in the GPIO number space, the
- * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
- */
-extern int pxa_last_gpio;
-
-extern void pxa_init_gpio(int mux_irq, int start, int end,
-			  int (*fn)(struct irq_data *, unsigned int));
-#endif /* __PLAT_GPIO_H */
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 6465030..08fe9f6 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -141,6 +141,12 @@ config GPIO_PL061
 	help
 	  Say yes here to support the PrimeCell PL061 GPIO device
 
+config GPIO_PXA
+	def_bool y
+	depends on ARCH_PXA || ARCH_MMP
+	help
+	  Say yes here to support the PXA GPIO device
+
 config GPIO_XILINX
 	bool "Xilinx GPIO support"
 	depends on PPC_OF || MICROBLAZE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a4c8ac9..194899f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
+obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
new file mode 100644
index 0000000..21d1394
--- /dev/null
+++ b/drivers/gpio/gpio-pxa.c
@@ -0,0 +1,500 @@
+/*
+ *  linux/arch/arm/plat-pxa/gpio.c
+ *
+ *  Generic PXA GPIO handling
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  Copyright (C) 2011 Marvell Technology
+ *  Moved to drivers/gpio - Haojian Zhuang <haojian.zhuang at marvell.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <linux/gpio-pxa.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+
+static int pxa_last_gpio;
+
+struct pxa_gpio_irq_data {
+	int	gpio_type;
+	int	irq_gpio0;
+	int	irq_gpio1;
+	int	irq_mux;
+};
+
+struct pxa_gpio_chip {
+	struct gpio_chip		chip;
+	void __iomem			*regbase;
+	char				label[10];
+
+	unsigned long			irq_mask;
+	unsigned long			irq_edge_rise;
+	unsigned long			irq_edge_fall;
+	struct pxa_gpio_irq_data	*data;
+
+#ifdef CONFIG_PM
+	unsigned long			saved_gplr;
+	unsigned long			saved_gpdr;
+	unsigned long			saved_grer;
+	unsigned long			saved_gfer;
+#endif
+};
+
+struct pxa_gpio_regs pxa_gpio_regs;
+
+static DEFINE_SPINLOCK(gpio_lock);
+static struct pxa_gpio_chip *pxa_gpio_chips;
+
+#define for_each_gpio_chip(i, c)			\
+	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
+
+static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
+{
+	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
+}
+
+static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
+{
+	return &pxa_gpio_chips[gpio_to_bank(gpio)];
+}
+
+static int __gpio_is_inverted(int gpio)
+{
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *data;
+
+	c = gpio_to_pxachip(gpio);
+	data = c->data;
+#ifdef CONFIG_ARCH_PXA
+	if (gpio_is_pxa_type(data->gpio_type)) {
+		if (data->gpio_type == PXA26X_GPIO && gpio > 84)
+			return 1;
+		else
+			return 0;
+	}
+#endif
+#ifdef CONFIG_ARCH_MMP
+	if (gpio_is_mmp_type(data->gpio_type))
+		return 0;
+#endif
+	return 0;
+}
+
+static int __gpio_is_irq(int gpio)
+{
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *data;
+	int af = 0, dir = 0;
+	int ret;
+
+	c = gpio_to_pxachip(gpio);
+	data = c->data;
+	switch (data->gpio_type) {
+	case PXA25X_GPIO:
+	case PXA26X_GPIO:
+	case PXA27X_GPIO:
+		af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+		dir = GPDR(gpio) & GPIO_bit(gpio);
+		if ((data->gpio_type == PXA26X_GPIO) && (gpio > 84))
+			ret = (af != 1) || (dir == 0);
+		else
+			ret = (af != 0) || (dir != 0);
+		break;
+	default:
+		ret = GPDR(gpio) & GPIO_bit(gpio);
+		break;
+	}
+	return ret;
+}
+
+static inline int mgpio_to_irq(int gpio)
+{
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *data;
+
+	c = gpio_to_pxachip(gpio);
+	data = c->data;
+#ifdef CONFIG_ARCH_PXA
+	if (gpio_is_pxa_type(data->gpio_type))
+		return pxa_gpio_to_irq(gpio);
+#endif
+#ifdef CONFIG_ARCH_MMP
+	if (gpio_is_mmp_type(data->gpio_type))
+		return mmp_gpio_to_irq(gpio);
+#endif
+	return 0;
+}
+
+static inline int mirq_to_gpio(struct irq_data *d)
+{
+	struct pxa_gpio_irq_data *data = irq_data_get_irq_chip_data(d);
+
+#ifdef CONFIG_ARCH_PXA
+	if (gpio_is_pxa_type(data->gpio_type))
+		return pxa_irq_to_gpio(d->irq);
+#endif
+#ifdef CONFIG_ARCH_MMP
+	if (gpio_is_mmp_type(data->gpio_type))
+		return mmp_irq_to_gpio(d->irq);
+#endif
+	return 0;
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t value, mask = 1 << offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	value = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		value |= mask;
+	else
+		value &= ~mask;
+	__raw_writel(value, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t tmp, mask = 1 << offset;
+	unsigned long flags;
+
+	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	tmp = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		tmp &= ~mask;
+	else
+		tmp |= mask;
+	__raw_writel(tmp, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
+}
+
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	__raw_writel(1 << offset, gpio_chip_base(chip) +
+				(value ? GPSR_OFFSET : GPCR_OFFSET));
+}
+
+static int __init pxa_init_gpio_chip(int gpio_end,
+				     struct pxa_gpio_irq_data *data)
+{
+	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct pxa_gpio_chip *chips;
+
+	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
+	if (chips == NULL) {
+		pr_err("%s: failed to allocate GPIO chips\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+		struct gpio_chip *c = &chips[i].chip;
+
+		sprintf(chips[i].label, "gpio-%d", i);
+		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
+		chips[i].data = data;
+
+		c->base  = gpio;
+		c->label = chips[i].label;
+
+		c->direction_input  = pxa_gpio_direction_input;
+		c->direction_output = pxa_gpio_direction_output;
+		c->get = pxa_gpio_get;
+		c->set = pxa_gpio_set;
+
+		/* number of GPIOs on last bank may be less than 32 */
+		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+		gpiochip_add(c);
+	}
+	pxa_gpio_chips = chips;
+	return 0;
+}
+
+/* Update only those GRERx and GFERx edge detection register bits if those
+ * bits are set in c->irq_mask
+ */
+static inline void update_edge_detect(struct pxa_gpio_chip *c)
+{
+	uint32_t grer, gfer;
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
+	grer |= c->irq_edge_rise & c->irq_mask;
+	gfer |= c->irq_edge_fall & c->irq_mask;
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	struct pxa_gpio_chip *c;
+	int gpio = mirq_to_gpio(d);
+	unsigned long gpdr, mask = GPIO_bit(gpio);
+
+	c = gpio_to_pxachip(gpio);
+
+	if (type == IRQ_TYPE_PROBE) {
+		/* Don't mess with enabled GPIOs using preconfigured edges or
+		 * GPIOs set to alternate function or to output during probe
+		 */
+		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
+			return 0;
+
+		if (!__gpio_is_irq(gpio))
+			return 0;
+
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+
+	if (__gpio_is_inverted(gpio))
+		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
+	else
+		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		c->irq_edge_rise |= mask;
+	else
+		c->irq_edge_rise &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		c->irq_edge_fall |= mask;
+	else
+		c->irq_edge_fall &= ~mask;
+
+	update_edge_detect(c);
+
+	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
+		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
+		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
+	return 0;
+}
+
+static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pxa_gpio_chip *c;
+	int loop, gpio, gpio_base, n;
+	unsigned long gedr;
+
+	do {
+		loop = 0;
+		for_each_gpio_chip(gpio, c) {
+			gpio_base = c->chip.base;
+
+			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
+			gedr = gedr & c->irq_mask;
+			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
+
+			n = find_first_bit(&gedr, BITS_PER_LONG);
+			while (n < BITS_PER_LONG) {
+				loop = 1;
+
+				irq = mgpio_to_irq(gpio_base + n);
+				generic_handle_irq(irq);
+				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
+			}
+		}
+	} while (loop);
+}
+
+static void pxa_ack_muxed_gpio(struct irq_data *d)
+{
+	int gpio = mirq_to_gpio(d);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
+}
+
+static void pxa_mask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = mirq_to_gpio(d);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	uint32_t grer, gfer;
+
+	c->irq_mask &= ~GPIO_bit(gpio);
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static void pxa_unmask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = mirq_to_gpio(d);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	c->irq_mask |= GPIO_bit(gpio);
+	update_edge_detect(c);
+}
+
+static struct irq_chip pxa_muxed_gpio_chip = {
+	.name		= "GPIO",
+	.irq_ack	= pxa_ack_muxed_gpio,
+	.irq_mask	= pxa_mask_muxed_gpio,
+	.irq_unmask	= pxa_unmask_muxed_gpio,
+	.irq_set_type	= pxa_gpio_irq_type,
+};
+
+
+static int __init pxa_gpio_probe(struct platform_device *pdev)
+{
+	struct pxa_gpio_platform_data *pdata;
+	struct pxa_gpio_chip *c;
+	struct pxa_gpio_irq_data *mux_data;
+	int gpio, irq;
+	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+	pdata = pdev->dev.platform_data;
+	pxa_last_gpio = pdata->gpio_end;
+
+	mux_data = kzalloc(sizeof(struct pxa_gpio_irq_data), GFP_KERNEL);
+	if (mux_data < 0)
+		return -ENOMEM;
+
+	irq0 = platform_get_irq_byname(pdev, "gpio0");
+	irq1 = platform_get_irq_byname(pdev, "gpio1");
+	irq_mux = platform_get_irq_byname(pdev, "gpio_mux");
+	if ((irq0 > 0 && irq1 < 0) || (irq0 < 0 && irq1 > 0) || (irq_mux < 0))
+		return -EINVAL;
+
+	if (irq0 > 0) {
+		mux_data->irq_gpio0 = irq0;
+		mux_data->irq_gpio1 = irq1;
+		gpio_offset = 2;
+	}
+	mux_data->irq_mux = irq_mux;
+	mux_data->gpio_type = pdata->gpio_type;
+
+	/* Initialize GPIO chips */
+	pxa_init_gpio_chip(pdata->gpio_end, mux_data);
+
+	/* clear all GPIO edge detects */
+	for_each_gpio_chip(gpio, c) {
+		__raw_writel(0, c->regbase + GFER_OFFSET);
+		__raw_writel(0, c->regbase + GRER_OFFSET);
+		__raw_writel(~0,c->regbase + GEDR_OFFSET);
+	}
+
+#ifdef CONFIG_ARCH_PXA
+	if (irq0 > 0) {
+		irq = pxa_gpio_to_irq(0);
+		irq_set_chip_data(irq, mux_data);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
+
+		irq = pxa_gpio_to_irq(1);
+		irq_set_chip_data(irq, mux_data);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
+	}
+#endif	/* CONFIG_ARCH_PXA */
+
+	for (irq = mgpio_to_irq(gpio_offset);
+		irq <= mgpio_to_irq(pdata->gpio_end); irq++) {
+		irq_set_chip_data(irq, mux_data);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);
+	return 0;
+}
+
+static struct platform_driver pxa_gpio_driver = {
+	.probe		= pxa_gpio_probe,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "pxa-gpio",
+	},
+};
+
+static int __init pxa_gpio_init(void)
+{
+	return platform_driver_register(&pxa_gpio_driver);
+}
+postcore_initcall(pxa_gpio_init);
+
+#ifdef CONFIG_PM
+static int pxa_gpio_suspend(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
+		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
+		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
+
+		/* Clear GPIO transition detect bits */
+		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
+	}
+	return 0;
+}
+
+static void pxa_gpio_resume(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		/* restore level with set/clear */
+		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
+		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
+
+		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
+		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
+		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
+	}
+}
+#else
+#define pxa_gpio_suspend	NULL
+#define pxa_gpio_resume		NULL
+#endif
+
+struct syscore_ops pxa_gpio_syscore_ops = {
+	.suspend	= pxa_gpio_suspend,
+	.resume		= pxa_gpio_resume,
+};
+
+static int __init pxa_gpio_sysinit(void)
+{
+	register_syscore_ops(&pxa_gpio_syscore_ops);
+	return 0;
+}
+postcore_initcall(pxa_gpio_sysinit);
diff --git a/include/linux/gpio-pxa.h b/include/linux/gpio-pxa.h
new file mode 100644
index 0000000..97d89af
--- /dev/null
+++ b/include/linux/gpio-pxa.h
@@ -0,0 +1,105 @@
+#ifndef __GPIO_PXA_H
+#define __GPIO_PXA_H
+
+#include <asm/io.h>
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ * GPLR -- GPIO Pin Level Registers
+ * GPDR -- GPIO Pin Direction Registers
+ * GPSR -- GPIO Pin Output Set Registers
+ * GPCR -- GPIO Pin Output Clear Registers
+ * GRER -- GPIO Rising Edge Detect Registers
+ * GFER -- GPIO Falling Edge Detect Registers
+ * GEDR -- GPIO Edge Detect Status Registers
+ *
+ *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
+ * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
+ * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
+ * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
+ *
+ * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
+ * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
+ * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
+ *
+ * NOTE:
+ *   BANK 3 is only available on PXA27x and later processors.
+ *   BANK 4 and 5 are only available on PXA935
+ */
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+
+#define gpio_to_bank(x)	((x) >> 5)
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+
+#define GPLR_OFFSET	0x00
+#define GPDR_OFFSET	0x0C
+#define GPSR_OFFSET	0x18
+#define GPCR_OFFSET	0x24
+#define GRER_OFFSET	0x30
+#define GFER_OFFSET	0x3C
+#define GEDR_OFFSET	0x48
+#define GAFR_OFFSET	0x54
+
+enum {
+	/*
+	 * Interrupt of GPIO0 & GPIO1 is dependant in PXA series.
+	 * Interrupt of all GPIO is muxed into one in MMP series.
+	 */
+	PXA25X_GPIO = 0,
+	PXA26X_GPIO,
+	PXA27X_GPIO,
+	PXA3XX_GPIO,
+	PXA93X_GPIO,
+	MMP_GPIO = 0x10,
+	MMP2_GPIO,
+};
+
+#define MASK_GPIO_PXA				0x0f
+#define MASK_GPIO_MMP				0xf0
+
+struct pxa_gpio_platform_data {
+	int	gpio_end;
+	int	gpio_type;
+};
+
+static inline int gpio_is_pxa_type(int type)
+{
+	return type & MASK_GPIO_PXA;
+}
+
+static inline int gpio_is_mmp_type(int type)
+{
+	return type & MASK_GPIO_MMP;
+}
+
+struct pxa_gpio_regs {
+	u32	gplr;
+	u32	gpdr;
+	u32	gpsr;
+	u32	gpcr;
+	u32	grer;
+	u32	gfer;
+	u32	gedr;
+	u32	gafr;
+};
+
+extern struct pxa_gpio_regs pxa_gpio_regs;
+
+#define GPLR(x)		(*(volatile u32 *)(pxa_gpio_regs.gplr + BANK_OFF((x >> 5))))
+#define GPDR(x)		(*(volatile u32 *)(pxa_gpio_regs.gpdr + BANK_OFF((x >> 5))))
+#define GPSR(x)		(*(volatile u32 *)(pxa_gpio_regs.gpsr + BANK_OFF((x >> 5))))
+#define GPCR(x)		(*(volatile u32 *)(pxa_gpio_regs.gpcr + BANK_OFF((x >> 5))))
+#define GRER(x)		(*(volatile u32 *)(pxa_gpio_regs.grer + BANK_OFF((x >> 5))))
+#define GFER(x)		(*(volatile u32 *)(pxa_gpio_regs.gfer + BANK_OFF((x >> 5))))
+#define GEDR(x)		(*(volatile u32 *)(pxa_gpio_regs.gedr + BANK_OFF((x >> 5))))
+#define GAFR(x)		(*(volatile u32 *)(pxa_gpio_regs.gafr + (((x) & 0x70) >> 2)))
+
+#define GPIO_BANK(n)	(pxa_gpio_regs.gplr + BANK_OFF(n))
+
+#endif	/* __GPIO_PXA_H */
-- 
1.7.2.5




More information about the linux-arm-kernel mailing list