summary refs log tree commit diff
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig44
-rw-r--r--drivers/gpio/Makefile5
-rw-r--r--drivers/gpio/gpio-74x164.c6
-rw-r--r--drivers/gpio/gpio-ab8500.c6
-rw-r--r--drivers/gpio/gpio-adnp.c10
-rw-r--r--drivers/gpio/gpio-adp5520.c6
-rw-r--r--drivers/gpio/gpio-adp5588.c6
-rw-r--r--drivers/gpio/gpio-arizona.c6
-rw-r--r--drivers/gpio/gpio-clps711x.c199
-rw-r--r--drivers/gpio/gpio-cs5535.c6
-rw-r--r--drivers/gpio/gpio-da9052.c8
-rw-r--r--drivers/gpio/gpio-da9055.c204
-rw-r--r--drivers/gpio/gpio-em.c54
-rw-r--r--drivers/gpio/gpio-ep93xx.c2
-rw-r--r--drivers/gpio/gpio-generic.c6
-rw-r--r--drivers/gpio/gpio-ich.c10
-rw-r--r--drivers/gpio/gpio-janz-ttl.c10
-rw-r--r--drivers/gpio/gpio-langwell.c8
-rw-r--r--drivers/gpio/gpio-lpc32xx.c4
-rw-r--r--drivers/gpio/gpio-max7300.c6
-rw-r--r--drivers/gpio/gpio-max7301.c6
-rw-r--r--drivers/gpio/gpio-max730x.c16
-rw-r--r--drivers/gpio/gpio-max732x.c8
-rw-r--r--drivers/gpio/gpio-mc33880.c6
-rw-r--r--drivers/gpio/gpio-mcp23s08.c12
-rw-r--r--drivers/gpio/gpio-ml-ioh.c8
-rw-r--r--drivers/gpio/gpio-mpc5200.c4
-rw-r--r--drivers/gpio/gpio-msic.c2
-rw-r--r--drivers/gpio/gpio-msm-v2.c6
-rw-r--r--drivers/gpio/gpio-mvebu.c36
-rw-r--r--drivers/gpio/gpio-mxc.c4
-rw-r--r--drivers/gpio/gpio-mxs.c2
-rw-r--r--drivers/gpio/gpio-omap.c8
-rw-r--r--drivers/gpio/gpio-pca953x.c61
-rw-r--r--drivers/gpio/gpio-pcf857x.c29
-rw-r--r--drivers/gpio/gpio-pch.c9
-rw-r--r--drivers/gpio/gpio-pl061.c66
-rw-r--r--drivers/gpio/gpio-pxa.c8
-rw-r--r--drivers/gpio/gpio-rc5t583.c6
-rw-r--r--drivers/gpio/gpio-rdc321x.c6
-rw-r--r--drivers/gpio/gpio-samsung.c68
-rw-r--r--drivers/gpio/gpio-sch.c6
-rw-r--r--drivers/gpio/gpio-sodaville.c4
-rw-r--r--drivers/gpio/gpio-spear-spics.c217
-rw-r--r--drivers/gpio/gpio-sta2x11.c4
-rw-r--r--drivers/gpio/gpio-stmpe.c94
-rw-r--r--drivers/gpio/gpio-stp-xway.c2
-rw-r--r--drivers/gpio/gpio-sx150x.c6
-rw-r--r--drivers/gpio/gpio-tc3589x.c26
-rw-r--r--drivers/gpio/gpio-tegra.c47
-rw-r--r--drivers/gpio/gpio-timberdale.c4
-rw-r--r--drivers/gpio/gpio-tps6586x.c6
-rw-r--r--drivers/gpio/gpio-tps65910.c6
-rw-r--r--drivers/gpio/gpio-tps65912.c6
-rw-r--r--drivers/gpio/gpio-ts5500.c466
-rw-r--r--drivers/gpio/gpio-twl4030.c43
-rw-r--r--drivers/gpio/gpio-twl6040.c4
-rw-r--r--drivers/gpio/gpio-vr41xx.c6
-rw-r--r--drivers/gpio/gpio-vt8500.c4
-rw-r--r--drivers/gpio/gpio-vx855.c6
-rw-r--r--drivers/gpio/gpio-wm831x.c6
-rw-r--r--drivers/gpio/gpio-wm8350.c6
-rw-r--r--drivers/gpio/gpio-wm8994.c6
-rw-r--r--drivers/gpio/gpio-xilinx.c4
-rw-r--r--drivers/gpio/gpiolib-acpi.c54
-rw-r--r--drivers/gpio/gpiolib-of.c52
-rw-r--r--drivers/gpio/gpiolib.c200
67 files changed, 1826 insertions, 436 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index c3bbd08bcdc3..8ae1f5b19669 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -47,7 +47,11 @@ if GPIOLIB
 
 config OF_GPIO
 	def_bool y
-	depends on OF && !SPARC
+	depends on OF
+
+config GPIO_ACPI
+	def_bool y
+	depends on ACPI
 
 config DEBUG_GPIO
 	bool "Debug GPIO calls"
@@ -86,11 +90,26 @@ config GPIO_DA9052
 	help
 	  Say yes here to enable the GPIO driver for the DA9052 chip.
 
+config GPIO_DA9055
+	tristate "Dialog Semiconductor DA9055 GPIO"
+	depends on MFD_DA9055
+	help
+	  Say yes here to enable the GPIO driver for the DA9055 chip.
+
+	  The Dialog DA9055 PMIC chip has 3 GPIO pins that can be
+	  be controller by this driver.
+
+	  If driver is built as a module it will be called gpio-da9055.
+
 config GPIO_MAX730X
 	tristate
 
 comment "Memory mapped GPIO drivers:"
 
+config GPIO_CLPS711X
+	def_bool y
+	depends on ARCH_CLPS711X
+
 config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
 	select GPIO_GENERIC
@@ -152,7 +171,7 @@ config GPIO_MSM_V2
 
 config GPIO_MVEBU
 	def_bool y
-	depends on ARCH_MVEBU
+	depends on PLAT_ORION
 	select GPIO_GENERIC
 	select GENERIC_IRQ_CHIP
 
@@ -170,7 +189,7 @@ config GPIO_MXS
 
 config GPIO_PL061
 	bool "PrimeCell PL061 GPIO support"
-	depends on ARM_AMBA
+	depends on ARM && ARM_AMBA
 	select GENERIC_IRQ_CHIP
 	help
 	  Say yes here to support the PrimeCell PL061 GPIO device
@@ -181,6 +200,13 @@ config GPIO_PXA
 	help
 	  Say yes here to support the PXA GPIO device
 
+config GPIO_SPEAR_SPICS
+	bool "ST SPEAr13xx SPI Chip Select as GPIO support"
+	depends on PLAT_SPEAR
+	select GENERIC_IRQ_CHIP
+	help
+	  Say yes here to support ST SPEAr SPI Chip Select as GPIO device
+
 config GPIO_STA2X11
 	bool "STA2x11/ConneXt GPIO support"
 	depends on MFD_STA2X11
@@ -189,6 +215,14 @@ config GPIO_STA2X11
 	  Say yes here to support the STA2x11/ConneXt GPIO device.
 	  The GPIO module has 128 GPIO pins with alternate functions.
 
+config GPIO_TS5500
+	tristate "TS-5500 DIO blocks and compatibles"
+	help
+	  This driver supports Digital I/O exposed by pin blocks found on some
+	  Technologic Systems platforms. It includes, but is not limited to, 3
+	  blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
+	  LCD port.
+
 config GPIO_VT8500
 	bool "VIA/Wondermedia SoC GPIO Support"
 	depends on ARCH_VT8500
@@ -466,11 +500,11 @@ config GPIO_ADP5588_IRQ
 
 config GPIO_ADNP
 	tristate "Avionic Design N-bit GPIO expander"
-	depends on I2C && OF
+	depends on I2C && OF_GPIO
 	help
 	  This option enables support for N GPIOs found on Avionic Design
 	  I2C GPIO expanders. The register space will be extended by powers
-	  of two, so the controller will need to accomodate for that. For
+	  of two, so the controller will need to accommodate for that. For
 	  example: if a controller provides 48 pins, 6 registers will be
 	  enough to represent all pins, but the driver will assume a
 	  register layout for 64 pins (8 registers).
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 16a1385226e9..c5aebd008dde 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG
 
 obj-$(CONFIG_GPIOLIB)		+= gpiolib.o devres.o
 obj-$(CONFIG_OF_GPIO)		+= gpiolib-of.o
+obj-$(CONFIG_GPIO_ACPI)		+= gpiolib-acpi.o
 
 # Device drivers. Generally keep list sorted alphabetically
 obj-$(CONFIG_GPIO_GENERIC)	+= gpio-generic.o
@@ -16,8 +17,10 @@ obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o
 obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o
 obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
+obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
+obj-$(CONFIG_GPIO_DA9055)	+= gpio-da9055.o
 obj-$(CONFIG_ARCH_DAVINCI)	+= gpio-davinci.o
 obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
@@ -57,6 +60,7 @@ obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_SODAVILLE)	+= gpio-sodaville.o
+obj-$(CONFIG_GPIO_SPEAR_SPICS)	+= gpio-spear-spics.o
 obj-$(CONFIG_GPIO_STA2X11)	+= gpio-sta2x11.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_STP_XWAY)	+= gpio-stp-xway.o
@@ -68,6 +72,7 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
 obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
+obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
 obj-$(CONFIG_GPIO_UCB1400)	+= gpio-ucb1400.o
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index f05e54258ffb..464be961f605 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -105,7 +105,7 @@ static int gen_74x164_direction_output(struct gpio_chip *gc,
 	return 0;
 }
 
-static int __devinit gen_74x164_probe(struct spi_device *spi)
+static int gen_74x164_probe(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
 	struct gen_74x164_chip_platform_data *pdata;
@@ -181,7 +181,7 @@ exit_destroy:
 	return ret;
 }
 
-static int __devexit gen_74x164_remove(struct spi_device *spi)
+static int gen_74x164_remove(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
 	int ret;
@@ -215,7 +215,7 @@ static struct spi_driver gen_74x164_driver = {
 		.of_match_table	= of_match_ptr(gen_74x164_dt_ids),
 	},
 	.probe		= gen_74x164_probe,
-	.remove		= __devexit_p(gen_74x164_remove),
+	.remove		= gen_74x164_remove,
 };
 module_spi_driver(gen_74x164_driver);
 
diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
index 050c05d91896..983ad425f0ac 100644
--- a/drivers/gpio/gpio-ab8500.c
+++ b/drivers/gpio/gpio-ab8500.c
@@ -402,7 +402,7 @@ static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
 	}
 }
 
-static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
+static int ab8500_gpio_probe(struct platform_device *pdev)
 {
 	struct ab8500_platform_data *ab8500_pdata =
 				dev_get_platdata(pdev->dev.parent);
@@ -474,7 +474,7 @@ out_free:
  * ab8500_gpio_remove() - remove Ab8500-gpio driver
  * @pdev :	Platform device registered
  */
-static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
+static int ab8500_gpio_remove(struct platform_device *pdev)
 {
 	struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
 	int ret;
@@ -499,7 +499,7 @@ static struct platform_driver ab8500_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = ab8500_gpio_probe,
-	.remove = __devexit_p(ab8500_gpio_remove),
+	.remove = ab8500_gpio_remove,
 };
 
 static int __init ab8500_gpio_init(void)
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 3df88336415e..e60567fc5073 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -516,7 +516,7 @@ static void adnp_irq_teardown(struct adnp *adnp)
 	irq_domain_remove(adnp->domain);
 }
 
-static __devinit int adnp_i2c_probe(struct i2c_client *client,
+static int adnp_i2c_probe(struct i2c_client *client,
 				    const struct i2c_device_id *id)
 {
 	struct device_node *np = client->dev.of_node;
@@ -563,7 +563,7 @@ teardown:
 	return err;
 }
 
-static __devexit int adnp_i2c_remove(struct i2c_client *client)
+static int adnp_i2c_remove(struct i2c_client *client)
 {
 	struct adnp *adnp = i2c_get_clientdata(client);
 	struct device_node *np = client->dev.of_node;
@@ -582,13 +582,13 @@ static __devexit int adnp_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
-static const struct i2c_device_id adnp_i2c_id[] __devinitconst = {
+static const struct i2c_device_id adnp_i2c_id[] = {
 	{ "gpio-adnp" },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, adnp_i2c_id);
 
-static const struct of_device_id adnp_of_match[] __devinitconst = {
+static const struct of_device_id adnp_of_match[] = {
 	{ .compatible = "ad,gpio-adnp", },
 	{ },
 };
@@ -601,7 +601,7 @@ static struct i2c_driver adnp_i2c_driver = {
 		.of_match_table = of_match_ptr(adnp_of_match),
 	},
 	.probe = adnp_i2c_probe,
-	.remove = __devexit_p(adnp_i2c_remove),
+	.remove = adnp_i2c_remove,
 	.id_table = adnp_i2c_id,
 };
 module_i2c_driver(adnp_i2c_driver);
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
index 2f263cc32561..8afa95f831b1 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/gpio-adp5520.c
@@ -87,7 +87,7 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip,
 	return ret;
 }
 
-static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
+static int adp5520_gpio_probe(struct platform_device *pdev)
 {
 	struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
 	struct adp5520_gpio *dev;
@@ -167,7 +167,7 @@ err:
 	return ret;
 }
 
-static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
+static int adp5520_gpio_remove(struct platform_device *pdev)
 {
 	struct adp5520_gpio *dev;
 	int ret;
@@ -190,7 +190,7 @@ static struct platform_driver adp5520_gpio_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= adp5520_gpio_probe,
-	.remove		= __devexit_p(adp5520_gpio_remove),
+	.remove		= adp5520_gpio_remove,
 };
 
 module_platform_driver(adp5520_gpio_driver);
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index eeedad42913e..2ba56987db04 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -346,7 +346,7 @@ static void adp5588_irq_teardown(struct adp5588_gpio *dev)
 }
 #endif /* CONFIG_GPIO_ADP5588_IRQ */
 
-static int __devinit adp5588_gpio_probe(struct i2c_client *client,
+static int adp5588_gpio_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
@@ -438,7 +438,7 @@ err:
 	return ret;
 }
 
-static int __devexit adp5588_gpio_remove(struct i2c_client *client)
+static int adp5588_gpio_remove(struct i2c_client *client)
 {
 	struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
 	struct adp5588_gpio *dev = i2c_get_clientdata(client);
@@ -479,7 +479,7 @@ static struct i2c_driver adp5588_gpio_driver = {
 		   .name = DRV_NAME,
 		   },
 	.probe = adp5588_gpio_probe,
-	.remove = __devexit_p(adp5588_gpio_remove),
+	.remove = adp5588_gpio_remove,
 	.id_table = adp5588_gpio_id,
 };
 
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 8740d2eb06f8..0ea853f68db2 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -94,7 +94,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit arizona_gpio_probe(struct platform_device *pdev)
+static int arizona_gpio_probe(struct platform_device *pdev)
 {
 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
 	struct arizona_pdata *pdata = arizona->dev->platform_data;
@@ -141,7 +141,7 @@ err:
 	return ret;
 }
 
-static int __devexit arizona_gpio_remove(struct platform_device *pdev)
+static int arizona_gpio_remove(struct platform_device *pdev)
 {
 	struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
 
@@ -152,7 +152,7 @@ static struct platform_driver arizona_gpio_driver = {
 	.driver.name	= "arizona-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= arizona_gpio_probe,
-	.remove		= __devexit_p(arizona_gpio_remove),
+	.remove		= arizona_gpio_remove,
 };
 
 module_platform_driver(arizona_gpio_driver);
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
new file mode 100644
index 000000000000..ce63b75b13f5
--- /dev/null
+++ b/drivers/gpio/gpio-clps711x.c
@@ -0,0 +1,199 @@
+/*
+ *  CLPS711X GPIO driver
+ *
+ *  Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+
+#define CLPS711X_GPIO_PORTS	5
+#define CLPS711X_GPIO_NAME	"gpio-clps711x"
+
+struct clps711x_gpio {
+	struct gpio_chip	chip[CLPS711X_GPIO_PORTS];
+	spinlock_t		lock;
+};
+
+static void __iomem *clps711x_ports[] = {
+	CLPS711X_VIRT_BASE + PADR,
+	CLPS711X_VIRT_BASE + PBDR,
+	CLPS711X_VIRT_BASE + PCDR,
+	CLPS711X_VIRT_BASE + PDDR,
+	CLPS711X_VIRT_BASE + PEDR,
+};
+
+static void __iomem *clps711x_pdirs[] = {
+	CLPS711X_VIRT_BASE + PADDR,
+	CLPS711X_VIRT_BASE + PBDDR,
+	CLPS711X_VIRT_BASE + PCDDR,
+	CLPS711X_VIRT_BASE + PDDDR,
+	CLPS711X_VIRT_BASE + PEDDR,
+};
+
+#define clps711x_port(x)	clps711x_ports[x->base / 8]
+#define clps711x_pdir(x)	clps711x_pdirs[x->base / 8]
+
+static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset)
+{
+	return !!(readb(clps711x_port(chip)) & (1 << offset));
+}
+
+static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset,
+			      int value)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+	if (value)
+		tmp |= 1 << offset;
+	writeb(tmp, clps711x_port(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset,
+				 int value)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) | (1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+	if (value)
+		tmp |= 1 << offset;
+	writeb(tmp, clps711x_port(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) | (1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset,
+				     int value)
+{
+	int tmp;
+	unsigned long flags;
+	struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+	spin_lock_irqsave(&gpio->lock, flags);
+	tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
+	writeb(tmp, clps711x_pdir(chip));
+	tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+	if (value)
+		tmp |= 1 << offset;
+	writeb(tmp, clps711x_port(chip));
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
+static struct {
+	char	*name;
+	int	nr;
+	int	inv_dir;
+} clps711x_gpio_ports[] __initconst = {
+	{ "PORTA", 8, 0, },
+	{ "PORTB", 8, 0, },
+	{ "PORTC", 8, 0, },
+	{ "PORTD", 8, 1, },
+	{ "PORTE", 3, 0, },
+};
+
+static int __init gpio_clps711x_init(void)
+{
+	int i;
+	struct platform_device *pdev;
+	struct clps711x_gpio *gpio;
+
+	pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0);
+	if (!pdev) {
+		pr_err("Cannot create platform device: %s\n",
+		       CLPS711X_GPIO_NAME);
+		return -ENOMEM;
+	}
+
+	platform_device_add(pdev);
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio),
+			    GFP_KERNEL);
+	if (!gpio) {
+		dev_err(&pdev->dev, "GPIO allocating memory error\n");
+		platform_device_unregister(pdev);
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, gpio);
+
+	spin_lock_init(&gpio->lock);
+
+	for (i = 0; i < CLPS711X_GPIO_PORTS; i++) {
+		gpio->chip[i].owner		= THIS_MODULE;
+		gpio->chip[i].dev		= &pdev->dev;
+		gpio->chip[i].label		= clps711x_gpio_ports[i].name;
+		gpio->chip[i].base		= i * 8;
+		gpio->chip[i].ngpio		= clps711x_gpio_ports[i].nr;
+		gpio->chip[i].get		= gpio_clps711x_get;
+		gpio->chip[i].set		= gpio_clps711x_set;
+		if (!clps711x_gpio_ports[i].inv_dir) {
+			gpio->chip[i].direction_input = gpio_clps711x_dir_in;
+			gpio->chip[i].direction_output = gpio_clps711x_dir_out;
+		} else {
+			gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv;
+			gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv;
+		}
+		WARN_ON(gpiochip_add(&gpio->chip[i]));
+	}
+
+	dev_info(&pdev->dev, "GPIO driver initialized\n");
+
+	return 0;
+}
+arch_initcall(gpio_clps711x_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("CLPS711X GPIO driver");
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
index 19eda1bbe343..c0a3aeba6f21 100644
--- a/drivers/gpio/gpio-cs5535.c
+++ b/drivers/gpio/gpio-cs5535.c
@@ -300,7 +300,7 @@ static struct cs5535_gpio_chip cs5535_gpio_chip = {
 	},
 };
 
-static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
+static int cs5535_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int err = -EIO;
@@ -355,7 +355,7 @@ done:
 	return err;
 }
 
-static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
+static int cs5535_gpio_remove(struct platform_device *pdev)
 {
 	struct resource *r;
 	int err;
@@ -378,7 +378,7 @@ static struct platform_driver cs5535_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = cs5535_gpio_probe,
-	.remove = __devexit_p(cs5535_gpio_remove),
+	.remove = cs5535_gpio_remove,
 };
 
 module_platform_driver(cs5535_gpio_driver);
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
index 63f9f5bbc75c..29b11e9b6a78 100644
--- a/drivers/gpio/gpio-da9052.c
+++ b/drivers/gpio/gpio-da9052.c
@@ -192,7 +192,7 @@ static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
 	return irq;
 }
 
-static struct gpio_chip reference_gp __devinitdata = {
+static struct gpio_chip reference_gp = {
 	.label = "da9052-gpio",
 	.owner = THIS_MODULE,
 	.get = da9052_gpio_get,
@@ -205,7 +205,7 @@ static struct gpio_chip reference_gp __devinitdata = {
 	.base = -1,
 };
 
-static int __devinit da9052_gpio_probe(struct platform_device *pdev)
+static int da9052_gpio_probe(struct platform_device *pdev)
 {
 	struct da9052_gpio *gpio;
 	struct da9052_pdata *pdata;
@@ -233,7 +233,7 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int __devexit da9052_gpio_remove(struct platform_device *pdev)
+static int da9052_gpio_remove(struct platform_device *pdev)
 {
 	struct da9052_gpio *gpio = platform_get_drvdata(pdev);
 
@@ -242,7 +242,7 @@ static int __devexit da9052_gpio_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_gpio_driver = {
 	.probe = da9052_gpio_probe,
-	.remove = __devexit_p(da9052_gpio_remove),
+	.remove = da9052_gpio_remove,
 	.driver = {
 		.name	= "da9052-gpio",
 		.owner	= THIS_MODULE,
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c
new file mode 100644
index 000000000000..55d83c7d9c7f
--- /dev/null
+++ b/drivers/gpio/gpio-da9055.c
@@ -0,0 +1,204 @@
+/*
+ * GPIO Driver for Dialog DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ *  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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_VDD_IO			0x0
+#define DA9055_PUSH_PULL		0x3
+#define DA9055_ACT_LOW			0x0
+#define DA9055_GPI			0x1
+#define DA9055_PORT_MASK		0x3
+#define DA9055_PORT_SHIFT(offset)	(4 * (offset % 2))
+
+#define DA9055_INPUT			DA9055_GPI
+#define DA9055_OUTPUT			DA9055_PUSH_PULL
+#define DA9055_IRQ_GPI0			3
+
+struct da9055_gpio {
+	struct da9055 *da9055;
+	struct gpio_chip gp;
+};
+
+static inline struct da9055_gpio *to_da9055_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct da9055_gpio, gp);
+}
+
+static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	int gpio_direction = 0;
+	int ret;
+
+	/* Get GPIO direction */
+	ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1);
+	if (ret < 0)
+		return ret;
+
+	gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset);
+	gpio_direction >>= DA9055_PORT_SHIFT(offset);
+	switch (gpio_direction) {
+	case DA9055_INPUT:
+		ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B);
+		if (ret < 0)
+			return ret;
+		break;
+	case DA9055_OUTPUT:
+		ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret & (1 << offset);
+
+}
+
+static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+
+	da9055_reg_update(gpio->da9055,
+			DA9055_REG_GPIO_MODE0_2,
+			1 << offset,
+			value << offset);
+}
+
+static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	unsigned char reg_byte;
+
+	reg_byte = (DA9055_ACT_LOW | DA9055_GPI)
+				<< DA9055_PORT_SHIFT(offset);
+
+	return da9055_reg_update(gpio->da9055, (offset >> 1) +
+				DA9055_REG_GPIO0_1,
+				DA9055_PORT_MASK <<
+				DA9055_PORT_SHIFT(offset),
+				reg_byte);
+}
+
+static int da9055_gpio_direction_output(struct gpio_chip *gc,
+					unsigned offset, int value)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	unsigned char reg_byte;
+	int ret;
+
+	reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL)
+					<< DA9055_PORT_SHIFT(offset);
+
+	ret = da9055_reg_update(gpio->da9055, (offset >> 1) +
+				DA9055_REG_GPIO0_1,
+				DA9055_PORT_MASK <<
+				DA9055_PORT_SHIFT(offset),
+				reg_byte);
+	if (ret < 0)
+		return ret;
+
+	da9055_gpio_set(gc, offset, value);
+
+	return 0;
+}
+
+static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+{
+	struct da9055_gpio *gpio = to_da9055_gpio(gc);
+	struct da9055 *da9055 = gpio->da9055;
+
+	return regmap_irq_get_virq(da9055->irq_data,
+				  DA9055_IRQ_GPI0 + offset);
+}
+
+static struct gpio_chip reference_gp __devinitdata = {
+	.label = "da9055-gpio",
+	.owner = THIS_MODULE,
+	.get = da9055_gpio_get,
+	.set = da9055_gpio_set,
+	.direction_input = da9055_gpio_direction_input,
+	.direction_output = da9055_gpio_direction_output,
+	.to_irq = da9055_gpio_to_irq,
+	.can_sleep = 1,
+	.ngpio = 3,
+	.base = -1,
+};
+
+static int __devinit da9055_gpio_probe(struct platform_device *pdev)
+{
+	struct da9055_gpio *gpio;
+	struct da9055_pdata *pdata;
+	int ret;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (gpio == NULL)
+		return -ENOMEM;
+
+	gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
+	pdata = gpio->da9055->dev->platform_data;
+
+	gpio->gp = reference_gp;
+	if (pdata && pdata->gpio_base)
+		gpio->gp.base = pdata->gpio_base;
+
+	ret = gpiochip_add(&gpio->gp);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+		goto err_mem;
+	}
+
+	platform_set_drvdata(pdev, gpio);
+
+	return 0;
+
+err_mem:
+	return ret;
+}
+
+static int __devexit da9055_gpio_remove(struct platform_device *pdev)
+{
+	struct da9055_gpio *gpio = platform_get_drvdata(pdev);
+
+	return gpiochip_remove(&gpio->gp);
+}
+
+static struct platform_driver da9055_gpio_driver = {
+	.probe = da9055_gpio_probe,
+	.remove = __devexit_p(da9055_gpio_remove),
+	.driver = {
+		.name	= "da9055-gpio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init da9055_gpio_init(void)
+{
+	return platform_driver_register(&da9055_gpio_driver);
+}
+subsys_initcall(da9055_gpio_init);
+
+static void __exit da9055_gpio_exit(void)
+{
+	platform_driver_unregister(&da9055_gpio_driver);
+}
+module_exit(da9055_gpio_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 GPIO Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-gpio");
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index efb4c2d0d132..bdc8302e711a 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -35,7 +35,6 @@
 struct em_gio_priv {
 	void __iomem *base0;
 	void __iomem *base1;
-	unsigned int irq_base;
 	spinlock_t sense_lock;
 	struct platform_device *pdev;
 	struct gpio_chip gpio_chip;
@@ -214,7 +213,7 @@ static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
 
 static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset);
+	return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
 }
 
 static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
@@ -234,41 +233,7 @@ static struct irq_domain_ops em_gio_irq_domain_ops = {
 	.map	= em_gio_irq_domain_map,
 };
 
-static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)
-{
-	struct platform_device *pdev = p->pdev;
-	struct gpio_em_config *pdata = pdev->dev.platform_data;
-
-	p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
-				      pdata->number_of_pins, numa_node_id());
-	if (p->irq_base < 0) {
-		dev_err(&pdev->dev, "cannot get irq_desc\n");
-		return p->irq_base;
-	}
-	pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
-		 pdata->gpio_base, pdata->number_of_pins, p->irq_base);
-
-	p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
-					      pdata->number_of_pins,
-					      p->irq_base, 0,
-					      &em_gio_irq_domain_ops, p);
-	if (!p->irq_domain) {
-		irq_free_descs(p->irq_base, pdata->number_of_pins);
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-static void em_gio_irq_domain_cleanup(struct em_gio_priv *p)
-{
-	struct gpio_em_config *pdata = p->pdev->dev.platform_data;
-
-	irq_free_descs(p->irq_base, pdata->number_of_pins);
-	/* FIXME: irq domain wants to be freed! */
-}
-
-static int __devinit em_gio_probe(struct platform_device *pdev)
+static int em_gio_probe(struct platform_device *pdev)
 {
 	struct gpio_em_config *pdata = pdev->dev.platform_data;
 	struct em_gio_priv *p;
@@ -334,8 +299,11 @@ static int __devinit em_gio_probe(struct platform_device *pdev)
 	irq_chip->irq_set_type = em_gio_irq_set_type;
 	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE;
 
-	ret = em_gio_irq_domain_init(p);
-	if (ret) {
+	p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+					      pdata->number_of_pins,
+					      &em_gio_irq_domain_ops, p);
+	if (!p->irq_domain) {
+		ret = -ENXIO;
 		dev_err(&pdev->dev, "cannot initialize irq domain\n");
 		goto err3;
 	}
@@ -364,7 +332,7 @@ err6:
 err5:
 	free_irq(irq[0]->start, pdev);
 err4:
-	em_gio_irq_domain_cleanup(p);
+	irq_domain_remove(p->irq_domain);
 err3:
 	iounmap(p->base1);
 err2:
@@ -375,7 +343,7 @@ err0:
 	return ret;
 }
 
-static int __devexit em_gio_remove(struct platform_device *pdev)
+static int em_gio_remove(struct platform_device *pdev)
 {
 	struct em_gio_priv *p = platform_get_drvdata(pdev);
 	struct resource *irq[2];
@@ -390,7 +358,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
 
 	free_irq(irq[1]->start, pdev);
 	free_irq(irq[0]->start, pdev);
-	em_gio_irq_domain_cleanup(p);
+	irq_domain_remove(p->irq_domain);
 	iounmap(p->base1);
 	iounmap(p->base0);
 	kfree(p);
@@ -399,7 +367,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
 
 static struct platform_driver em_gio_device_driver = {
 	.probe		= em_gio_probe,
-	.remove		= __devexit_p(em_gio_remove),
+	.remove		= em_gio_remove,
 	.driver		= {
 		.name	= "em_gio",
 	}
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index 9fe5b8fe9be8..56b98eebe1fc 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -340,7 +340,7 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
 	return gpiochip_add(&bgc->gc);
 }
 
-static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
+static int ep93xx_gpio_probe(struct platform_device *pdev)
 {
 	struct ep93xx_gpio *ep93xx_gpio;
 	struct resource *res;
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index 82e2e4fe599e..05fcc0f247ca 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -444,7 +444,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 	return ret;
 }
 
-static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
+static int bgpio_pdev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *r;
@@ -507,7 +507,7 @@ static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
 	return gpiochip_add(&bgc->gc);
 }
 
-static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
+static int bgpio_pdev_remove(struct platform_device *pdev)
 {
 	struct bgpio_chip *bgc = platform_get_drvdata(pdev);
 
@@ -527,7 +527,7 @@ static struct platform_driver bgpio_driver = {
 	},
 	.id_table = bgpio_id_table,
 	.probe = bgpio_pdev_probe,
-	.remove = __devexit_p(bgpio_pdev_remove),
+	.remove = bgpio_pdev_remove,
 };
 
 module_platform_driver(bgpio_driver);
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index d4d617966696..6cc87ac8e019 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -238,7 +238,7 @@ static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
 	ichx_write_bit(GPIO_LVL, nr, val, 0);
 }
 
-static void __devinit ichx_gpiolib_setup(struct gpio_chip *chip)
+static void ichx_gpiolib_setup(struct gpio_chip *chip)
 {
 	chip->owner = THIS_MODULE;
 	chip->label = DRV_NAME;
@@ -313,7 +313,7 @@ static struct ichx_desc intel5_desc = {
 	.ngpio = 76,
 };
 
-static int __devinit ichx_gpio_request_regions(struct resource *res_base,
+static int ichx_gpio_request_regions(struct resource *res_base,
 						const char *name, u8 use_gpio)
 {
 	int i;
@@ -353,7 +353,7 @@ static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
 	}
 }
 
-static int __devinit ichx_gpio_probe(struct platform_device *pdev)
+static int ichx_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res_base, *res_pm;
 	int err;
@@ -442,7 +442,7 @@ add_err:
 	return err;
 }
 
-static int __devexit ichx_gpio_remove(struct platform_device *pdev)
+static int ichx_gpio_remove(struct platform_device *pdev)
 {
 	int err;
 
@@ -467,7 +467,7 @@ static struct platform_driver ichx_gpio_driver = {
 		.name	= DRV_NAME,
 	},
 	.probe		= ichx_gpio_probe,
-	.remove		= __devexit_p(ichx_gpio_remove),
+	.remove		= ichx_gpio_remove,
 };
 
 module_platform_driver(ichx_gpio_driver);
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
index f2f000dd70b3..7d0a04169a35 100644
--- a/drivers/gpio/gpio-janz-ttl.c
+++ b/drivers/gpio/gpio-janz-ttl.c
@@ -108,13 +108,13 @@ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
 	spin_unlock(&mod->lock);
 }
 
-static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
+static void ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
 {
 	iowrite16be(reg, &mod->regs->control);
 	iowrite16be(val, &mod->regs->control);
 }
 
-static void __devinit ttl_setup_device(struct ttl_module *mod)
+static void ttl_setup_device(struct ttl_module *mod)
 {
 	/* reset the device to a known state */
 	iowrite16be(0x0000, &mod->regs->control);
@@ -140,7 +140,7 @@ static void __devinit ttl_setup_device(struct ttl_module *mod)
 	ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
 }
 
-static int __devinit ttl_probe(struct platform_device *pdev)
+static int ttl_probe(struct platform_device *pdev)
 {
 	struct janz_platform_data *pdata;
 	struct device *dev = &pdev->dev;
@@ -211,7 +211,7 @@ out_return:
 	return ret;
 }
 
-static int __devexit ttl_remove(struct platform_device *pdev)
+static int ttl_remove(struct platform_device *pdev)
 {
 	struct ttl_module *mod = platform_get_drvdata(pdev);
 	struct device *dev = &pdev->dev;
@@ -234,7 +234,7 @@ static struct platform_driver ttl_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= ttl_probe,
-	.remove		= __devexit_p(ttl_remove),
+	.remove		= ttl_remove,
 };
 
 module_platform_driver(ttl_driver);
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
index 202a99207b7d..e77b2b3e94af 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -332,7 +332,7 @@ static const struct dev_pm_ops lnw_gpio_pm_ops = {
 	.runtime_idle = lnw_gpio_runtime_idle,
 };
 
-static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
+static int lnw_gpio_probe(struct pci_dev *pdev,
 			const struct pci_device_id *id)
 {
 	void *base;
@@ -435,7 +435,7 @@ static struct pci_driver lnw_gpio_driver = {
 };
 
 
-static int __devinit wp_gpio_probe(struct platform_device *pdev)
+static int wp_gpio_probe(struct platform_device *pdev)
 {
 	struct lnw_gpio *lnw;
 	struct gpio_chip *gc;
@@ -484,7 +484,7 @@ err_kmalloc:
 	return retval;
 }
 
-static int __devexit wp_gpio_remove(struct platform_device *pdev)
+static int wp_gpio_remove(struct platform_device *pdev)
 {
 	struct lnw_gpio *lnw = platform_get_drvdata(pdev);
 	int err;
@@ -499,7 +499,7 @@ static int __devexit wp_gpio_remove(struct platform_device *pdev)
 
 static struct platform_driver wp_gpio_driver = {
 	.probe		= wp_gpio_probe,
-	.remove		= __devexit_p(wp_gpio_remove),
+	.remove		= wp_gpio_remove,
 	.driver		= {
 		.name	= "wp_gpio",
 		.owner	= THIS_MODULE,
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 3644e0dcb3dd..36d7dee07b28 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -542,7 +542,7 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
 	return gpiospec->args[1];
 }
 
-static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
+static int lpc32xx_gpio_probe(struct platform_device *pdev)
 {
 	int i;
 
@@ -559,7 +559,7 @@ static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id lpc32xx_gpio_of_match[] __devinitdata = {
+static struct of_device_id lpc32xx_gpio_of_match[] = {
 	{ .compatible = "nxp,lpc3220-gpio", },
 	{ },
 };
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
index a5ca0ab1b372..4b6b9a04e326 100644
--- a/drivers/gpio/gpio-max7300.c
+++ b/drivers/gpio/gpio-max7300.c
@@ -31,7 +31,7 @@ static int max7300_i2c_read(struct device *dev, unsigned int reg)
 	return i2c_smbus_read_byte_data(client, reg);
 }
 
-static int __devinit max7300_probe(struct i2c_client *client,
+static int max7300_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct max7301 *ts;
@@ -55,7 +55,7 @@ static int __devinit max7300_probe(struct i2c_client *client,
 	return ret;
 }
 
-static int __devexit max7300_remove(struct i2c_client *client)
+static int max7300_remove(struct i2c_client *client)
 {
 	return __max730x_remove(&client->dev);
 }
@@ -72,7 +72,7 @@ static struct i2c_driver max7300_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max7300_probe,
-	.remove = __devexit_p(max7300_remove),
+	.remove = max7300_remove,
 	.id_table = max7300_id,
 };
 
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
index 741acfcbe761..c6c535c1310e 100644
--- a/drivers/gpio/gpio-max7301.c
+++ b/drivers/gpio/gpio-max7301.c
@@ -50,7 +50,7 @@ static int max7301_spi_read(struct device *dev, unsigned int reg)
 	return word & 0xff;
 }
 
-static int __devinit max7301_probe(struct spi_device *spi)
+static int max7301_probe(struct spi_device *spi)
 {
 	struct max7301 *ts;
 	int ret;
@@ -75,7 +75,7 @@ static int __devinit max7301_probe(struct spi_device *spi)
 	return ret;
 }
 
-static int __devexit max7301_remove(struct spi_device *spi)
+static int max7301_remove(struct spi_device *spi)
 {
 	return __max730x_remove(&spi->dev);
 }
@@ -92,7 +92,7 @@ static struct spi_driver max7301_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max7301_probe,
-	.remove = __devexit_p(max7301_remove),
+	.remove = max7301_remove,
 	.id_table = max7301_id,
 };
 
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
index 05e2dac60b3b..00092342b84c 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -160,17 +160,13 @@ static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
 	mutex_unlock(&ts->lock);
 }
 
-int __devinit __max730x_probe(struct max7301 *ts)
+int __max730x_probe(struct max7301 *ts)
 {
 	struct device *dev = ts->dev;
 	struct max7301_platform_data *pdata;
 	int i, ret;
 
 	pdata = dev->platform_data;
-	if (!pdata || !pdata->base) {
-		dev_err(dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
 
 	mutex_init(&ts->lock);
 	dev_set_drvdata(dev, ts);
@@ -178,7 +174,12 @@ int __devinit __max730x_probe(struct max7301 *ts)
 	/* Power up the chip and disable IRQ output */
 	ts->write(dev, 0x04, 0x01);
 
-	ts->input_pullup_active = pdata->input_pullup_active;
+	if (pdata) {
+		ts->input_pullup_active = pdata->input_pullup_active;
+		ts->chip.base = pdata->base;
+	} else {
+		ts->chip.base = -1;
+	}
 	ts->chip.label = dev->driver->name;
 
 	ts->chip.direction_input = max7301_direction_input;
@@ -186,7 +187,6 @@ int __devinit __max730x_probe(struct max7301 *ts)
 	ts->chip.direction_output = max7301_direction_output;
 	ts->chip.set = max7301_set;
 
-	ts->chip.base = pdata->base;
 	ts->chip.ngpio = PIN_NUMBER;
 	ts->chip.can_sleep = 1;
 	ts->chip.dev = dev;
@@ -226,7 +226,7 @@ exit_destroy:
 }
 EXPORT_SYMBOL_GPL(__max730x_probe);
 
-int __devexit __max730x_remove(struct device *dev)
+int __max730x_remove(struct device *dev)
 {
 	struct max7301 *ts = dev_get_drvdata(dev);
 	int ret;
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index 9504120812a5..1e0467ce4c37 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -526,7 +526,7 @@ static void max732x_irq_teardown(struct max732x_chip *chip)
 }
 #endif
 
-static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+static int max732x_setup_gpio(struct max732x_chip *chip,
 					const struct i2c_device_id *id,
 					unsigned gpio_start)
 {
@@ -574,7 +574,7 @@ static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
 	return port;
 }
 
-static int __devinit max732x_probe(struct i2c_client *client,
+static int max732x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct max732x_platform_data *pdata;
@@ -651,7 +651,7 @@ out_failed:
 	return ret;
 }
 
-static int __devexit max732x_remove(struct i2c_client *client)
+static int max732x_remove(struct i2c_client *client)
 {
 	struct max732x_platform_data *pdata = client->dev.platform_data;
 	struct max732x_chip *chip = i2c_get_clientdata(client);
@@ -690,7 +690,7 @@ static struct i2c_driver max732x_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max732x_probe,
-	.remove		= __devexit_p(max732x_remove),
+	.remove		= max732x_remove,
 	.id_table	= max732x_id,
 };
 
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 2de57ce5feb6..6a8fdc26ae6a 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -80,7 +80,7 @@ static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
 	mutex_unlock(&mc->lock);
 }
 
-static int __devinit mc33880_probe(struct spi_device *spi)
+static int mc33880_probe(struct spi_device *spi)
 {
 	struct mc33880 *mc;
 	struct mc33880_platform_data *pdata;
@@ -147,7 +147,7 @@ exit_destroy:
 	return ret;
 }
 
-static int __devexit mc33880_remove(struct spi_device *spi)
+static int mc33880_remove(struct spi_device *spi)
 {
 	struct mc33880 *mc;
 	int ret;
@@ -175,7 +175,7 @@ static struct spi_driver mc33880_driver = {
 		.owner		= THIS_MODULE,
 	},
 	.probe		= mc33880_probe,
-	.remove		= __devexit_p(mc33880_remove),
+	.remove		= mc33880_remove,
 };
 
 static int __init mc33880_init(void)
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 0f425189de11..3cea0ea79e80 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -77,7 +77,7 @@ struct mcp23s08_driver_data {
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
 {
@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 		break;
 #endif /* CONFIG_SPI_MASTER */
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 	case MCP_TYPE_008:
 		mcp->ops = &mcp23008_ops;
 		mcp->chip.ngpio = 8;
@@ -473,9 +473,9 @@ fail:
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
-static int __devinit mcp230xx_probe(struct i2c_client *client,
+static int mcp230xx_probe(struct i2c_client *client,
 				    const struct i2c_device_id *id)
 {
 	struct mcp23s08_platform_data *pdata;
@@ -508,7 +508,7 @@ fail:
 	return status;
 }
 
-static int __devexit mcp230xx_remove(struct i2c_client *client)
+static int mcp230xx_remove(struct i2c_client *client)
 {
 	struct mcp23s08 *mcp = i2c_get_clientdata(client);
 	int status;
@@ -533,7 +533,7 @@ static struct i2c_driver mcp230xx_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= mcp230xx_probe,
-	.remove		= __devexit_p(mcp230xx_remove),
+	.remove		= mcp230xx_remove,
 	.id_table	= mcp230xx_id,
 };
 
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 6a29ee1847be..b73366523fae 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -385,7 +385,7 @@ static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
 	return ret;
 }
 
-static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+static void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
 				unsigned int irq_start, unsigned int num)
 {
 	struct irq_chip_generic *gc;
@@ -406,7 +406,7 @@ static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
+static int ioh_gpio_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	int ret;
@@ -517,7 +517,7 @@ err_pci_enable:
 	return ret;
 }
 
-static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
+static void ioh_gpio_remove(struct pci_dev *pdev)
 {
 	int err;
 	int i;
@@ -606,7 +606,7 @@ static struct pci_driver ioh_gpio_driver = {
 	.name = "ml_ioh_gpio",
 	.id_table = ioh_gpio_pcidev_id,
 	.probe = ioh_gpio_probe,
-	.remove = __devexit_p(ioh_gpio_remove),
+	.remove = ioh_gpio_remove,
 	.suspend = ioh_gpio_suspend,
 	.resume = ioh_gpio_resume
 };
diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
index 2c7cef367fc0..42647f26c9e0 100644
--- a/drivers/gpio/gpio-mpc5200.c
+++ b/drivers/gpio/gpio-mpc5200.c
@@ -148,7 +148,7 @@ mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 	return 0;
 }
 
-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
+static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct mpc52xx_gpio_wkup __iomem *regs;
@@ -308,7 +308,7 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 	return 0;
 }
 
-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
+static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct gpio_chip *gc;
diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c
index b38986285868..27ea7b9257ff 100644
--- a/drivers/gpio/gpio-msic.c
+++ b/drivers/gpio/gpio-msic.c
@@ -256,7 +256,7 @@ static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 	chip->irq_eoi(data);
 }
 
-static int __devinit platform_msic_gpio_probe(struct platform_device *pdev)
+static int platform_msic_gpio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct intel_msic_gpio_pdata *pdata = dev->platform_data;
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index 38305beb4375..55a7e7769af6 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -352,7 +352,7 @@ static struct irq_chip msm_gpio_irq_chip = {
 	.irq_set_wake	= msm_gpio_irq_set_wake,
 };
 
-static int __devinit msm_gpio_probe(struct platform_device *dev)
+static int msm_gpio_probe(struct platform_device *dev)
 {
 	int i, irq, ret;
 
@@ -376,7 +376,7 @@ static int __devinit msm_gpio_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int __devexit msm_gpio_remove(struct platform_device *dev)
+static int msm_gpio_remove(struct platform_device *dev)
 {
 	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
 
@@ -390,7 +390,7 @@ static int __devexit msm_gpio_remove(struct platform_device *dev)
 
 static struct platform_driver msm_gpio_driver = {
 	.probe = msm_gpio_probe,
-	.remove = __devexit_p(msm_gpio_remove),
+	.remove = msm_gpio_remove,
 	.driver = {
 		.name = "msmgpio",
 		.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index cf7afb9eb61a..d767b534c4af 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
 	return mvchip->membase + GPIO_OUT_OFF;
 }
 
+static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
+{
+	return mvchip->membase + GPIO_BLINK_EN_OFF;
+}
+
 static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
 {
 	return mvchip->membase + GPIO_IO_CONF_OFF;
@@ -163,12 +168,12 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
  * Functions implementing the gpio_chip methods
  */
 
-int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
+static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
 {
 	return pinctrl_request_gpio(chip->base + pin);
 }
 
-void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
+static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
 {
 	pinctrl_free_gpio(chip->base + pin);
 }
@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
 	return (u >> pin) & 1;
 }
 
+static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
+{
+	struct mvebu_gpio_chip *mvchip =
+		container_of(chip, struct mvebu_gpio_chip, chip);
+	unsigned long flags;
+	u32 u;
+
+	spin_lock_irqsave(&mvchip->lock, flags);
+	u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+	if (value)
+		u |= 1 << pin;
+	else
+		u &= ~(1 << pin);
+	writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
+	spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
 static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
 	struct mvebu_gpio_chip *mvchip =
@@ -244,6 +266,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
 	if (ret)
 		return ret;
 
+	mvebu_gpio_blink(chip, pin, 0);
 	mvebu_gpio_set(chip, pin, value);
 
 	spin_lock_irqsave(&mvchip->lock, flags);
@@ -459,7 +482,7 @@ static struct platform_device_id mvebu_gpio_ids[] = {
 };
 MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
 
-static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
+static struct of_device_id mvebu_gpio_of_match[] = {
 	{
 		.compatible = "marvell,orion-gpio",
 		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
@@ -478,7 +501,7 @@ static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
 
-static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
+static int mvebu_gpio_probe(struct platform_device *pdev)
 {
 	struct mvebu_gpio_chip *mvchip;
 	const struct of_device_id *match;
@@ -523,6 +546,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
 	mvchip->chip.label = dev_name(&pdev->dev);
 	mvchip->chip.dev = &pdev->dev;
 	mvchip->chip.request = mvebu_gpio_request;
+	mvchip->chip.free = mvebu_gpio_free;
 	mvchip->chip.direction_input = mvebu_gpio_direction_input;
 	mvchip->chip.get = mvebu_gpio_get;
 	mvchip->chip.direction_output = mvebu_gpio_direction_output;
@@ -650,8 +674,8 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
 			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
 	/* Setup irq domain on top of the generic chip. */
-	mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
-					       mvchip->irqbase, 0,
+	mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio,
+					       mvchip->irqbase,
 					       &irq_domain_simple_ops,
 					       mvchip);
 	if (!mvchip->domain) {
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 80f44bb64a87..7877335c4cc8 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -356,7 +356,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
 			       IRQ_NOREQUEST, 0);
 }
 
-static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
+static void mxc_gpio_get_hw(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(mxc_gpio_dt_ids, &pdev->dev);
@@ -395,7 +395,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 	return irq_find_mapping(port->domain, offset);
 }
 
-static int __devinit mxc_gpio_probe(struct platform_device *pdev)
+static int mxc_gpio_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct mxc_gpio_port *port;
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index 796fb13e4815..fa2a63cad32e 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -214,7 +214,7 @@ static const struct of_device_id mxs_gpio_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
 
-static int __devinit mxs_gpio_probe(struct platform_device *pdev)
+static int mxs_gpio_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
 			of_match_device(mxs_gpio_dt_ids, &pdev->dev);
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index d335af1d4d85..f1fbedb2a6f9 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1012,7 +1012,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
 		dev_err(bank->dev, "Could not get gpio dbck\n");
 }
 
-static __devinit void
+static void
 omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
 		    unsigned int num)
 {
@@ -1041,7 +1041,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
+static void omap_gpio_chip_init(struct gpio_bank *bank)
 {
 	int j;
 	static int gpio;
@@ -1089,7 +1089,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
 
 static const struct of_device_id omap_gpio_match[];
 
-static int __devinit omap_gpio_probe(struct platform_device *pdev)
+static int omap_gpio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
@@ -1105,7 +1105,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	if (!pdata)
 		return -EINVAL;
 
-	bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
+	bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
 	if (!bank) {
 		dev_err(dev, "Memory alloc failed\n");
 		return -ENOMEM;
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 9c693ae17956..cc102d25ee24 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -16,6 +16,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/slab.h>
@@ -83,6 +84,7 @@ struct pca953x_chip {
 	u32 irq_trig_raise;
 	u32 irq_trig_fall;
 	int	 irq_base;
+	struct irq_domain *domain;
 #endif
 
 	struct i2c_client *client;
@@ -333,14 +335,14 @@ static void pca953x_irq_mask(struct irq_data *d)
 {
 	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
+	chip->irq_mask &= ~(1 << d->hwirq);
 }
 
 static void pca953x_irq_unmask(struct irq_data *d)
 {
 	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-	chip->irq_mask |= 1 << (d->irq - chip->irq_base);
+	chip->irq_mask |= 1 << d->hwirq;
 }
 
 static void pca953x_irq_bus_lock(struct irq_data *d)
@@ -372,8 +374,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
 static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
-	u32 level = d->irq - chip->irq_base;
-	u32 mask = 1 << level;
+	u32 mask = 1 << d->hwirq;
 
 	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
 		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
@@ -454,7 +455,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
 
 	do {
 		level = __ffs(pending);
-		handle_nested_irq(level + chip->irq_base);
+		handle_nested_irq(irq_find_mapping(chip->domain, level));
 
 		pending &= ~(1 << level);
 	} while (pending);
@@ -499,6 +500,17 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 		if (chip->irq_base < 0)
 			goto out_failed;
 
+		chip->domain = irq_domain_add_legacy(client->dev.of_node,
+						chip->gpio_chip.ngpio,
+						chip->irq_base,
+						0,
+						&irq_domain_simple_ops,
+						NULL);
+		if (!chip->domain) {
+			ret = -ENODEV;
+			goto out_irqdesc_free;
+		}
+
 		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
 			int irq = lvl + chip->irq_base;
 
@@ -521,7 +533,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 		if (ret) {
 			dev_err(&client->dev, "failed to request irq %d\n",
 				client->irq);
-			goto out_failed;
+			goto out_irqdesc_free;
 		}
 
 		chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
@@ -529,6 +541,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 
 	return 0;
 
+out_irqdesc_free:
+	irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
 out_failed:
 	chip->irq_base = -1;
 	return ret;
@@ -602,7 +616,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
 }
 #endif
 
-static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
 {
 	int ret;
 
@@ -621,7 +635,7 @@ out:
 	return ret;
 }
 
-static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
 {
 	int ret;
 	u32 val = 0;
@@ -652,7 +666,7 @@ out:
 	return ret;
 }
 
-static int __devinit pca953x_probe(struct i2c_client *client,
+static int pca953x_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
 	struct pca953x_platform_data *pdata;
@@ -751,9 +765,38 @@ static int pca953x_remove(struct i2c_client *client)
 	return 0;
 }
 
+static const struct of_device_id pca953x_dt_ids[] = {
+	{ .compatible = "nxp,pca9534", },
+	{ .compatible = "nxp,pca9535", },
+	{ .compatible = "nxp,pca9536", },
+	{ .compatible = "nxp,pca9537", },
+	{ .compatible = "nxp,pca9538", },
+	{ .compatible = "nxp,pca9539", },
+	{ .compatible = "nxp,pca9554", },
+	{ .compatible = "nxp,pca9555", },
+	{ .compatible = "nxp,pca9556", },
+	{ .compatible = "nxp,pca9557", },
+	{ .compatible = "nxp,pca9574", },
+	{ .compatible = "nxp,pca9575", },
+
+	{ .compatible = "maxim,max7310", },
+	{ .compatible = "maxim,max7312", },
+	{ .compatible = "maxim,max7313", },
+	{ .compatible = "maxim,max7315", },
+
+	{ .compatible = "ti,pca6107", },
+	{ .compatible = "ti,tca6408", },
+	{ .compatible = "ti,tca6416", },
+	{ .compatible = "ti,tca6424", },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, pca953x_dt_ids);
+
 static struct i2c_driver pca953x_driver = {
 	.driver = {
 		.name	= "pca953x",
+		.of_match_table = pca953x_dt_ids,
 	},
 	.probe		= pca953x_probe,
 	.remove		= pca953x_remove,
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 16af35cd2b10..a19b7457a726 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -223,11 +223,11 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
 
 static int pcf857x_irq_domain_init(struct pcf857x *gpio,
 				   struct pcf857x_platform_data *pdata,
-				   struct device *dev)
+				   struct i2c_client *client)
 {
 	int status;
 
-	gpio->irq_domain = irq_domain_add_linear(dev->of_node,
+	gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
 						 gpio->chip.ngpio,
 						 &pcf857x_irq_domain_ops,
 						 NULL);
@@ -235,15 +235,15 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
 		goto fail;
 
 	/* enable real irq */
-	status = request_irq(pdata->irq, pcf857x_irq_demux, 0,
-			     dev_name(dev), gpio);
+	status = request_irq(client->irq, pcf857x_irq_demux, 0,
+			     dev_name(&client->dev), gpio);
 	if (status)
 		goto fail;
 
 	/* enable gpio_to_irq() */
 	INIT_WORK(&gpio->work, pcf857x_irq_demux_work);
 	gpio->chip.to_irq	= pcf857x_to_irq;
-	gpio->irq		= pdata->irq;
+	gpio->irq		= client->irq;
 
 	return 0;
 
@@ -285,8 +285,8 @@ static int pcf857x_probe(struct i2c_client *client,
 	gpio->chip.ngpio		= id->driver_data;
 
 	/* enable gpio_to_irq() if platform has settings */
-	if (pdata && pdata->irq) {
-		status = pcf857x_irq_domain_init(gpio, pdata, &client->dev);
+	if (pdata && client->irq) {
+		status = pcf857x_irq_domain_init(gpio, pdata, client);
 		if (status < 0) {
 			dev_err(&client->dev, "irq_domain init failed\n");
 			goto fail;
@@ -368,15 +368,6 @@ static int pcf857x_probe(struct i2c_client *client,
 	if (status < 0)
 		goto fail;
 
-	/* NOTE: these chips can issue "some pin-changed" IRQs, which we
-	 * don't yet even try to use.  Among other issues, the relevant
-	 * genirq state isn't available to modular drivers; and most irq
-	 * methods can't be called from sleeping contexts.
-	 */
-
-	dev_info(&client->dev, "%s\n",
-			client->irq ? " (irq ignored)" : "");
-
 	/* Let platform code set up the GPIOs and their users.
 	 * Now is the first time anyone could use them.
 	 */
@@ -388,13 +379,15 @@ static int pcf857x_probe(struct i2c_client *client,
 			dev_warn(&client->dev, "setup --> %d\n", status);
 	}
 
+	dev_info(&client->dev, "probed\n");
+
 	return 0;
 
 fail:
 	dev_dbg(&client->dev, "probe error %d for '%s'\n",
 			status, client->name);
 
-	if (pdata && pdata->irq)
+	if (pdata && client->irq)
 		pcf857x_irq_domain_cleanup(gpio);
 
 	kfree(gpio);
@@ -418,7 +411,7 @@ static int pcf857x_remove(struct i2c_client *client)
 		}
 	}
 
-	if (pdata && pdata->irq)
+	if (pdata && client->irq)
 		pcf857x_irq_domain_cleanup(gpio);
 
 	status = gpiochip_remove(&gpio->chip);
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 4ad0c4f9171c..cdf599687cf7 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -215,6 +215,7 @@ static void pch_gpio_setup(struct pch_gpio *chip)
 	struct gpio_chip *gpio = &chip->gpio;
 
 	gpio->label = dev_name(chip->dev);
+	gpio->dev = chip->dev;
 	gpio->owner = THIS_MODULE;
 	gpio->direction_input = pch_gpio_direction_input;
 	gpio->get = pch_gpio_get;
@@ -325,7 +326,7 @@ static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
 	return ret;
 }
 
-static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+static void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
 				unsigned int irq_start, unsigned int num)
 {
 	struct irq_chip_generic *gc;
@@ -345,7 +346,7 @@ static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
 			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static int __devinit pch_gpio_probe(struct pci_dev *pdev,
+static int pch_gpio_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
 	s32 ret;
@@ -442,7 +443,7 @@ err_pci_enable:
 	return ret;
 }
 
-static void __devexit pch_gpio_remove(struct pci_dev *pdev)
+static void pch_gpio_remove(struct pci_dev *pdev)
 {
 	int err;
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
@@ -531,7 +532,7 @@ static struct pci_driver pch_gpio_driver = {
 	.name = "pch_gpio",
 	.id_table = pch_gpio_pcidev_id,
 	.probe = pch_gpio_probe,
-	.remove = __devexit_p(pch_gpio_remove),
+	.remove = pch_gpio_remove,
 	.suspend = pch_gpio_suspend,
 	.resume = pch_gpio_resume
 };
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b4b5da4fd2cc..c1720de18a4f 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -48,12 +48,7 @@ struct pl061_context_save_regs {
 #endif
 
 struct pl061_gpio {
-	/* Each of the two spinlocks protects a different set of hardware
-	 * regiters and data structurs. This decouples the code of the IRQ from
-	 * the GPIO code. This also makes the case of a GPIO routine call from
-	 * the IRQ code simpler.
-	 */
-	spinlock_t		lock;		/* GPIO registers */
+	spinlock_t		lock;
 
 	void __iomem		*base;
 	int			irq_base;
@@ -216,39 +211,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
 			       IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
 }
 
-static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 {
-	struct pl061_platform_data *pdata;
+	struct device *dev = &adev->dev;
+	struct pl061_platform_data *pdata = dev->platform_data;
 	struct pl061_gpio *chip;
 	int ret, irq, i;
 
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
-	pdata = dev->dev.platform_data;
 	if (pdata) {
 		chip->gc.base = pdata->gpio_base;
 		chip->irq_base = pdata->irq_base;
-	} else if (dev->dev.of_node) {
+	} else if (adev->dev.of_node) {
 		chip->gc.base = -1;
 		chip->irq_base = 0;
-	} else {
-		ret = -ENODEV;
-		goto free_mem;
-	}
+	} else
+		return -ENODEV;
 
-	if (!request_mem_region(dev->res.start,
-				resource_size(&dev->res), "pl061")) {
-		ret = -EBUSY;
-		goto free_mem;
-	}
+	if (!devm_request_mem_region(dev, adev->res.start,
+				resource_size(&adev->res), "pl061"))
+		return -EBUSY;
 
-	chip->base = ioremap(dev->res.start, resource_size(&dev->res));
-	if (chip->base == NULL) {
-		ret = -ENOMEM;
-		goto release_region;
-	}
+	chip->base = devm_ioremap(dev, adev->res.start,
+				resource_size(&adev->res));
+	if (chip->base == NULL)
+		return -ENOMEM;
 
 	spin_lock_init(&chip->lock);
 
@@ -258,13 +248,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 	chip->gc.set = pl061_set_value;
 	chip->gc.to_irq = pl061_to_irq;
 	chip->gc.ngpio = PL061_GPIO_NR;
-	chip->gc.label = dev_name(&dev->dev);
-	chip->gc.dev = &dev->dev;
+	chip->gc.label = dev_name(dev);
+	chip->gc.dev = dev;
 	chip->gc.owner = THIS_MODULE;
 
 	ret = gpiochip_add(&chip->gc);
 	if (ret)
-		goto iounmap;
+		return ret;
 
 	/*
 	 * irq_chip support
@@ -276,11 +266,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 	pl061_init_gc(chip, chip->irq_base);
 
 	writeb(0, chip->base + GPIOIE); /* disable irqs */
-	irq = dev->irq[0];
-	if (irq < 0) {
-		ret = -ENODEV;
-		goto iounmap;
-	}
+	irq = adev->irq[0];
+	if (irq < 0)
+		return -ENODEV;
+
 	irq_set_chained_handler(irq, pl061_irq_handler);
 	irq_set_handler_data(irq, chip);
 
@@ -294,18 +283,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 		}
 	}
 
-	amba_set_drvdata(dev, chip);
+	amba_set_drvdata(adev, chip);
 
 	return 0;
-
-iounmap:
-	iounmap(chip->base);
-release_region:
-	release_mem_region(dev->res.start, resource_size(&dev->res));
-free_mem:
-	kfree(chip);
-
-	return ret;
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 98d52cb3fd1a..8325f580c0f1 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -250,7 +250,7 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc,
 }
 #endif
 
-static int __devinit pxa_init_gpio_chip(int gpio_end,
+static int pxa_init_gpio_chip(int gpio_end,
 					int (*set_wake)(unsigned int, unsigned int))
 {
 	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
@@ -448,7 +448,7 @@ static int pxa_gpio_nums(void)
 	} else if (cpu_is_pxa27x()) {
 		count = 120;
 		gpio_type = PXA27X_GPIO;
-	} else if (cpu_is_pxa93x() || cpu_is_pxa95x()) {
+	} else if (cpu_is_pxa93x()) {
 		count = 191;
 		gpio_type = PXA93X_GPIO;
 	} else if (cpu_is_pxa3xx()) {
@@ -490,7 +490,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
 	.xlate	= irq_domain_xlate_twocell,
 };
 
-static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
+static int pxa_gpio_probe_dt(struct platform_device *pdev)
 {
 	int ret, nr_banks, nr_gpios;
 	struct device_node *prev, *next, *np = pdev->dev.of_node;
@@ -537,7 +537,7 @@ err:
 #define pxa_gpio_probe_dt(pdev)		(-1)
 #endif
 
-static int __devinit pxa_gpio_probe(struct platform_device *pdev)
+static int pxa_gpio_probe(struct platform_device *pdev)
 {
 	struct pxa_gpio_chip *c;
 	struct resource *res;
diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
index 08428bf17718..e63d6a397e17 100644
--- a/drivers/gpio/gpio-rc5t583.c
+++ b/drivers/gpio/gpio-rc5t583.c
@@ -111,7 +111,7 @@ static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset)
 	rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
 }
 
-static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
+static int rc5t583_gpio_probe(struct platform_device *pdev)
 {
 	struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
 	struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -146,7 +146,7 @@ static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
 	return gpiochip_add(&rc5t583_gpio->gpio_chip);
 }
 
-static int __devexit rc5t583_gpio_remove(struct platform_device *pdev)
+static int rc5t583_gpio_remove(struct platform_device *pdev)
 {
 	struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
 
@@ -159,7 +159,7 @@ static struct platform_driver rc5t583_gpio_driver = {
 		.owner   = THIS_MODULE,
 	},
 	.probe		= rc5t583_gpio_probe,
-	.remove		= __devexit_p(rc5t583_gpio_remove),
+	.remove		= rc5t583_gpio_remove,
 };
 
 static int __init rc5t583_gpio_init(void)
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index b62d443e9a59..1bf55f67f7a5 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -128,7 +128,7 @@ static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 /*
  * Cache the initial value of both GPIO data registers
  */
-static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
+static int rdc321x_gpio_probe(struct platform_device *pdev)
 {
 	int err;
 	struct resource *r;
@@ -206,7 +206,7 @@ out_free:
 	return err;
 }
 
-static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
+static int rdc321x_gpio_remove(struct platform_device *pdev)
 {
 	int ret;
 	struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
@@ -225,7 +225,7 @@ static struct platform_driver rdc321x_gpio_driver = {
 	.driver.name	= "rdc321x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= rdc321x_gpio_probe,
-	.remove		= __devexit_p(rdc321x_gpio_remove),
+	.remove		= rdc321x_gpio_remove,
 };
 
 module_platform_driver(rdc321x_gpio_driver);
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index a006f0db15af..01f7fe955590 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -42,12 +42,6 @@
 #include <plat/gpio-fns.h>
 #include <plat/pm.h>
 
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
 int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
 				unsigned int off, samsung_gpio_pull_t pull)
 {
@@ -596,10 +590,13 @@ static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
 	unsigned long con;
 
 	con = __raw_readl(base + GPIOCON_OFF);
-	con &= ~(0xf << con_4bit_shift(offset));
+	if (ourchip->bitmap_gpio_int & BIT(offset))
+		con |= 0xf << con_4bit_shift(offset);
+	else
+		con &= ~(0xf << con_4bit_shift(offset));
 	__raw_writel(con, base + GPIOCON_OFF);
 
-	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+	pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
 
 	return 0;
 }
@@ -627,7 +624,7 @@ static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
 	__raw_writel(con, base + GPIOCON_OFF);
 	__raw_writel(dat, base + GPIODAT_OFF);
 
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 
 	return 0;
 }
@@ -671,7 +668,7 @@ static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
 	con &= ~(0xf << con_4bit_shift(offset));
 	__raw_writel(con, regcon);
 
-	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+	pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
 
 	return 0;
 }
@@ -706,7 +703,7 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
 	__raw_writel(con, regcon);
 	__raw_writel(dat, base + GPIODAT_OFF);
 
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 
 	return 0;
 }
@@ -926,10 +923,10 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
 #ifdef CONFIG_PM
 	if (chip->pm != NULL) {
 		if (!chip->pm->save || !chip->pm->resume)
-			printk(KERN_ERR "gpio: %s has missing PM functions\n",
+			pr_err("gpio: %s has missing PM functions\n",
 			       gc->label);
 	} else
-		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+		pr_err("gpio: %s has no PM function\n", gc->label);
 #endif
 
 	/* gpiochip_add() prints own failure message on error. */
@@ -1081,6 +1078,8 @@ static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip
 		if ((base != NULL) && (chip->base == NULL))
 			chip->base = base + ((i) * 0x20);
 
+		chip->bitmap_gpio_int = 0;
+
 		samsung_gpiolib_add(chip);
 	}
 }
@@ -2797,27 +2796,6 @@ static __init void exynos4_gpiolib_init(void)
 	int group = 0;
 	void __iomem *gpx_base;
 
-#ifdef CONFIG_PINCTRL_SAMSUNG
-		/*
-		 * This gpio driver includes support for device tree support and
-		 * there are platforms using it. In order to maintain
-		 * compatibility with those platforms, and to allow non-dt
-		 * Exynos4210 platforms to use this gpiolib support, a check
-		 * is added to find out if there is a active pin-controller
-		 * driver support available. If it is available, this gpiolib
-		 * support is ignored and the gpiolib support available in
-		 * pin-controller driver is used. This is a temporary check and
-		 * will go away when all of the Exynos4210 platforms have
-		 * switched to using device tree and the pin-ctrl driver.
-		 */
-		struct device_node *pctrl_np;
-		const char *pctrl_compat = "samsung,pinctrl-exynos4210";
-		pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat);
-		if (pctrl_np)
-			if (of_device_is_available(pctrl_np))
-				return;
-#endif
-
 	/* gpio part1 */
 	gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
 	if (gpio_base1 == NULL) {
@@ -3032,6 +3010,28 @@ static __init int samsung_gpiolib_init(void)
 	int i, nr_chips;
 	int group = 0;
 
+#ifdef CONFIG_PINCTRL_SAMSUNG
+	/*
+	* This gpio driver includes support for device tree support and there
+	* are platforms using it. In order to maintain compatibility with those
+	* platforms, and to allow non-dt Exynos4210 platforms to use this
+	* gpiolib support, a check is added to find out if there is a active
+	* pin-controller driver support available. If it is available, this
+	* gpiolib support is ignored and the gpiolib support available in
+	* pin-controller driver is used. This is a temporary check and will go
+	* away when all of the Exynos4210 platforms have switched to using
+	* device tree and the pin-ctrl driver.
+	*/
+	struct device_node *pctrl_np;
+	static const struct of_device_id exynos_pinctrl_ids[] = {
+		{ .compatible = "samsung,pinctrl-exynos4210", },
+		{ .compatible = "samsung,pinctrl-exynos4x12", },
+	};
+	for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
+		if (pctrl_np && of_device_is_available(pctrl_np))
+			return -ENODEV;
+#endif
+
 	samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
 
 	if (soc_is_s3c24xx()) {
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index 8707d4572a06..edae963f4625 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -185,7 +185,7 @@ static struct gpio_chip sch_gpio_resume = {
 	.set			= sch_gpio_resume_set,
 };
 
-static int __devinit sch_gpio_probe(struct platform_device *pdev)
+static int sch_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	int err, id;
@@ -271,7 +271,7 @@ err_sch_gpio_core:
 	return err;
 }
 
-static int __devexit sch_gpio_remove(struct platform_device *pdev)
+static int sch_gpio_remove(struct platform_device *pdev)
 {
 	struct resource *res;
 	if (gpio_ba) {
@@ -303,7 +303,7 @@ static struct platform_driver sch_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe		= sch_gpio_probe,
-	.remove		= __devexit_p(sch_gpio_remove),
+	.remove		= sch_gpio_remove,
 };
 
 module_platform_driver(sch_gpio_driver);
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index e25f73130b40..88f374ac7753 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -129,7 +129,7 @@ static struct irq_domain_ops irq_domain_sdv_ops = {
 	.xlate = sdv_xlate,
 };
 
-static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
+static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
 		struct pci_dev *pdev)
 {
 	struct irq_chip_type *ct;
@@ -186,7 +186,7 @@ out_free_desc:
 	return ret;
 }
 
-static int __devinit sdv_gpio_probe(struct pci_dev *pdev,
+static int sdv_gpio_probe(struct pci_dev *pdev,
 					const struct pci_device_id *pci_id)
 {
 	struct sdv_gpio_chip_data *sd;
diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c
new file mode 100644
index 000000000000..5f45fc4ed5d1
--- /dev/null
+++ b/drivers/gpio/gpio-spear-spics.c
@@ -0,0 +1,217 @@
+/*
+ * SPEAr platform SPI chipselect abstraction over gpiolib
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+/* maximum chipselects */
+#define NUM_OF_GPIO	4
+
+/*
+ * Provision is available on some SPEAr SoCs to control ARM PL022 spi cs
+ * through system registers. This register lies outside spi (pl022)
+ * address space into system registers.
+ *
+ * It provides control for spi chip select lines so that any chipselect
+ * (out of 4 possible chipselects in pl022) can be made low to select
+ * the particular slave.
+ */
+
+/**
+ * struct spear_spics - represents spi chip select control
+ * @base: base address
+ * @perip_cfg: configuration register
+ * @sw_enable_bit: bit to enable s/w control over chipselects
+ * @cs_value_bit: bit to program high or low chipselect
+ * @cs_enable_mask: mask to select bits required to select chipselect
+ * @cs_enable_shift: bit pos of cs_enable_mask
+ * @use_count: use count of a spi controller cs lines
+ * @last_off: stores last offset caller of set_value()
+ * @chip: gpio_chip abstraction
+ */
+struct spear_spics {
+	void __iomem		*base;
+	u32			perip_cfg;
+	u32			sw_enable_bit;
+	u32			cs_value_bit;
+	u32			cs_enable_mask;
+	u32			cs_enable_shift;
+	unsigned long		use_count;
+	int			last_off;
+	struct gpio_chip	chip;
+};
+
+/* gpio framework specific routines */
+static int spics_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	return -ENXIO;
+}
+
+static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct spear_spics *spics = container_of(chip, struct spear_spics,
+			chip);
+	u32 tmp;
+
+	/* select chip select from register */
+	tmp = readl_relaxed(spics->base + spics->perip_cfg);
+	if (spics->last_off != offset) {
+		spics->last_off = offset;
+		tmp &= ~(spics->cs_enable_mask << spics->cs_enable_shift);
+		tmp |= offset << spics->cs_enable_shift;
+	}
+
+	/* toggle chip select line */
+	tmp &= ~(0x1 << spics->cs_value_bit);
+	tmp |= value << spics->cs_value_bit;
+	writel_relaxed(tmp, spics->base + spics->perip_cfg);
+}
+
+static int spics_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return -ENXIO;
+}
+
+static int spics_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	spics_set_value(chip, offset, value);
+	return 0;
+}
+
+static int spics_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct spear_spics *spics = container_of(chip, struct spear_spics,
+			chip);
+	u32 tmp;
+
+	if (!spics->use_count++) {
+		tmp = readl_relaxed(spics->base + spics->perip_cfg);
+		tmp |= 0x1 << spics->sw_enable_bit;
+		tmp |= 0x1 << spics->cs_value_bit;
+		writel_relaxed(tmp, spics->base + spics->perip_cfg);
+	}
+
+	return 0;
+}
+
+static void spics_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct spear_spics *spics = container_of(chip, struct spear_spics,
+			chip);
+	u32 tmp;
+
+	if (!--spics->use_count) {
+		tmp = readl_relaxed(spics->base + spics->perip_cfg);
+		tmp &= ~(0x1 << spics->sw_enable_bit);
+		writel_relaxed(tmp, spics->base + spics->perip_cfg);
+	}
+}
+
+static int spics_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct spear_spics *spics;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+		return -EBUSY;
+	}
+
+	spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
+	if (!spics) {
+		dev_err(&pdev->dev, "memory allocation fail\n");
+		return -ENOMEM;
+	}
+
+	spics->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!spics->base) {
+		dev_err(&pdev->dev, "request and ioremap fail\n");
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32(np, "st-spics,peripcfg-reg",
+				&spics->perip_cfg))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,sw-enable-bit",
+				&spics->sw_enable_bit))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,cs-value-bit",
+				&spics->cs_value_bit))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,cs-enable-mask",
+				&spics->cs_enable_mask))
+		goto err_dt_data;
+	if (of_property_read_u32(np, "st-spics,cs-enable-shift",
+				&spics->cs_enable_shift))
+		goto err_dt_data;
+
+	platform_set_drvdata(pdev, spics);
+
+	spics->chip.ngpio = NUM_OF_GPIO;
+	spics->chip.base = -1;
+	spics->chip.request = spics_request;
+	spics->chip.free = spics_free;
+	spics->chip.direction_input = spics_direction_input;
+	spics->chip.direction_output = spics_direction_output;
+	spics->chip.get = spics_get_value;
+	spics->chip.set = spics_set_value;
+	spics->chip.label = dev_name(&pdev->dev);
+	spics->chip.dev = &pdev->dev;
+	spics->chip.owner = THIS_MODULE;
+	spics->last_off = -1;
+
+	ret = gpiochip_add(&spics->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpio chip\n");
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "spear spics registered\n");
+	return 0;
+
+err_dt_data:
+	dev_err(&pdev->dev, "DT probe failed\n");
+	return -EINVAL;
+}
+
+static const struct of_device_id spics_gpio_of_match[] = {
+	{ .compatible = "st,spear-spics-gpio" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, spics_gpio_of_match);
+
+static struct platform_driver spics_gpio_driver = {
+	.probe = spics_gpio_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "spear-spics-gpio",
+		.of_match_table = spics_gpio_of_match,
+	},
+};
+
+static int __init spics_gpio_init(void)
+{
+	return platform_driver_register(&spics_gpio_driver);
+}
+subsys_initcall(spics_gpio_init);
+
+MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c
index 6064fb376e11..558542552aae 100644
--- a/drivers/gpio/gpio-sta2x11.c
+++ b/drivers/gpio/gpio-sta2x11.c
@@ -320,7 +320,7 @@ static irqreturn_t gsta_gpio_handler(int irq, void *dev_id)
 	return ret;
 }
 
-static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
+static void gsta_alloc_irq_chip(struct gsta_gpio *chip)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
@@ -353,7 +353,7 @@ static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
 }
 
 /* The platform device used here is instantiated by the MFD device */
-static int __devinit gsta_probe(struct platform_device *dev)
+static int gsta_probe(struct platform_device *dev)
 {
 	int i, err;
 	struct pci_dev *pdev;
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index dce34727bbf8..770476a9da87 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -11,7 +11,9 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
 #include <linux/mfd/stmpe.h>
 
 /*
@@ -28,6 +30,7 @@ struct stmpe_gpio {
 	struct stmpe *stmpe;
 	struct device *dev;
 	struct mutex irq_lock;
+	struct irq_domain *domain;
 
 	int irq_base;
 	unsigned norequest_mask;
@@ -103,7 +106,7 @@ static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
 
-	return stmpe_gpio->irq_base + offset;
+	return irq_create_mapping(stmpe_gpio->domain, offset);
 }
 
 static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -132,7 +135,7 @@ static struct gpio_chip template_chip = {
 static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - stmpe_gpio->irq_base;
+	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -199,7 +202,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
 static void stmpe_gpio_irq_mask(struct irq_data *d)
 {
 	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - stmpe_gpio->irq_base;
+	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -209,7 +212,7 @@ static void stmpe_gpio_irq_mask(struct irq_data *d)
 static void stmpe_gpio_irq_unmask(struct irq_data *d)
 {
 	struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - stmpe_gpio->irq_base;
+	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -251,8 +254,9 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = bank * 8 + bit;
+			int virq = irq_find_mapping(stmpe_gpio->domain, line);
 
-			handle_nested_irq(stmpe_gpio->irq_base + line);
+			handle_nested_irq(virq);
 			stat &= ~(1 << bit);
 		}
 
@@ -267,43 +271,61 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
+		       irq_hw_number_t hwirq)
 {
-	int base = stmpe_gpio->irq_base;
-	int irq;
+	struct stmpe_gpio *stmpe_gpio = d->host_data;
+
+	if (!stmpe_gpio)
+		return -EINVAL;
 
-	for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
-		irq_set_chip_data(irq, stmpe_gpio);
-		irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
-					 handle_simple_irq);
-		irq_set_nested_thread(irq, 1);
+	irq_set_chip_data(hwirq, stmpe_gpio);
+	irq_set_chip_and_handler(hwirq, &stmpe_gpio_irq_chip,
+				 handle_simple_irq);
+	irq_set_nested_thread(hwirq, 1);
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
+	set_irq_flags(hwirq, IRQF_VALID);
 #else
-		irq_set_noprobe(irq);
+	irq_set_noprobe(hwirq);
 #endif
-	}
 
 	return 0;
 }
 
-static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
+void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
 {
-	int base = stmpe_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
+	set_irq_flags(virq, 0);
 #endif
-		irq_set_chip_and_handler(irq, NULL, NULL);
-		irq_set_chip_data(irq, NULL);
+	irq_set_chip_and_handler(virq, NULL, NULL);
+	irq_set_chip_data(virq, NULL);
+}
+
+static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
+	.unmap = stmpe_gpio_irq_unmap,
+	.map = stmpe_gpio_irq_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+{
+	int base = stmpe_gpio->irq_base;
+
+	stmpe_gpio->domain = irq_domain_add_simple(NULL,
+				stmpe_gpio->chip.ngpio, base,
+				&stmpe_gpio_irq_simple_ops, stmpe_gpio);
+	if (!stmpe_gpio->domain) {
+		dev_err(stmpe_gpio->dev, "failed to create irqdomain\n");
+		return -ENOSYS;
 	}
+
+	return 0;
 }
 
-static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
+static int stmpe_gpio_probe(struct platform_device *pdev)
 {
 	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+	struct device_node *np = pdev->dev.of_node;
 	struct stmpe_gpio_platform_data *pdata;
 	struct stmpe_gpio *stmpe_gpio;
 	int ret;
@@ -321,13 +343,17 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
 
 	stmpe_gpio->dev = &pdev->dev;
 	stmpe_gpio->stmpe = stmpe;
-	stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0;
-
 	stmpe_gpio->chip = template_chip;
 	stmpe_gpio->chip.ngpio = stmpe->num_gpios;
 	stmpe_gpio->chip.dev = &pdev->dev;
 	stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
 
+	if (pdata)
+		stmpe_gpio->norequest_mask = pdata->norequest_mask;
+	else if (np)
+		of_property_read_u32(np, "st,norequest-mask",
+				&stmpe_gpio->norequest_mask);
+
 	if (irq >= 0)
 		stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
 	else
@@ -348,7 +374,7 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
 				IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
 		if (ret) {
 			dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-			goto out_removeirq;
+			goto out_disable;
 		}
 	}
 
@@ -368,9 +394,6 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
 out_freeirq:
 	if (irq >= 0)
 		free_irq(irq, stmpe_gpio);
-out_removeirq:
-	if (irq >= 0)
-		stmpe_gpio_irq_remove(stmpe_gpio);
 out_disable:
 	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 out_free:
@@ -378,7 +401,7 @@ out_free:
 	return ret;
 }
 
-static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
+static int stmpe_gpio_remove(struct platform_device *pdev)
 {
 	struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
 	struct stmpe *stmpe = stmpe_gpio->stmpe;
@@ -398,10 +421,9 @@ static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
 
 	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
 
-	if (irq >= 0) {
+	if (irq >= 0)
 		free_irq(irq, stmpe_gpio);
-		stmpe_gpio_irq_remove(stmpe_gpio);
-	}
+
 	platform_set_drvdata(pdev, NULL);
 	kfree(stmpe_gpio);
 
@@ -412,7 +434,7 @@ static struct platform_driver stmpe_gpio_driver = {
 	.driver.name	= "stmpe-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= stmpe_gpio_probe,
-	.remove		= __devexit_p(stmpe_gpio_remove),
+	.remove		= stmpe_gpio_remove,
 };
 
 static int __init stmpe_gpio_init(void)
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index 8bead0bb6459..85841ee70b17 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -197,7 +197,7 @@ static int xway_stp_hw_init(struct xway_stp *chip)
 	return 0;
 }
 
-static int __devinit xway_stp_probe(struct platform_device *pdev)
+static int xway_stp_probe(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	const __be32 *shadow, *groups, *dsl, *phy;
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index eb3e215d2396..796b6c42fa70 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -575,7 +575,7 @@ static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
 	}
 }
 
-static int __devinit sx150x_probe(struct i2c_client *client,
+static int sx150x_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
@@ -622,7 +622,7 @@ probe_fail_pre_gpiochip_add:
 	return rc;
 }
 
-static int __devexit sx150x_remove(struct i2c_client *client)
+static int sx150x_remove(struct i2c_client *client)
 {
 	struct sx150x_chip *chip;
 	int rc;
@@ -646,7 +646,7 @@ static struct i2c_driver sx150x_driver = {
 		.owner = THIS_MODULE
 	},
 	.probe    = sx150x_probe,
-	.remove   = __devexit_p(sx150x_remove),
+	.remove   = sx150x_remove,
 	.id_table = sx150x_id,
 };
 
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 1e48317e70fb..c0595bbf3268 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -292,17 +292,15 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
 {
 	int base = tc3589x_gpio->irq_base;
 
-	if (base) {
-		tc3589x_gpio->domain = irq_domain_add_legacy(
-			NULL, tc3589x_gpio->chip.ngpio, base,
-			0, &tc3589x_irq_ops, tc3589x_gpio);
-	}
-	else {
-		tc3589x_gpio->domain = irq_domain_add_linear(
-			np, tc3589x_gpio->chip.ngpio,
-			&tc3589x_irq_ops, tc3589x_gpio);
-	}
-
+	/*
+	 * If this results in a linear domain, irq_create_mapping() will
+	 * take care of allocating IRQ descriptors at runtime. When a base
+	 * is provided, the IRQ descriptors will be allocated when the
+	 * domain is instantiated.
+	 */
+	tc3589x_gpio->domain = irq_domain_add_simple(np,
+			tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
+			tc3589x_gpio);
 	if (!tc3589x_gpio->domain) {
 		dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
 		return -ENOSYS;
@@ -311,7 +309,7 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
 	return 0;
 }
 
-static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
+static int tc3589x_gpio_probe(struct platform_device *pdev)
 {
 	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
 	struct tc3589x_gpio_platform_data *pdata;
@@ -389,7 +387,7 @@ out_free:
 	return ret;
 }
 
-static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
+static int tc3589x_gpio_remove(struct platform_device *pdev)
 {
 	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
@@ -419,7 +417,7 @@ static struct platform_driver tc3589x_gpio_driver = {
 	.driver.name	= "tc3589x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= tc3589x_gpio_probe,
-	.remove		= __devexit_p(tc3589x_gpio_remove),
+	.remove		= tc3589x_gpio_remove,
 };
 
 static int __init tc3589x_gpio_init(void)
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index d982593d7563..63cb643d4b5a 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/irqdomain.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/pm.h>
 
 #include <asm/mach/irq.h>
 
@@ -64,7 +65,7 @@ struct tegra_gpio_bank {
 	int bank;
 	int irq;
 	spinlock_t lvl_lock[4];
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 	u32 cnf[4];
 	u32 out[4];
 	u32 oe[4];
@@ -109,20 +110,18 @@ static void tegra_gpio_enable(int gpio)
 {
 	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
 }
-EXPORT_SYMBOL_GPL(tegra_gpio_enable);
 
 static void tegra_gpio_disable(int gpio)
 {
 	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
 }
-EXPORT_SYMBOL_GPL(tegra_gpio_disable);
 
-int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
+static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
 	return pinctrl_request_gpio(offset);
 }
 
-void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
+static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
 	pinctrl_free_gpio(offset);
 	tegra_gpio_disable(offset);
@@ -135,6 +134,11 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
+	/* If gpio is in output mode then read from the out value */
+	if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1)
+		return (tegra_gpio_readl(GPIO_OUT(offset)) >>
+				GPIO_BIT(offset)) & 0x1;
+
 	return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
 }
 
@@ -285,8 +289,8 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 }
 
-#ifdef CONFIG_PM
-void tegra_gpio_resume(void)
+#ifdef CONFIG_PM_SLEEP
+static int tegra_gpio_resume(struct device *dev)
 {
 	unsigned long flags;
 	int b;
@@ -308,9 +312,10 @@ void tegra_gpio_resume(void)
 	}
 
 	local_irq_restore(flags);
+	return 0;
 }
 
-void tegra_gpio_suspend(void)
+static int tegra_gpio_suspend(struct device *dev)
 {
 	unsigned long flags;
 	int b;
@@ -330,6 +335,7 @@ void tegra_gpio_suspend(void)
 		}
 	}
 	local_irq_restore(flags);
+	return 0;
 }
 
 static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
@@ -345,11 +351,15 @@ static struct irq_chip tegra_gpio_irq_chip = {
 	.irq_mask	= tegra_gpio_irq_mask,
 	.irq_unmask	= tegra_gpio_irq_unmask,
 	.irq_set_type	= tegra_gpio_irq_set_type,
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 	.irq_set_wake	= tegra_gpio_wake_enable,
 #endif
 };
 
+static const struct dev_pm_ops tegra_gpio_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
+};
+
 struct tegra_gpio_soc_config {
 	u32 bank_stride;
 	u32 upper_offset;
@@ -365,7 +375,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {
 	.upper_offset = 0x80,
 };
 
-static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+static struct of_device_id tegra_gpio_of_match[] = {
 	{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
 	{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
 	{ },
@@ -376,11 +386,10 @@ static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
  */
 static struct lock_class_key gpio_lock_class;
 
-static int __devinit tegra_gpio_probe(struct platform_device *pdev)
+static int tegra_gpio_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
 	struct tegra_gpio_soc_config *config;
-	int irq_base;
 	struct resource *res;
 	struct tegra_gpio_bank *bank;
 	int gpio;
@@ -417,14 +426,11 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0);
-	if (irq_base < 0) {
-		dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n");
-		return -ENODEV;
-	}
-	irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
-					   tegra_gpio_chip.ngpio, irq_base, 0,
+	irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+					   tegra_gpio_chip.ngpio,
 					   &irq_domain_simple_ops, NULL);
+	if (!irq_domain)
+		return -ENODEV;
 
 	for (i = 0; i < tegra_gpio_bank_count; i++) {
 		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
@@ -464,7 +470,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
 	gpiochip_add(&tegra_gpio_chip);
 
 	for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) {
-		int irq = irq_find_mapping(irq_domain, gpio);
+		int irq = irq_create_mapping(irq_domain, gpio);
 		/* No validity check; all Tegra GPIOs are valid IRQs */
 
 		bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
@@ -493,6 +499,7 @@ static struct platform_driver tegra_gpio_driver = {
 	.driver		= {
 		.name	= "tegra-gpio",
 		.owner	= THIS_MODULE,
+		.pm	= &tegra_gpio_pm_ops,
 		.of_match_table = tegra_gpio_of_match,
 	},
 	.probe		= tegra_gpio_probe,
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index 1a3e2b9b4772..702cca9284f1 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -222,7 +222,7 @@ static struct irq_chip timbgpio_irqchip = {
 	.irq_set_type	= timbgpio_irq_type,
 };
 
-static int __devinit timbgpio_probe(struct platform_device *pdev)
+static int timbgpio_probe(struct platform_device *pdev)
 {
 	int err, i;
 	struct gpio_chip *gc;
@@ -316,7 +316,7 @@ err_mem:
 	return err;
 }
 
-static int __devexit timbgpio_remove(struct platform_device *pdev)
+static int timbgpio_remove(struct platform_device *pdev)
 {
 	int err;
 	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
index 62e9e1cb3bc1..29e8e750bd49 100644
--- a/drivers/gpio/gpio-tps6586x.c
+++ b/drivers/gpio/gpio-tps6586x.c
@@ -88,7 +88,7 @@ static int tps6586x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 				TPS6586X_INT_PLDO_0 + offset);
 }
 
-static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
+static int tps6586x_gpio_probe(struct platform_device *pdev)
 {
 	struct tps6586x_platform_data *pdata;
 	struct tps6586x_gpio *tps6586x_gpio;
@@ -135,7 +135,7 @@ static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit tps6586x_gpio_remove(struct platform_device *pdev)
+static int tps6586x_gpio_remove(struct platform_device *pdev)
 {
 	struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
 
@@ -146,7 +146,7 @@ static struct platform_driver tps6586x_gpio_driver = {
 	.driver.name	= "tps6586x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= tps6586x_gpio_probe,
-	.remove		= __devexit_p(tps6586x_gpio_remove),
+	.remove		= tps6586x_gpio_remove,
 };
 
 static int __init tps6586x_gpio_init(void)
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index 11f29c82253c..5083825a0348 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -113,7 +113,7 @@ static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
 }
 #endif
 
-static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
+static int tps65910_gpio_probe(struct platform_device *pdev)
 {
 	struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
 	struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
@@ -188,7 +188,7 @@ skip_init:
 	return ret;
 }
 
-static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
+static int tps65910_gpio_remove(struct platform_device *pdev)
 {
 	struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
 
@@ -199,7 +199,7 @@ static struct platform_driver tps65910_gpio_driver = {
 	.driver.name    = "tps65910-gpio",
 	.driver.owner   = THIS_MODULE,
 	.probe		= tps65910_gpio_probe,
-	.remove		= __devexit_p(tps65910_gpio_remove),
+	.remove		= tps65910_gpio_remove,
 };
 
 static int __init tps65910_gpio_init(void)
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
index 99106d1e2e55..30a5844a7dca 100644
--- a/drivers/gpio/gpio-tps65912.c
+++ b/drivers/gpio/gpio-tps65912.c
@@ -84,7 +84,7 @@ static struct gpio_chip template_chip = {
 	.base			= -1,
 };
 
-static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
+static int tps65912_gpio_probe(struct platform_device *pdev)
 {
 	struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
 	struct tps65912_board *pdata = tps65912->dev->platform_data;
@@ -113,7 +113,7 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
+static int tps65912_gpio_remove(struct platform_device *pdev)
 {
 	struct tps65912_gpio_data  *tps65912_gpio = platform_get_drvdata(pdev);
 
@@ -126,7 +126,7 @@ static struct platform_driver tps65912_gpio_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = tps65912_gpio_probe,
-	.remove = __devexit_p(tps65912_gpio_remove),
+	.remove = tps65912_gpio_remove,
 };
 
 static int __init tps65912_gpio_init(void)
diff --git a/drivers/gpio/gpio-ts5500.c b/drivers/gpio/gpio-ts5500.c
new file mode 100644
index 000000000000..0634ceea3c24
--- /dev/null
+++ b/drivers/gpio/gpio-ts5500.c
@@ -0,0 +1,466 @@
+/*
+ * Digital I/O driver for Technologic Systems TS-5500
+ *
+ * Copyright (c) 2012 Savoir-faire Linux Inc.
+ *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * Technologic Systems platforms have pin blocks, exposing several Digital
+ * Input/Output lines (DIO). This driver aims to support single pin blocks.
+ * In that sense, the support is not limited to the TS-5500 blocks.
+ * Actually, the following platforms have DIO support:
+ *
+ * TS-5500:
+ *   Documentation: http://wiki.embeddedarm.com/wiki/TS-5500
+ *   Blocks: DIO1, DIO2 and LCD port.
+ *
+ * TS-5600:
+ *   Documentation: http://wiki.embeddedarm.com/wiki/TS-5600
+ *   Blocks: LCD port (identical to TS-5500 LCD).
+ *
+ * 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/bitops.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_data/gpio-ts5500.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* List of supported Technologic Systems platforms DIO blocks */
+enum ts5500_blocks { TS5500_DIO1, TS5500_DIO2, TS5500_LCD, TS5600_LCD };
+
+struct ts5500_priv {
+	const struct ts5500_dio *pinout;
+	struct gpio_chip gpio_chip;
+	spinlock_t lock;
+	bool strap;
+	u8 hwirq;
+};
+
+/*
+ * Hex 7D is used to control several blocks (e.g. DIO2 and LCD port).
+ * This flag ensures that the region has been requested by this driver.
+ */
+static bool hex7d_reserved;
+
+/*
+ * This structure is used to describe capabilities of DIO lines,
+ * such as available directions and connected interrupt (if any).
+ */
+struct ts5500_dio {
+	const u8 value_addr;
+	const u8 value_mask;
+	const u8 control_addr;
+	const u8 control_mask;
+	const bool no_input;
+	const bool no_output;
+	const u8 irq;
+};
+
+#define TS5500_DIO_IN_OUT(vaddr, vbit, caddr, cbit)	\
+	{						\
+		.value_addr = vaddr,			\
+		.value_mask = BIT(vbit),		\
+		.control_addr = caddr,			\
+		.control_mask = BIT(cbit),		\
+	}
+
+#define TS5500_DIO_IN(addr, bit)		\
+	{					\
+		.value_addr = addr,		\
+		.value_mask = BIT(bit),		\
+		.no_output = true,		\
+	}
+
+#define TS5500_DIO_IN_IRQ(addr, bit, _irq)	\
+	{					\
+		.value_addr = addr,		\
+		.value_mask = BIT(bit),		\
+		.no_output = true,		\
+		.irq = _irq,			\
+	}
+
+#define TS5500_DIO_OUT(addr, bit)		\
+	{					\
+		.value_addr = addr,		\
+		.value_mask = BIT(bit),		\
+		.no_input = true,		\
+	}
+
+/*
+ * Input/Output DIO lines are programmed in groups of 4. Their values are
+ * available through 4 consecutive bits in a value port, whereas the direction
+ * of these 4 lines is driven by only 1 bit in a control port.
+ */
+#define TS5500_DIO_GROUP(vaddr, vbitfrom, caddr, cbit)		\
+	TS5500_DIO_IN_OUT(vaddr, vbitfrom + 0, caddr, cbit),	\
+	TS5500_DIO_IN_OUT(vaddr, vbitfrom + 1, caddr, cbit),	\
+	TS5500_DIO_IN_OUT(vaddr, vbitfrom + 2, caddr, cbit),	\
+	TS5500_DIO_IN_OUT(vaddr, vbitfrom + 3, caddr, cbit)
+
+/*
+ * TS-5500 DIO1 block
+ *
+ *  value    control  dir    hw
+ *  addr bit addr bit in out irq name     pin offset
+ *
+ *  0x7b  0  0x7a  0  x   x      DIO1_0   1   0
+ *  0x7b  1  0x7a  0  x   x      DIO1_1   3   1
+ *  0x7b  2  0x7a  0  x   x      DIO1_2   5   2
+ *  0x7b  3  0x7a  0  x   x      DIO1_3   7   3
+ *  0x7b  4  0x7a  1  x   x      DIO1_4   9   4
+ *  0x7b  5  0x7a  1  x   x      DIO1_5   11  5
+ *  0x7b  6  0x7a  1  x   x      DIO1_6   13  6
+ *  0x7b  7  0x7a  1  x   x      DIO1_7   15  7
+ *  0x7c  0  0x7a  5  x   x      DIO1_8   4   8
+ *  0x7c  1  0x7a  5  x   x      DIO1_9   6   9
+ *  0x7c  2  0x7a  5  x   x      DIO1_10  8   10
+ *  0x7c  3  0x7a  5  x   x      DIO1_11  10  11
+ *  0x7c  4           x          DIO1_12  12  12
+ *  0x7c  5           x      7   DIO1_13  14  13
+ */
+static const struct ts5500_dio ts5500_dio1[] = {
+	TS5500_DIO_GROUP(0x7b, 0, 0x7a, 0),
+	TS5500_DIO_GROUP(0x7b, 4, 0x7a, 1),
+	TS5500_DIO_GROUP(0x7c, 0, 0x7a, 5),
+	TS5500_DIO_IN(0x7c, 4),
+	TS5500_DIO_IN_IRQ(0x7c, 5, 7),
+};
+
+/*
+ * TS-5500 DIO2 block
+ *
+ *  value    control  dir    hw
+ *  addr bit addr bit in out irq name     pin offset
+ *
+ *  0x7e  0  0x7d  0  x   x      DIO2_0   1   0
+ *  0x7e  1  0x7d  0  x   x      DIO2_1   3   1
+ *  0x7e  2  0x7d  0  x   x      DIO2_2   5   2
+ *  0x7e  3  0x7d  0  x   x      DIO2_3   7   3
+ *  0x7e  4  0x7d  1  x   x      DIO2_4   9   4
+ *  0x7e  5  0x7d  1  x   x      DIO2_5   11  5
+ *  0x7e  6  0x7d  1  x   x      DIO2_6   13  6
+ *  0x7e  7  0x7d  1  x   x      DIO2_7   15  7
+ *  0x7f  0  0x7d  5  x   x      DIO2_8   4   8
+ *  0x7f  1  0x7d  5  x   x      DIO2_9   6   9
+ *  0x7f  2  0x7d  5  x   x      DIO2_10  8   10
+ *  0x7f  3  0x7d  5  x   x      DIO2_11  10  11
+ *  0x7f  4           x      6   DIO2_13  14  12
+ */
+static const struct ts5500_dio ts5500_dio2[] = {
+	TS5500_DIO_GROUP(0x7e, 0, 0x7d, 0),
+	TS5500_DIO_GROUP(0x7e, 4, 0x7d, 1),
+	TS5500_DIO_GROUP(0x7f, 0, 0x7d, 5),
+	TS5500_DIO_IN_IRQ(0x7f, 4, 6),
+};
+
+/*
+ * TS-5500 LCD port used as DIO block
+ * TS-5600 LCD port is identical
+ *
+ *  value    control  dir    hw
+ *  addr bit addr bit in out irq name    pin offset
+ *
+ *  0x72  0  0x7d  2  x   x      LCD_0   8   0
+ *  0x72  1  0x7d  2  x   x      LCD_1   7   1
+ *  0x72  2  0x7d  2  x   x      LCD_2   10  2
+ *  0x72  3  0x7d  2  x   x      LCD_3   9   3
+ *  0x72  4  0x7d  3  x   x      LCD_4   12  4
+ *  0x72  5  0x7d  3  x   x      LCD_5   11  5
+ *  0x72  6  0x7d  3  x   x      LCD_6   14  6
+ *  0x72  7  0x7d  3  x   x      LCD_7   13  7
+ *  0x73  0               x      LCD_EN  5   8
+ *  0x73  6           x          LCD_WR  6   9
+ *  0x73  7           x      1   LCD_RS  3   10
+ */
+static const struct ts5500_dio ts5500_lcd[] = {
+	TS5500_DIO_GROUP(0x72, 0, 0x7d, 2),
+	TS5500_DIO_GROUP(0x72, 4, 0x7d, 3),
+	TS5500_DIO_OUT(0x73, 0),
+	TS5500_DIO_IN(0x73, 6),
+	TS5500_DIO_IN_IRQ(0x73, 7, 1),
+};
+
+static inline struct ts5500_priv *ts5500_gc_to_priv(struct gpio_chip *chip)
+{
+	return container_of(chip, struct ts5500_priv, gpio_chip);
+}
+
+static inline void ts5500_set_mask(u8 mask, u8 addr)
+{
+	u8 val = inb(addr);
+	val |= mask;
+	outb(val, addr);
+}
+
+static inline void ts5500_clear_mask(u8 mask, u8 addr)
+{
+	u8 val = inb(addr);
+	val &= ~mask;
+	outb(val, addr);
+}
+
+static int ts5500_gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+	const struct ts5500_dio line = priv->pinout[offset];
+	unsigned long flags;
+
+	if (line.no_input)
+		return -ENXIO;
+
+	if (line.no_output)
+		return 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	ts5500_clear_mask(line.control_mask, line.control_addr);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static int ts5500_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+	const struct ts5500_dio line = priv->pinout[offset];
+
+	return !!(inb(line.value_addr) & line.value_mask);
+}
+
+static int ts5500_gpio_output(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+	const struct ts5500_dio line = priv->pinout[offset];
+	unsigned long flags;
+
+	if (line.no_output)
+		return -ENXIO;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!line.no_input)
+		ts5500_set_mask(line.control_mask, line.control_addr);
+
+	if (val)
+		ts5500_set_mask(line.value_mask, line.value_addr);
+	else
+		ts5500_clear_mask(line.value_mask, line.value_addr);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+static void ts5500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+	const struct ts5500_dio line = priv->pinout[offset];
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (val)
+		ts5500_set_mask(line.value_mask, line.value_addr);
+	else
+		ts5500_clear_mask(line.value_mask, line.value_addr);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int ts5500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+	const struct ts5500_dio *block = priv->pinout;
+	const struct ts5500_dio line = block[offset];
+
+	/* Only one pin is connected to an interrupt */
+	if (line.irq)
+		return line.irq;
+
+	/* As this pin is input-only, we may strap it to another in/out pin */
+	if (priv->strap)
+		return priv->hwirq;
+
+	return -ENXIO;
+}
+
+static int ts5500_enable_irq(struct ts5500_priv *priv)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->hwirq == 7)
+		ts5500_set_mask(BIT(7), 0x7a); /* DIO1_13 on IRQ7 */
+	else if (priv->hwirq == 6)
+		ts5500_set_mask(BIT(7), 0x7d); /* DIO2_13 on IRQ6 */
+	else if (priv->hwirq == 1)
+		ts5500_set_mask(BIT(6), 0x7d); /* LCD_RS on IRQ1 */
+	else
+		ret = -EINVAL;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return ret;
+}
+
+static void ts5500_disable_irq(struct ts5500_priv *priv)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->hwirq == 7)
+		ts5500_clear_mask(BIT(7), 0x7a); /* DIO1_13 on IRQ7 */
+	else if (priv->hwirq == 6)
+		ts5500_clear_mask(BIT(7), 0x7d); /* DIO2_13 on IRQ6 */
+	else if (priv->hwirq == 1)
+		ts5500_clear_mask(BIT(6), 0x7d); /* LCD_RS on IRQ1 */
+	else
+		dev_err(priv->gpio_chip.dev, "invalid hwirq %d\n", priv->hwirq);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int __devinit ts5500_dio_probe(struct platform_device *pdev)
+{
+	enum ts5500_blocks block = platform_get_device_id(pdev)->driver_data;
+	struct ts5500_dio_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	const char *name = dev_name(dev);
+	struct ts5500_priv *priv;
+	struct resource *res;
+	unsigned long flags;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "missing IRQ resource\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(struct ts5500_priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+	priv->hwirq = res->start;
+	spin_lock_init(&priv->lock);
+
+	priv->gpio_chip.owner = THIS_MODULE;
+	priv->gpio_chip.label = name;
+	priv->gpio_chip.dev = dev;
+	priv->gpio_chip.direction_input = ts5500_gpio_input;
+	priv->gpio_chip.direction_output = ts5500_gpio_output;
+	priv->gpio_chip.get = ts5500_gpio_get;
+	priv->gpio_chip.set = ts5500_gpio_set;
+	priv->gpio_chip.to_irq = ts5500_gpio_to_irq;
+	priv->gpio_chip.base = -1;
+	if (pdata) {
+		priv->gpio_chip.base = pdata->base;
+		priv->strap = pdata->strap;
+	}
+
+	switch (block) {
+	case TS5500_DIO1:
+		priv->pinout = ts5500_dio1;
+		priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio1);
+
+		if (!devm_request_region(dev, 0x7a, 3, name)) {
+			dev_err(dev, "failed to request %s ports\n", name);
+			return -EBUSY;
+		}
+		break;
+	case TS5500_DIO2:
+		priv->pinout = ts5500_dio2;
+		priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio2);
+
+		if (!devm_request_region(dev, 0x7e, 2, name)) {
+			dev_err(dev, "failed to request %s ports\n", name);
+			return -EBUSY;
+		}
+
+		if (hex7d_reserved)
+			break;
+
+		if (!devm_request_region(dev, 0x7d, 1, name)) {
+			dev_err(dev, "failed to request %s 7D\n", name);
+			return -EBUSY;
+		}
+
+		hex7d_reserved = true;
+		break;
+	case TS5500_LCD:
+	case TS5600_LCD:
+		priv->pinout = ts5500_lcd;
+		priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_lcd);
+
+		if (!devm_request_region(dev, 0x72, 2, name)) {
+			dev_err(dev, "failed to request %s ports\n", name);
+			return -EBUSY;
+		}
+
+		if (!hex7d_reserved) {
+			if (!devm_request_region(dev, 0x7d, 1, name)) {
+				dev_err(dev, "failed to request %s 7D\n", name);
+				return -EBUSY;
+			}
+
+			hex7d_reserved = true;
+		}
+
+		/* Ensure usage of LCD port as DIO */
+		spin_lock_irqsave(&priv->lock, flags);
+		ts5500_clear_mask(BIT(4), 0x7d);
+		spin_unlock_irqrestore(&priv->lock, flags);
+		break;
+	}
+
+	ret = gpiochip_add(&priv->gpio_chip);
+	if (ret) {
+		dev_err(dev, "failed to register the gpio chip\n");
+		return ret;
+	}
+
+	ret = ts5500_enable_irq(priv);
+	if (ret) {
+		dev_err(dev, "invalid interrupt %d\n", priv->hwirq);
+		goto cleanup;
+	}
+
+	return 0;
+cleanup:
+	if (gpiochip_remove(&priv->gpio_chip))
+		dev_err(dev, "failed to remove gpio chip\n");
+	return ret;
+}
+
+static int __devexit ts5500_dio_remove(struct platform_device *pdev)
+{
+	struct ts5500_priv *priv = platform_get_drvdata(pdev);
+
+	ts5500_disable_irq(priv);
+	return gpiochip_remove(&priv->gpio_chip);
+}
+
+static struct platform_device_id ts5500_dio_ids[] = {
+	{ "ts5500-dio1", TS5500_DIO1 },
+	{ "ts5500-dio2", TS5500_DIO2 },
+	{ "ts5500-dio-lcd", TS5500_LCD },
+	{ "ts5600-dio-lcd", TS5600_LCD },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, ts5500_dio_ids);
+
+static struct platform_driver ts5500_dio_driver = {
+	.driver = {
+		.name = "ts5500-dio",
+		.owner = THIS_MODULE,
+	},
+	.probe = ts5500_dio_probe,
+	.remove = __devexit_p(ts5500_dio_remove),
+	.id_table = ts5500_dio_ids,
+};
+
+module_platform_driver(ts5500_dio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>");
+MODULE_DESCRIPTION("Technologic Systems TS-5500 Digital I/O driver");
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index 88829c3337bf..9572aa137e6f 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -88,11 +88,15 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
 /*----------------------------------------------------------------------*/
 
 /*
- * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
+ * LED register offsets from TWL_MODULE_LED base
  * PWMs A and B are dedicated to LEDs A and B, respectively.
  */
 
-#define TWL4030_LED_LEDEN	0x0
+#define TWL4030_LED_LEDEN_REG	0x00
+#define TWL4030_PWMAON_REG	0x01
+#define TWL4030_PWMAOFF_REG	0x02
+#define TWL4030_PWMBON_REG	0x03
+#define TWL4030_PWMBOFF_REG	0x04
 
 /* LEDEN bits */
 #define LEDEN_LEDAON		BIT(0)
@@ -104,9 +108,6 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
 #define LEDEN_PWM_LENGTHA	BIT(6)
 #define LEDEN_PWM_LENGTHB	BIT(7)
 
-#define TWL4030_PWMx_PWMxON	0x0
-#define TWL4030_PWMx_PWMxOFF	0x1
-
 #define PWMxON_LENGTH		BIT(7)
 
 /*----------------------------------------------------------------------*/
@@ -145,7 +146,7 @@ static void twl4030_led_set_value(int led, int value)
 	else
 		cached_leden |= mask;
 	status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
-			TWL4030_LED_LEDEN);
+				  TWL4030_LED_LEDEN_REG);
 	mutex_unlock(&gpio_lock);
 }
 
@@ -216,33 +217,33 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
 	if (offset >= TWL4030_GPIO_MAX) {
 		u8	ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
 				| LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
-		u8	module = TWL4030_MODULE_PWMA;
+		u8	reg = TWL4030_PWMAON_REG;
 
 		offset -= TWL4030_GPIO_MAX;
 		if (offset) {
 			ledclr_mask <<= 1;
-			module = TWL4030_MODULE_PWMB;
+			reg = TWL4030_PWMBON_REG;
 		}
 
 		/* initialize PWM to always-drive */
-		status = twl_i2c_write_u8(module, 0x7f,
-				TWL4030_PWMx_PWMxOFF);
+		/* Configure PWM OFF register first */
+		status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg + 1);
 		if (status < 0)
 			goto done;
-		status = twl_i2c_write_u8(module, 0x7f,
-				TWL4030_PWMx_PWMxON);
+
+		/* Followed by PWM ON register */
+		status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg);
 		if (status < 0)
 			goto done;
 
 		/* init LED to not-driven (high) */
-		module = TWL4030_MODULE_LED;
-		status = twl_i2c_read_u8(module, &cached_leden,
-				TWL4030_LED_LEDEN);
+		status = twl_i2c_read_u8(TWL4030_MODULE_LED, &cached_leden,
+					 TWL4030_LED_LEDEN_REG);
 		if (status < 0)
 			goto done;
 		cached_leden &= ~ledclr_mask;
-		status = twl_i2c_write_u8(module, cached_leden,
-				TWL4030_LED_LEDEN);
+		status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
+					  TWL4030_LED_LEDEN_REG);
 		if (status < 0)
 			goto done;
 
@@ -352,7 +353,7 @@ static struct gpio_chip twl_gpiochip = {
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
+static int gpio_twl4030_pulls(u32 ups, u32 downs)
 {
 	u8		message[5];
 	unsigned	i, gpio_bit;
@@ -377,7 +378,7 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
 				REG_GPIOPUPDCTR1, 5);
 }
 
-static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
 {
 	u8		message[3];
 
@@ -419,7 +420,7 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
 	return omap_twl_info;
 }
 
-static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
+static int gpio_twl4030_probe(struct platform_device *pdev)
 {
 	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
 	struct device_node *node = pdev->dev.of_node;
@@ -505,7 +506,7 @@ out:
 	return ret;
 }
 
-/* Cannot use __devexit as gpio_twl4030_probe() calls us */
+/* Cannot use as gpio_twl4030_probe() calls us */
 static int gpio_twl4030_remove(struct platform_device *pdev)
 {
 	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
index dd58e8b25043..0be82c6dd796 100644
--- a/drivers/gpio/gpio-twl6040.c
+++ b/drivers/gpio/gpio-twl6040.c
@@ -82,7 +82,7 @@ static struct gpio_chip twl6040gpo_chip = {
 
 /*----------------------------------------------------------------------*/
 
-static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
+static int gpo_twl6040_probe(struct platform_device *pdev)
 {
 	struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
 	struct device *twl6040_core_dev = pdev->dev.parent;
@@ -113,7 +113,7 @@ static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit gpo_twl6040_remove(struct platform_device *pdev)
+static int gpo_twl6040_remove(struct platform_device *pdev)
 {
 	return gpiochip_remove(&twl6040gpo_chip);
 }
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
index 82d5c20ad3cb..9902732a382d 100644
--- a/drivers/gpio/gpio-vr41xx.c
+++ b/drivers/gpio/gpio-vr41xx.c
@@ -490,7 +490,7 @@ static struct gpio_chip vr41xx_gpio_chip = {
 	.to_irq			= vr41xx_gpio_to_irq,
 };
 
-static int __devinit giu_probe(struct platform_device *pdev)
+static int giu_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	unsigned int trigger, i, pin;
@@ -552,7 +552,7 @@ static int __devinit giu_probe(struct platform_device *pdev)
 	return cascade_irq(irq, giu_get_irq);
 }
 
-static int __devexit giu_remove(struct platform_device *pdev)
+static int giu_remove(struct platform_device *pdev)
 {
 	if (giu_base) {
 		iounmap(giu_base);
@@ -564,7 +564,7 @@ static int __devexit giu_remove(struct platform_device *pdev)
 
 static struct platform_driver giu_device_driver = {
 	.probe		= giu_probe,
-	.remove		= __devexit_p(giu_remove),
+	.remove		= giu_remove,
 	.driver		= {
 		.name	= "GIU",
 		.owner	= THIS_MODULE,
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
index bcd8e4aa7c7d..b53320a16fc8 100644
--- a/drivers/gpio/gpio-vt8500.c
+++ b/drivers/gpio/gpio-vt8500.c
@@ -96,6 +96,7 @@ static struct vt8500_gpio_data wm8505_data = {
 		VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
 		VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
 		VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
+		VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
 	},
 };
 
@@ -115,6 +116,7 @@ static struct vt8500_gpio_data wm8650_data = {
 		VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
 		VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
 		VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
+		VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
 	},
 };
 
@@ -269,7 +271,7 @@ static struct of_device_id vt8500_gpio_dt_ids[] = {
 	{ /* Sentinel */ },
 };
 
-static int __devinit vt8500_gpio_probe(struct platform_device *pdev)
+static int vt8500_gpio_probe(struct platform_device *pdev)
 {
 	void __iomem *gpio_base;
 	struct device_node *np;
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
index 76ebfe5ff702..2b7252cb2427 100644
--- a/drivers/gpio/gpio-vx855.c
+++ b/drivers/gpio/gpio-vx855.c
@@ -219,7 +219,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
 }
 
 /* This platform device is ordinarily registered by the vx855 mfd driver */
-static __devinit int vx855gpio_probe(struct platform_device *pdev)
+static int vx855gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res_gpi;
 	struct resource *res_gpo;
@@ -284,7 +284,7 @@ out_release:
 	return ret;
 }
 
-static int __devexit vx855gpio_remove(struct platform_device *pdev)
+static int vx855gpio_remove(struct platform_device *pdev)
 {
 	struct vx855_gpio *vg = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -312,7 +312,7 @@ static struct platform_driver vx855gpio_driver = {
 		.owner	= THIS_MODULE,
 	},
 	.probe		= vx855gpio_probe,
-	.remove		= __devexit_p(vx855gpio_remove),
+	.remove		= vx855gpio_remove,
 };
 
 module_platform_driver(vx855gpio_driver);
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
index b6eda35089d5..2a743e10ecb6 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -243,7 +243,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
+static int wm831x_gpio_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -275,7 +275,7 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
+static int wm831x_gpio_remove(struct platform_device *pdev)
 {
 	struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
 
@@ -286,7 +286,7 @@ static struct platform_driver wm831x_gpio_driver = {
 	.driver.name	= "wm831x-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= wm831x_gpio_probe,
-	.remove		= __devexit_p(wm831x_gpio_remove),
+	.remove		= wm831x_gpio_remove,
 };
 
 static int __init wm831x_gpio_init(void)
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
index fb4293889392..0b598cf3df9d 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -109,7 +109,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
+static int wm8350_gpio_probe(struct platform_device *pdev)
 {
 	struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
 	struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
@@ -141,7 +141,7 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
 	return ret;
 }
 
-static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
+static int wm8350_gpio_remove(struct platform_device *pdev)
 {
 	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
 
@@ -152,7 +152,7 @@ static struct platform_driver wm8350_gpio_driver = {
 	.driver.name	= "wm8350-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= wm8350_gpio_probe,
-	.remove		= __devexit_p(wm8350_gpio_remove),
+	.remove		= wm8350_gpio_remove,
 };
 
 static int __init wm8350_gpio_init(void)
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
index 1c764e779d80..ae409fd94af7 100644
--- a/drivers/gpio/gpio-wm8994.c
+++ b/drivers/gpio/gpio-wm8994.c
@@ -245,7 +245,7 @@ static struct gpio_chip template_chip = {
 	.can_sleep		= 1,
 };
 
-static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
+static int wm8994_gpio_probe(struct platform_device *pdev)
 {
 	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
 	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -281,7 +281,7 @@ err:
 	return ret;
 }
 
-static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
+static int wm8994_gpio_remove(struct platform_device *pdev)
 {
 	struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
 
@@ -292,7 +292,7 @@ static struct platform_driver wm8994_gpio_driver = {
 	.driver.name	= "wm8994-gpio",
 	.driver.owner	= THIS_MODULE,
 	.probe		= wm8994_gpio_probe,
-	.remove		= __devexit_p(wm8994_gpio_remove),
+	.remove		= wm8994_gpio_remove,
 };
 
 static int __init wm8994_gpio_init(void)
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 79b0fe8a7253..9ae7aa8ca48a 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -159,7 +159,7 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
  * driver data structure. It returns 0, if the driver is bound to the GPIO
  * device, or a negative value if there is an error.
  */
-static int __devinit xgpio_of_probe(struct device_node *np)
+static int xgpio_of_probe(struct device_node *np)
 {
 	struct xgpio_instance *chip;
 	int status = 0;
@@ -209,7 +209,7 @@ static int __devinit xgpio_of_probe(struct device_node *np)
 	return 0;
 }
 
-static struct of_device_id xgpio_of_match[] __devinitdata = {
+static struct of_device_id xgpio_of_match[] = {
 	{ .compatible = "xlnx,xps-gpio-1.00.a", },
 	{ /* end of list */ },
 };
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
new file mode 100644
index 000000000000..cbad6e908d30
--- /dev/null
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -0,0 +1,54 @@
+/*
+ * ACPI helpers for GPIO API
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.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/errno.h>
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/acpi_gpio.h>
+#include <linux/acpi.h>
+
+static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
+{
+	if (!gc->dev)
+		return false;
+
+	return ACPI_HANDLE(gc->dev) == data;
+}
+
+/**
+ * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API
+ * @path:	ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
+ * @pin:	ACPI GPIO pin number (0-based, controller-relative)
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or errno error value
+ */
+
+int acpi_get_gpio(char *path, int pin)
+{
+	struct gpio_chip *chip;
+	acpi_handle handle;
+	acpi_status status;
+
+	status = acpi_get_handle(NULL, path, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	chip = gpiochip_find(handle, acpi_gpiochip_find);
+	if (!chip)
+		return -ENODEV;
+
+	if (!gpio_is_valid(chip->base + pin))
+		return -EINVAL;
+
+	return chip->base + pin;
+}
+EXPORT_SYMBOL_GPL(acpi_get_gpio);
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index f1a45997aea8..d542a141811a 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
 #include <linux/slab.h>
 
 /* Private data structure for of_gpiochip_find_and_xlate */
@@ -216,6 +217,54 @@ err0:
 }
 EXPORT_SYMBOL(of_mm_gpiochip_add);
 
+#ifdef CONFIG_PINCTRL
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
+{
+	struct device_node *np = chip->of_node;
+	struct of_phandle_args pinspec;
+	struct pinctrl_dev *pctldev;
+	int index = 0, ret;
+
+	if (!np)
+		return;
+
+	do {
+		ret = of_parse_phandle_with_args(np, "gpio-ranges",
+				"#gpio-range-cells", index, &pinspec);
+		if (ret)
+			break;
+
+		pctldev = of_pinctrl_get(pinspec.np);
+		if (!pctldev)
+			break;
+
+		/*
+		 * This assumes that the n GPIO pins are consecutive in the
+		 * GPIO number space, and that the pins are also consecutive
+		 * in their local number space. Currently it is not possible
+		 * to add different ranges for one and the same GPIO chip,
+		 * as the code assumes that we have one consecutive range
+		 * on both, mapping 1-to-1.
+		 *
+		 * TODO: make the OF bindings handle multiple sparse ranges
+		 * on the same GPIO chip.
+		 */
+		ret = gpiochip_add_pin_range(chip,
+					     pinctrl_dev_get_name(pctldev),
+					     0, /* offset in gpiochip */
+					     pinspec.args[0],
+					     pinspec.args[1]);
+
+		if (ret)
+			break;
+
+	} while (index++);
+}
+
+#else
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
+#endif
+
 void of_gpiochip_add(struct gpio_chip *chip)
 {
 	if ((!chip->of_node) && (chip->dev))
@@ -229,11 +278,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
 		chip->of_xlate = of_gpio_simple_xlate;
 	}
 
+	of_gpiochip_add_pin_range(chip);
 	of_node_get(chip->of_node);
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
 {
+	gpiochip_remove_pin_ranges(chip);
+
 	if (chip->of_node)
 		of_node_put(chip->of_node);
 }
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1c8d9e3380e1..199fca15f270 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -191,6 +191,32 @@ err:
 	return ret;
 }
 
+/* caller ensures gpio is valid and requested, chip->get_direction may sleep  */
+static int gpio_get_direction(unsigned gpio)
+{
+	struct gpio_chip	*chip;
+	struct gpio_desc	*desc = &gpio_desc[gpio];
+	int			status = -EINVAL;
+
+	chip = gpio_to_chip(gpio);
+	gpio -= chip->base;
+
+	if (!chip->get_direction)
+		return status;
+
+	status = chip->get_direction(chip, gpio);
+	if (status > 0) {
+		/* GPIOF_DIR_IN, or other positive */
+		status = 1;
+		clear_bit(FLAG_IS_OUT, &desc->flags);
+	}
+	if (status == 0) {
+		/* GPIOF_DIR_OUT */
+		set_bit(FLAG_IS_OUT, &desc->flags);
+	}
+	return status;
+}
+
 #ifdef CONFIG_GPIO_SYSFS
 
 /* lock protects against unexport_gpio() being called while
@@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	const struct gpio_desc	*desc = dev_get_drvdata(dev);
+	unsigned		gpio = desc - gpio_desc;
 	ssize_t			status;
 
 	mutex_lock(&sysfs_lock);
@@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev,
 	if (!test_bit(FLAG_EXPORT, &desc->flags))
 		status = -EIO;
 	else
+		gpio_get_direction(gpio);
 		status = sprintf(buf, "%s\n",
 			test_bit(FLAG_IS_OUT, &desc->flags)
 				? "out" : "in");
@@ -704,8 +732,9 @@ int gpio_export(unsigned gpio, bool direction_may_change)
 {
 	unsigned long		flags;
 	struct gpio_desc	*desc;
-	int			status = -EINVAL;
+	int			status;
 	const char		*ioname = NULL;
+	struct device		*dev;
 
 	/* can't export until sysfs is available ... */
 	if (!gpio_class.p) {
@@ -713,59 +742,66 @@ int gpio_export(unsigned gpio, bool direction_may_change)
 		return -ENOENT;
 	}
 
-	if (!gpio_is_valid(gpio))
-		goto done;
+	if (!gpio_is_valid(gpio)) {
+		pr_debug("%s: gpio %d is not valid\n", __func__, gpio);
+		return -EINVAL;
+	}
 
 	mutex_lock(&sysfs_lock);
 
 	spin_lock_irqsave(&gpio_lock, flags);
 	desc = &gpio_desc[gpio];
-	if (test_bit(FLAG_REQUESTED, &desc->flags)
-			&& !test_bit(FLAG_EXPORT, &desc->flags)) {
-		status = 0;
-		if (!desc->chip->direction_input
-				|| !desc->chip->direction_output)
-			direction_may_change = false;
+	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
+	     test_bit(FLAG_EXPORT, &desc->flags)) {
+		spin_unlock_irqrestore(&gpio_lock, flags);
+		pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n",
+				__func__, gpio,
+				test_bit(FLAG_REQUESTED, &desc->flags),
+				test_bit(FLAG_EXPORT, &desc->flags));
+		status = -EPERM;
+		goto fail_unlock;
 	}
+
+	if (!desc->chip->direction_input || !desc->chip->direction_output)
+		direction_may_change = false;
 	spin_unlock_irqrestore(&gpio_lock, flags);
 
 	if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])
 		ioname = desc->chip->names[gpio - desc->chip->base];
 
-	if (status == 0) {
-		struct device	*dev;
-
-		dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
-				desc, ioname ? ioname : "gpio%u", gpio);
-		if (!IS_ERR(dev)) {
-			status = sysfs_create_group(&dev->kobj,
-						&gpio_attr_group);
-
-			if (!status && direction_may_change)
-				status = device_create_file(dev,
-						&dev_attr_direction);
-
-			if (!status && gpio_to_irq(gpio) >= 0
-					&& (direction_may_change
-						|| !test_bit(FLAG_IS_OUT,
-							&desc->flags)))
-				status = device_create_file(dev,
-						&dev_attr_edge);
-
-			if (status != 0)
-				device_unregister(dev);
-		} else
-			status = PTR_ERR(dev);
-		if (status == 0)
-			set_bit(FLAG_EXPORT, &desc->flags);
+	dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+			    desc, ioname ? ioname : "gpio%u", gpio);
+	if (IS_ERR(dev)) {
+		status = PTR_ERR(dev);
+		goto fail_unlock;
 	}
 
-	mutex_unlock(&sysfs_lock);
-
-done:
+	status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
 	if (status)
-		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+		goto fail_unregister_device;
+
+	if (direction_may_change) {
+		status = device_create_file(dev, &dev_attr_direction);
+		if (status)
+			goto fail_unregister_device;
+	}
+
+	if (gpio_to_irq(gpio) >= 0 && (direction_may_change ||
+				       !test_bit(FLAG_IS_OUT, &desc->flags))) {
+		status = device_create_file(dev, &dev_attr_edge);
+		if (status)
+			goto fail_unregister_device;
+	}
+
+	set_bit(FLAG_EXPORT, &desc->flags);
+	mutex_unlock(&sysfs_lock);
+	return 0;
 
+fail_unregister_device:
+	device_unregister(dev);
+fail_unlock:
+	mutex_unlock(&sysfs_lock);
+	pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
 	return status;
 }
 EXPORT_SYMBOL_GPL(gpio_export);
@@ -1075,6 +1111,7 @@ int gpiochip_add(struct gpio_chip *chip)
 			 * inputs (often with pullups enabled) so power
 			 * usage is minimized.  Linux code should set the
 			 * gpio direction first thing; but until it does,
+			 * and in case chip->get_direction is not set,
 			 * we may expose the wrong direction in sysfs.
 			 */
 			gpio_desc[id].flags = !chip->direction_input
@@ -1083,6 +1120,10 @@ int gpiochip_add(struct gpio_chip *chip)
 		}
 	}
 
+#ifdef CONFIG_PINCTRL
+	INIT_LIST_HEAD(&chip->pin_ranges);
+#endif
+
 	of_gpiochip_add(chip);
 
 unlock:
@@ -1123,6 +1164,7 @@ int gpiochip_remove(struct gpio_chip *chip)
 
 	spin_lock_irqsave(&gpio_lock, flags);
 
+	gpiochip_remove_pin_ranges(chip);
 	of_gpiochip_remove(chip);
 
 	for (id = chip->base; id < chip->base + chip->ngpio; id++) {
@@ -1180,6 +1222,77 @@ struct gpio_chip *gpiochip_find(void *data,
 }
 EXPORT_SYMBOL_GPL(gpiochip_find);
 
+#ifdef CONFIG_PINCTRL
+
+/**
+ * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
+ * @chip: the gpiochip to add the range for
+ * @pinctrl_name: the dev_name() of the pin controller to map to
+ * @gpio_offset: the start offset in the current gpio_chip number space
+ * @pin_offset: the start offset in the pin controller number space
+ * @npins: the number of pins from the offset of each pin space (GPIO and
+ *	pin controller) to accumulate in this range
+ */
+int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+			   unsigned int gpio_offset, unsigned int pin_offset,
+			   unsigned int npins)
+{
+	struct gpio_pin_range *pin_range;
+	int ret;
+
+	pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
+	if (!pin_range) {
+		pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+				chip->label);
+		return -ENOMEM;
+	}
+
+	/* Use local offset as range ID */
+	pin_range->range.id = gpio_offset;
+	pin_range->range.gc = chip;
+	pin_range->range.name = chip->label;
+	pin_range->range.base = chip->base + gpio_offset;
+	pin_range->range.pin_base = pin_offset;
+	pin_range->range.npins = npins;
+	pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name,
+			&pin_range->range);
+	if (IS_ERR(pin_range->pctldev)) {
+		ret = PTR_ERR(pin_range->pctldev);
+		pr_err("%s: GPIO chip: could not create pin range\n",
+		       chip->label);
+		kfree(pin_range);
+		return ret;
+	}
+	pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n",
+		 chip->label, gpio_offset, gpio_offset + npins - 1,
+		 pinctl_name,
+		 pin_offset, pin_offset + npins - 1);
+
+	list_add_tail(&pin_range->node, &chip->pin_ranges);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
+
+/**
+ * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings
+ * @chip: the chip to remove all the mappings for
+ */
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+	struct gpio_pin_range *pin_range, *tmp;
+
+	list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+		list_del(&pin_range->node);
+		pinctrl_remove_gpio_range(pin_range->pctldev,
+				&pin_range->range);
+		kfree(pin_range);
+	}
+}
+EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
+
+#endif /* CONFIG_PINCTRL */
+
 /* These "optional" allocation calls help prevent drivers from stomping
  * on each other, and help provide better diagnostics in debugfs.
  * They're called even less than the "set direction" calls.
@@ -1228,9 +1341,15 @@ int gpio_request(unsigned gpio, const char *label)
 			desc_set_label(desc, NULL);
 			module_put(chip->owner);
 			clear_bit(FLAG_REQUESTED, &desc->flags);
+			goto done;
 		}
 	}
-
+	if (chip->get_direction) {
+		/* chip->get_direction may sleep */
+		spin_unlock_irqrestore(&gpio_lock, flags);
+		gpio_get_direction(gpio);
+		spin_lock_irqsave(&gpio_lock, flags);
+	}
 done:
 	if (status)
 		pr_debug("gpio_request: gpio-%d (%s) status %d\n",
@@ -1766,6 +1885,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 		if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
 			continue;
 
+		gpio_get_direction(gpio);
 		is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
 		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
 			gpio, gdesc->label,