diff --git a/Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt b/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt
similarity index 70%
rename from Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt
rename to Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt
index 5c9246c054e5bae6c0c552c52e76f84afa3eceb4..d04236558619d84b0b1b99351ac72803ac4b2ca9 100644
--- a/Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt
@@ -1,8 +1,11 @@
-Cortina Systems Gemini GPIO Controller
+Faraday Technology FTGPIO010 GPIO Controller
 
 Required properties:
 
-- compatible : Must be "cortina,gemini-gpio"
+- compatible : Should be one of
+  "cortina,gemini-gpio", "faraday,ftgpio010"
+  "moxa,moxart-gpio", "faraday,ftgpio010"
+  "faraday,ftgpio010"
 - reg : Should contain registers location and length
 - interrupts : Should contain the interrupt line for the GPIO block
 - gpio-controller : marks this as a GPIO controller
@@ -14,7 +17,7 @@ Required properties:
 Example:
 
 gpio@4d000000 {
-	compatible = "cortina,gemini-gpio";
+	compatible = "cortina,gemini-gpio", "faraday,ftgpio010";
 	reg = <0x4d000000 0x100>;
 	interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
 	gpio-controller;
diff --git a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt
index 393bb2ed8a774276bf1922ce63e018ab21985ca2..c756afa88cc62359323cfe3f0cc1171a31e955f4 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt
@@ -17,7 +17,8 @@ Required properties:
 
 Optional properties:
 
-- interrupt-parent     : The parent interrupt controller, optional if inherited
+- interrupt-parent      : The parent interrupt controller, optional if inherited
+- clocks                : A phandle to the HPLL clock node for debounce timings
 
 The gpio and interrupt properties are further described in their respective
 bindings documentation:
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
index a6f3bec1da7d0f46d6f0ecf22fcec20232b354dc..42c3bb2d53e88b651a7d39efe00e278c24d9c9b3 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
@@ -38,6 +38,24 @@ Required properties:
 - #gpio-cells: Should be two. The first cell is the pin number. The
   second cell is reserved for flags, unused at the moment.
 
+Optional properties:
+
+In order to use the GPIO lines in PWM mode, some additional optional
+properties are required. Only Armada 370 and XP support these properties.
+
+- compatible: Must contain "marvell,armada-370-xp-gpio"
+
+- reg: an additional register set is needed, for the GPIO Blink
+  Counter on/off registers.
+
+- reg-names: Must contain an entry "pwm" corresponding to the
+  additional register range needed for PWM operation.
+
+- #pwm-cells: Should be two. The first cell is the GPIO line number. The
+  second cell is the period in nanoseconds.
+
+- clocks: Must be a phandle to the clock for the GPIO controller.
+
 Example:
 
 		gpio0: gpio@d0018100 {
@@ -51,3 +69,17 @@ Example:
 			#interrupt-cells = <2>;
 			interrupts = <16>, <17>, <18>, <19>;
 		};
+
+		gpio1: gpio@18140 {
+			compatible = "marvell,armada-370-xp-gpio";
+			reg = <0x18140 0x40>, <0x181c8 0x08>;
+			reg-names = "gpio", "pwm";
+			ngpios = <17>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			#pwm-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <87>, <88>, <89>;
+			clocks = <&coreclk 0>;
+		};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
index e6393571001144bba965d0d72e3d4c50a0b9da8e..7f57271df2bc96b41168d337c911511ccb726e33 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
@@ -26,6 +26,7 @@ Required properties:
 	ti,tca6416
 	ti,tca6424
 	ti,tca9539
+	ti,tca9554
 	onsemi,pca9654
 	exar,xra1202
 
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
index ada4e29733234aa0f5c0afe8cf20e2ac4b8de173..7d3bd631d0114850d3598a9a64824e8af906d6ee 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
@@ -25,7 +25,6 @@ Required Properties:
     - "nxp,pcf8574": For the NXP PCF8574
     - "nxp,pcf8574a": For the NXP PCF8574A
     - "nxp,pcf8575": For the NXP PCF8575
-    - "ti,tca9554": For the TI TCA9554
 
   - reg: I2C slave address.
 
diff --git a/Documentation/devicetree/bindings/gpio/gpio-thunderx.txt b/Documentation/devicetree/bindings/gpio/gpio-thunderx.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3f883ae29d116887e702ead20b26a25f9d2349d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-thunderx.txt
@@ -0,0 +1,27 @@
+Cavium ThunderX/OCTEON-TX GPIO controller bindings
+
+Required Properties:
+- reg: The controller bus address.
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells: Must be 2.
+  - First cell is the GPIO pin number relative to the controller.
+  - Second cell is a standard generic flag bitfield as described in gpio.txt.
+
+Optional Properties:
+- compatible: "cavium,thunder-8890-gpio", unused as PCI driver binding is used.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells: Must be present and have value of 2 if
+                    "interrupt-controller" is present.
+  - First cell is the GPIO pin number relative to the controller.
+  - Second cell is triggering flags as defined in interrupts.txt.
+
+Example:
+
+gpio_6_0: gpio@6,0 {
+	compatible = "cavium,thunder-8890-gpio";
+	reg = <0x3000 0 0 0 0>; /*  DEVFN = 0x30 (6:0) */
+	gpio-controller;
+	#gpio-cells = <2>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e13cc399b363f24aae0083fc34b09bd434aa78cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
@@ -0,0 +1,46 @@
+GPIO Driver for XRA1403 16-BIT GPIO Expander With Reset Input from EXAR
+
+The XRA1403 is an 16-bit GPIO expander with an SPI interface. Features available:
+	- Individually programmable inputs:
+		- Internal pull-up resistors
+		- Polarity inversion
+		- Individual interrupt enable
+		- Rising edge and/or Falling edge interrupt
+		- Input filter
+	- Individually programmable outputs
+		- Output Level Control
+		- Output Three-State Control
+
+Properties
+----------
+Check documentation for SPI and GPIO controllers regarding properties needed to configure the node.
+
+	- compatible = "exar,xra1403".
+	- reg - SPI id of the device.
+	- gpio-controller - marks the node as gpio.
+	- #gpio-cells - should be two where the first cell is the pin number
+		and the second one is used for optional parameters.
+
+Optional properties:
+-------------------
+	- reset-gpios: in case available used to control the device reset line.
+	- interrupt-controller - marks the node as interrupt controller.
+	- #interrupt-cells - should be two and represents the number of cells
+		needed to encode interrupt source.
+
+Example
+--------
+
+	gpioxra0: gpio@2 {
+		compatible = "exar,xra1403";
+		reg = <2>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
+		spi-max-frequency = <1000000>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt b/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt
deleted file mode 100644
index f8e8f185a3dbacbd60641cd2b70da3b0c2c1e32a..0000000000000000000000000000000000000000
--- a/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-MOXA ART GPIO Controller
-
-Required properties:
-
-- #gpio-cells : Should be 2, The first cell is the pin number,
-		the second cell is used to specify polarity:
-			0 = active high
-			1 = active low
-- compatible : Must be "moxa,moxart-gpio"
-- reg : Should contain registers location and length
-
-Example:
-
-	gpio: gpio@98700000 {
-		gpio-controller;
-		#gpio-cells = <2>;
-		compatible = "moxa,moxart-gpio";
-		reg =	<0x98700000 0xC>;
-	};
diff --git a/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt b/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ca2f8c745a279cfea1375dc68dceff29a63f8de5
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt
@@ -0,0 +1,38 @@
+Bindings for the National Instruments 169445 GPIO NAND controller
+
+The 169445 GPIO NAND controller has two memory mapped GPIO registers, one
+for input (the ready signal) and one for output (control signals).  It is
+intended to be used with the GPIO NAND driver.
+
+Required properties:
+	- compatible: should be "ni,169445-nand-gpio"
+	- reg-names: must contain
+		"dat" - data register
+	- reg: address + size pairs describing the GPIO register sets;
+		order must correspond with the order of entries in reg-names
+	- #gpio-cells: must be set to 2. The first cell is the pin number and
+			the second cell is used to specify the gpio polarity:
+			0 = active high
+			1 = active low
+	- gpio-controller: Marks the device node as a gpio controller.
+
+Optional properties:
+	- no-output: disables driving output on the pins
+
+Examples:
+	gpio1: nand-gpio-out@1f300010 {
+		compatible = "ni,169445-nand-gpio";
+		reg = <0x1f300010 0x4>;
+		reg-names = "dat";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio2: nand-gpio-in@1f300014 {
+		compatible = "ni,169445-nand-gpio";
+		reg = <0x1f300014 0x4>;
+		reg-names = "dat";
+		gpio-controller;
+		#gpio-cells = <2>;
+		no-output;
+	};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index bbb8174405bc83cb0f9d1b4ecab505a58112e85f..257ec07cbaa063c8c5fc1b3946dd7edc879af681 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -103,6 +103,7 @@ ettus	NI Ettus Research
 eukrea  Eukréa Electromatique
 everest	Everest Semiconductor Co. Ltd.
 everspin	Everspin Technologies, Inc.
+exar	Exar Corporation
 excito	Excito
 ezchip	EZchip Semiconductor
 faraday	Faraday Technology Corporation
diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt
index 05676fdacfe3c56f1a9afdaf54795e9167a9c287..912568baabb9629083151fc4ed30578c066684cd 100644
--- a/Documentation/gpio/consumer.txt
+++ b/Documentation/gpio/consumer.txt
@@ -70,6 +70,12 @@ instead of -ENOENT if no GPIO has been assigned to the requested function:
 						   unsigned int index,
 						   enum gpiod_flags flags)
 
+Note that gpio_get*_optional() functions (and their managed variants), unlike
+the rest of gpiolib API, also return NULL when gpiolib support is disabled.
+This is helpful to driver authors, since they do not need to special case
+-ENOSYS return codes.  System integrators should however be careful to enable
+gpiolib on systems that need it.
+
 For a function using multiple GPIOs all of those can be obtained with one call:
 
 	struct gpio_descs *gpiod_get_array(struct device *dev,
diff --git a/MAINTAINERS b/MAINTAINERS
index 4e9d4e91fa9481882772b4bcccd066e4a1c803df..4f04a2bc305efe3434b3361db1eac4e9ec421ee9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10315,6 +10315,8 @@ F:	include/linux/pwm.h
 F:	drivers/pwm/
 F:	drivers/video/backlight/pwm_bl.c
 F:	include/linux/pwm_backlight.h
+F:	drivers/gpio/gpio-mvebu.c
+F:	Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
 
 PXA2xx/PXA3xx SUPPORT
 M:	Daniel Mack <daniel@zonque.org>
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 9b1bcb4d0df731f1a2cf8ad13d95037cb7dfcb87..23ca51ee6b28e416bc7472ca5525a71652bbde92 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -204,14 +204,15 @@ config GPIO_GE_FPGA
 	  and write pin state) for GPIO implemented in a number of GE single
 	  board computers.
 
-config GPIO_GEMINI
-	bool "Gemini GPIO"
-	depends on ARCH_GEMINI
+config GPIO_FTGPIO010
+	bool "Faraday FTGPIO010 GPIO"
 	depends on OF_GPIO
 	select GPIO_GENERIC
 	select GPIOLIB_IRQCHIP
+	default (ARCH_GEMINI || ARCH_MOXART)
 	help
-	  Support for common GPIOs found in Cortina systems Gemini platforms.
+	  Support for common GPIOs from the Faraday FTGPIO010 IP core, found in
+	  Cortina systems Gemini platforms, Moxa ART and others.
 
 config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
@@ -308,14 +309,6 @@ config GPIO_MOCKUP
 	  tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
 	  it.
 
-config GPIO_MOXART
-	bool "MOXART GPIO support"
-	depends on ARCH_MOXART || COMPILE_TEST
-	select GPIO_GENERIC
-	help
-	  Select this option to enable GPIO driver for
-	  MOXA ART SoC devices.
-
 config GPIO_MPC5200
 	def_bool y
 	depends on PPC_MPC52xx
@@ -387,6 +380,12 @@ config GPIO_RCAR
 	help
 	  Say yes here to support GPIO on Renesas R-Car SoCs.
 
+config GPIO_REG
+	bool
+	help
+	  A 32-bit single register GPIO fixed in/out implementation.  This
+	  can be used to represent any register as a set of GPIO signals.
+
 config GPIO_SPEAR_SPICS
 	bool "ST SPEAr13xx SPI Chip Select as GPIO support"
 	depends on PLAT_SPEAR
@@ -505,7 +504,7 @@ config GPIO_XILINX
 
 config GPIO_XLP
 	tristate "Netlogic XLP GPIO support"
-	depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || COMPILE_TEST)
+	depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || ARCH_THUNDER2 || COMPILE_TEST)
 	select GPIOLIB_IRQCHIP
 	help
 	  This driver provides support for GPIO interface on Netlogic XLP MIPS64
@@ -557,7 +556,7 @@ menu "Port-mapped I/O GPIO drivers"
 
 config GPIO_104_DIO_48E
 	tristate "ACCES 104-DIO-48E GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	help
 	  Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
@@ -567,7 +566,7 @@ config GPIO_104_DIO_48E
 
 config GPIO_104_IDIO_16
 	tristate "ACCES 104-IDIO-16 GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	help
 	  Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
@@ -578,7 +577,7 @@ config GPIO_104_IDIO_16
 
 config GPIO_104_IDI_48
 	tristate "ACCES 104-IDI-48 GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	help
 	  Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
@@ -598,7 +597,7 @@ config GPIO_F7188X
 
 config GPIO_GPIO_MM
 	tristate "Diamond Systems GPIO-MM GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	help
 	  Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12.
 
@@ -753,7 +752,7 @@ config GPIO_PCA953X
 	  4 bits:	pca9536, pca9537
 
 	  8 bits:	max7310, max7315, pca6107, pca9534, pca9538, pca9554,
-			pca9556, pca9557, pca9574, tca6408, xra1202
+			pca9556, pca9557, pca9574, tca6408, tca9554, xra1202
 
 	  16 bits:	max7312, max7313, pca9535, pca9539, pca9555, pca9575,
 			tca6416
@@ -845,6 +844,17 @@ config GPIO_ARIZONA
 	help
 	  Support for GPIOs on Wolfson Arizona class devices.
 
+config GPIO_BD9571MWV
+	tristate "ROHM BD9571 GPIO support"
+	depends on MFD_BD9571MWV
+	help
+	  Support for GPIOs on ROHM BD9571 PMIC. There are two GPIOs
+	  available on the ROHM PMIC in total, both of which can also
+	  generate interrupts.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called gpio-bd9571mwv.
+
 config GPIO_CRYSTAL_COVE
 	tristate "GPIO support for Crystal Cove PMIC"
 	depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index becb96c724fef59bf770c89268771c10acf6e48f..68b96277d9fa463bc641b0211eb4d719d75ac481 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_ASPEED)	+= gpio-aspeed.o
 obj-$(CONFIG_GPIO_AXP209)	+= gpio-axp209.o
 obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
+obj-$(CONFIG_GPIO_BD9571MWV)	+= gpio-bd9571mwv.o
 obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
@@ -48,8 +49,8 @@ obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_ETRAXFS)	+= gpio-etraxfs.o
 obj-$(CONFIG_GPIO_EXAR)		+= gpio-exar.o
 obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o
+obj-$(CONFIG_GPIO_FTGPIO010)	+= gpio-ftgpio010.o
 obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
-obj-$(CONFIG_GPIO_GEMINI)	+= gpio-gemini.o
 obj-$(CONFIG_GPIO_GPIO_MM)	+= gpio-gpio-mm.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_HTC_EGPIO)		+= gpio-htc-egpio.o
@@ -80,7 +81,6 @@ obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
 obj-$(CONFIG_GPIO_MOCKUP)      += gpio-mockup.o
-obj-$(CONFIG_GPIO_MOXART)	+= gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
@@ -99,6 +99,7 @@ obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RC5T583)	+= gpio-rc5t583.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
 obj-$(CONFIG_GPIO_RCAR)		+= gpio-rcar.o
+obj-$(CONFIG_GPIO_REG)		+= gpio-reg.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_SCH311X)	+= gpio-sch311x.o
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 7031eea165c98586fa355547c25157a099823d9c..a75511d1ea5d458f9c694ea3536bcdc69dc321c5 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -136,7 +136,7 @@ EXPORT_SYMBOL(devm_gpiod_get_index);
  * GPIO descriptors returned from this function are automatically disposed on
  * driver detach.
  *
- * On successfull request the GPIO pin is configured in accordance with
+ * On successful request the GPIO pin is configured in accordance with
  * provided @flags.
  */
 struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 17bd2ab4ebe200792ef207227fa67a5d7ce0106a..61b50c40b87bba9469fa650a4fd6858607312092 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -55,7 +55,7 @@ struct dio48e_gpio {
 	unsigned char io_state[6];
 	unsigned char out_state[6];
 	unsigned char control[2];
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned base;
 	unsigned char irq_mask;
 };
@@ -78,7 +78,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	unsigned long flags;
 	unsigned control;
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 	/* Check if configuring Port C */
 	if (io_port == 2 || io_port == 5) {
@@ -103,7 +103,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	control &= ~BIT(7);
 	outb(control, control_addr);
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 
 	return 0;
 }
@@ -120,7 +120,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 	unsigned long flags;
 	unsigned control;
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 	/* Check if configuring Port C */
 	if (io_port == 2 || io_port == 5) {
@@ -153,7 +153,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 	control &= ~BIT(7);
 	outb(control, control_addr);
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 
 	return 0;
 }
@@ -167,17 +167,17 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset)
 	unsigned long flags;
 	unsigned port_state;
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 	/* ensure that GPIO is set for input */
 	if (!(dio48egpio->io_state[port] & mask)) {
-		spin_unlock_irqrestore(&dio48egpio->lock, flags);
+		raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 		return -EINVAL;
 	}
 
 	port_state = inb(dio48egpio->base + in_port);
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 
 	return !!(port_state & mask);
 }
@@ -190,7 +190,7 @@ static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	const unsigned out_port = (port > 2) ? port + 1 : port;
 	unsigned long flags;
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 	if (value)
 		dio48egpio->out_state[port] |= mask;
@@ -199,7 +199,7 @@ static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 	outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 }
 
 static void dio48e_gpio_set_multiple(struct gpio_chip *chip,
@@ -225,14 +225,14 @@ static void dio48e_gpio_set_multiple(struct gpio_chip *chip,
 		out_port = (port > 2) ? port + 1 : port;
 		bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
 
-		spin_lock_irqsave(&dio48egpio->lock, flags);
+		raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 		/* update output state data and set device gpio register */
 		dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)];
 		dio48egpio->out_state[port] |= bitmask;
 		outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
 
-		spin_unlock_irqrestore(&dio48egpio->lock, flags);
+		raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 
 		/* prepare for next gpio register set */
 		mask[BIT_WORD(i)] >>= gpio_reg_size;
@@ -255,7 +255,7 @@ static void dio48e_irq_mask(struct irq_data *data)
 	if (offset != 19 && offset != 43)
 		return;
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 	if (offset == 19)
 		dio48egpio->irq_mask &= ~BIT(0);
@@ -266,7 +266,7 @@ static void dio48e_irq_mask(struct irq_data *data)
 		/* disable interrupts */
 		inb(dio48egpio->base + 0xB);
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 }
 
 static void dio48e_irq_unmask(struct irq_data *data)
@@ -280,7 +280,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
 	if (offset != 19 && offset != 43)
 		return;
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 	if (!dio48egpio->irq_mask) {
 		/* enable interrupts */
@@ -293,7 +293,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
 	else
 		dio48egpio->irq_mask |= BIT(1);
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 }
 
 static int dio48e_irq_set_type(struct irq_data *data, unsigned flow_type)
@@ -329,11 +329,11 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
 		generic_handle_irq(irq_find_mapping(chip->irqdomain,
 			19 + gpio*24));
 
-	spin_lock(&dio48egpio->lock);
+	raw_spin_lock(&dio48egpio->lock);
 
 	outb(0x00, dio48egpio->base + 0xF);
 
-	spin_unlock(&dio48egpio->lock);
+	raw_spin_unlock(&dio48egpio->lock);
 
 	return IRQ_HANDLED;
 }
@@ -388,7 +388,7 @@ static int dio48e_probe(struct device *dev, unsigned int id)
 	dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
 	dio48egpio->base = base[id];
 
-	spin_lock_init(&dio48egpio->lock);
+	raw_spin_lock_init(&dio48egpio->lock);
 
 	err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio);
 	if (err) {
diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index 568375a7ebc265a861cd3f5dcd9930d6d604427b..337c048168d82d90c68f2da6425621763a993146 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -51,7 +51,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
  */
 struct idi_48_gpio {
 	struct gpio_chip chip;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	spinlock_t ack_lock;
 	unsigned char irq_mask[6];
 	unsigned base;
@@ -112,11 +112,12 @@ static void idi_48_irq_mask(struct irq_data *data)
 			if (!idi48gpio->irq_mask[boundary]) {
 				idi48gpio->cos_enb &= ~BIT(boundary);
 
-				spin_lock_irqsave(&idi48gpio->lock, flags);
+				raw_spin_lock_irqsave(&idi48gpio->lock, flags);
 
 				outb(idi48gpio->cos_enb, idi48gpio->base + 7);
 
-				spin_unlock_irqrestore(&idi48gpio->lock, flags);
+				raw_spin_unlock_irqrestore(&idi48gpio->lock,
+						           flags);
 			}
 
 			return;
@@ -145,11 +146,12 @@ static void idi_48_irq_unmask(struct irq_data *data)
 			if (!prev_irq_mask) {
 				idi48gpio->cos_enb |= BIT(boundary);
 
-				spin_lock_irqsave(&idi48gpio->lock, flags);
+				raw_spin_lock_irqsave(&idi48gpio->lock, flags);
 
 				outb(idi48gpio->cos_enb, idi48gpio->base + 7);
 
-				spin_unlock_irqrestore(&idi48gpio->lock, flags);
+				raw_spin_unlock_irqrestore(&idi48gpio->lock,
+						           flags);
 			}
 
 			return;
@@ -186,11 +188,11 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
 
 	spin_lock(&idi48gpio->ack_lock);
 
-	spin_lock(&idi48gpio->lock);
+	raw_spin_lock(&idi48gpio->lock);
 
 	cos_status = inb(idi48gpio->base + 7);
 
-	spin_unlock(&idi48gpio->lock);
+	raw_spin_unlock(&idi48gpio->lock);
 
 	/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
 	if (cos_status & BIT(6)) {
@@ -256,7 +258,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
 	idi48gpio->chip.get = idi_48_gpio_get;
 	idi48gpio->base = base[id];
 
-	spin_lock_init(&idi48gpio->lock);
+	raw_spin_lock_init(&idi48gpio->lock);
 	spin_lock_init(&idi48gpio->ack_lock);
 
 	err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c
index 7053cf7366488b8516896aa7365db1d8c3549db7..5281e1cedb01d8937373cdda3c804c25f3f342e1 100644
--- a/drivers/gpio/gpio-104-idio-16.c
+++ b/drivers/gpio/gpio-104-idio-16.c
@@ -50,7 +50,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
  */
 struct idio_16_gpio {
 	struct gpio_chip chip;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned long irq_mask;
 	unsigned base;
 	unsigned out_state;
@@ -99,7 +99,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	if (offset > 15)
 		return;
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 	if (value)
 		idio16gpio->out_state |= mask;
@@ -111,7 +111,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	else
 		outb(idio16gpio->out_state, idio16gpio->base);
 
-	spin_unlock_irqrestore(&idio16gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 }
 
 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
@@ -120,7 +120,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 	unsigned long flags;
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 	idio16gpio->out_state &= ~*mask;
 	idio16gpio->out_state |= *mask & *bits;
@@ -130,7 +130,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 	if ((*mask >> 8) & 0xFF)
 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
 
-	spin_unlock_irqrestore(&idio16gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 }
 
 static void idio_16_irq_ack(struct irq_data *data)
@@ -147,11 +147,11 @@ static void idio_16_irq_mask(struct irq_data *data)
 	idio16gpio->irq_mask &= ~mask;
 
 	if (!idio16gpio->irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 		outb(0, idio16gpio->base + 2);
 
-		spin_unlock_irqrestore(&idio16gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 	}
 }
 
@@ -166,11 +166,11 @@ static void idio_16_irq_unmask(struct irq_data *data)
 	idio16gpio->irq_mask |= mask;
 
 	if (!prev_irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 		inb(idio16gpio->base + 2);
 
-		spin_unlock_irqrestore(&idio16gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 	}
 }
 
@@ -201,11 +201,11 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
 		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
 
-	spin_lock(&idio16gpio->lock);
+	raw_spin_lock(&idio16gpio->lock);
 
 	outb(0, idio16gpio->base + 1);
 
-	spin_unlock(&idio16gpio->lock);
+	raw_spin_unlock(&idio16gpio->lock);
 
 	return IRQ_HANDLED;
 }
@@ -249,7 +249,7 @@ static int idio_16_probe(struct device *dev, unsigned int id)
 	idio16gpio->base = base[id];
 	idio16gpio->out_state = 0xFFFF;
 
-	spin_lock_init(&idio16gpio->lock);
+	raw_spin_lock_init(&idio16gpio->lock);
 
 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 	if (err) {
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index 3fe6a21e05a5718d8769bf2dd505cb5968f41207..17485dc20384b1e849d7d89827b48ab7546abb8d 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -38,7 +38,7 @@
 */
 struct altera_gpio_chip {
 	struct of_mm_gpio_chip mmchip;
-	spinlock_t gpio_lock;
+	raw_spinlock_t gpio_lock;
 	int interrupt_trigger;
 	int mapped_irq;
 };
@@ -53,12 +53,12 @@ static void altera_gpio_irq_unmask(struct irq_data *d)
 	altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
 	mm_gc = &altera_gc->mmchip;
 
-	spin_lock_irqsave(&altera_gc->gpio_lock, flags);
+	raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
 	intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
 	/* Set ALTERA_GPIO_IRQ_MASK bit to unmask */
 	intmask |= BIT(irqd_to_hwirq(d));
 	writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
-	spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
 }
 
 static void altera_gpio_irq_mask(struct irq_data *d)
@@ -71,12 +71,12 @@ static void altera_gpio_irq_mask(struct irq_data *d)
 	altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
 	mm_gc = &altera_gc->mmchip;
 
-	spin_lock_irqsave(&altera_gc->gpio_lock, flags);
+	raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags);
 	intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
 	/* Clear ALTERA_GPIO_IRQ_MASK bit to mask */
 	intmask &= ~BIT(irqd_to_hwirq(d));
 	writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
-	spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
 }
 
 /**
@@ -140,14 +140,14 @@ static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 	mm_gc = to_of_mm_gpio_chip(gc);
 	chip = gpiochip_get_data(gc);
 
-	spin_lock_irqsave(&chip->gpio_lock, flags);
+	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
 	data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
 	if (value)
 		data_reg |= BIT(offset);
 	else
 		data_reg &= ~BIT(offset);
 	writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA);
-	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
 }
 
 static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
@@ -160,12 +160,12 @@ static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
 	mm_gc = to_of_mm_gpio_chip(gc);
 	chip = gpiochip_get_data(gc);
 
-	spin_lock_irqsave(&chip->gpio_lock, flags);
+	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
 	/* Set pin as input, assumes software controlled IP */
 	gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
 	gpio_ddr &= ~BIT(offset);
 	writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
-	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
 
 	return 0;
 }
@@ -181,7 +181,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc,
 	mm_gc = to_of_mm_gpio_chip(gc);
 	chip = gpiochip_get_data(gc);
 
-	spin_lock_irqsave(&chip->gpio_lock, flags);
+	raw_spin_lock_irqsave(&chip->gpio_lock, flags);
 	/* Sets the GPIO value */
 	data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
 	if (value)
@@ -194,7 +194,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc,
 	gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
 	gpio_ddr |= BIT(offset);
 	writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
-	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+	raw_spin_unlock_irqrestore(&chip->gpio_lock, flags);
 
 	return 0;
 }
@@ -262,7 +262,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
 	if (!altera_gc)
 		return -ENOMEM;
 
-	spin_lock_init(&altera_gc->gpio_lock);
+	raw_spin_lock_init(&altera_gc->gpio_lock);
 
 	if (of_property_read_u32(node, "altr,ngpio", &reg))
 		/* By default assume maximum ngpio */
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 1f91557717a65a0a33dda2446dde9d580aa30b83..cd23fd727f9528abf56a178c8f10295943f41819 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
 
 #include <linux/mfd/arizona/core.h>
@@ -41,13 +42,38 @@ static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
 	struct arizona *arizona = arizona_gpio->arizona;
-	unsigned int val;
+	unsigned int reg, val;
 	int ret;
 
-	ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val);
+	reg = ARIZONA_GPIO1_CTRL + offset;
+	ret = regmap_read(arizona->regmap, reg, &val);
 	if (ret < 0)
 		return ret;
 
+	/* Resume to read actual registers for input pins */
+	if (val & ARIZONA_GPN_DIR) {
+		ret = pm_runtime_get_sync(chip->parent);
+		if (ret < 0) {
+			dev_err(chip->parent, "Failed to resume: %d\n", ret);
+			return ret;
+		}
+
+		/* Register is cached, drop it to ensure a physical read */
+		ret = regcache_drop_region(arizona->regmap, reg, reg);
+		if (ret < 0) {
+			dev_err(chip->parent, "Failed to drop cache: %d\n",
+				ret);
+			return ret;
+		}
+
+		ret = regmap_read(arizona->regmap, reg, &val);
+		if (ret < 0)
+			return ret;
+
+		pm_runtime_mark_last_busy(chip->parent);
+		pm_runtime_put_autosuspend(chip->parent);
+	}
+
 	if (val & ARIZONA_GPN_LVL)
 		return 1;
 	else
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index fb16cc771c0ddfd88f8b51ad321f59c6601200eb..ccea609676eebfe8bbcd6e01acaa8f6c4499ffe7 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -9,14 +9,18 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
+#include <asm/div64.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/hashtable.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/gpio/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
 
 struct aspeed_bank_props {
 	unsigned int bank;
@@ -29,59 +33,85 @@ struct aspeed_gpio_config {
 	const struct aspeed_bank_props *props;
 };
 
+/*
+ * @offset_timer: Maps an offset to an @timer_users index, or zero if disabled
+ * @timer_users: Tracks the number of users for each timer
+ *
+ * The @timer_users has four elements but the first element is unused. This is
+ * to simplify accounting and indexing, as a zero value in @offset_timer
+ * represents disabled debouncing for the GPIO. Any other value for an element
+ * of @offset_timer is used as an index into @timer_users. This behaviour of
+ * the zero value aligns with the behaviour of zero built from the timer
+ * configuration registers (i.e. debouncing is disabled).
+ */
 struct aspeed_gpio {
 	struct gpio_chip chip;
 	spinlock_t lock;
 	void __iomem *base;
 	int irq;
 	const struct aspeed_gpio_config *config;
+
+	u8 *offset_timer;
+	unsigned int timer_users[4];
+	struct clk *clk;
 };
 
 struct aspeed_gpio_bank {
 	uint16_t	val_regs;
 	uint16_t	irq_regs;
+	uint16_t	debounce_regs;
 	const char	names[4][3];
 };
 
+static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 };
+
 static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
 	{
 		.val_regs = 0x0000,
 		.irq_regs = 0x0008,
+		.debounce_regs = 0x0040,
 		.names = { "A", "B", "C", "D" },
 	},
 	{
 		.val_regs = 0x0020,
 		.irq_regs = 0x0028,
+		.debounce_regs = 0x0048,
 		.names = { "E", "F", "G", "H" },
 	},
 	{
 		.val_regs = 0x0070,
 		.irq_regs = 0x0098,
+		.debounce_regs = 0x00b0,
 		.names = { "I", "J", "K", "L" },
 	},
 	{
 		.val_regs = 0x0078,
 		.irq_regs = 0x00e8,
+		.debounce_regs = 0x0100,
 		.names = { "M", "N", "O", "P" },
 	},
 	{
 		.val_regs = 0x0080,
 		.irq_regs = 0x0118,
+		.debounce_regs = 0x0130,
 		.names = { "Q", "R", "S", "T" },
 	},
 	{
 		.val_regs = 0x0088,
 		.irq_regs = 0x0148,
+		.debounce_regs = 0x0160,
 		.names = { "U", "V", "W", "X" },
 	},
 	{
 		.val_regs = 0x01E0,
 		.irq_regs = 0x0178,
+		.debounce_regs = 0x0190,
 		.names = { "Y", "Z", "AA", "AB" },
 	},
 	{
 		.val_regs = 0x01E8,
 		.irq_regs = 0x01A8,
+		.debounce_regs = 0x01c0,
 		.names = { "AC", "", "", "" },
 	},
 };
@@ -99,6 +129,13 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
 #define GPIO_IRQ_TYPE2	0x0c
 #define GPIO_IRQ_STATUS	0x10
 
+#define GPIO_DEBOUNCE_SEL1 0x00
+#define GPIO_DEBOUNCE_SEL2 0x04
+
+#define _GPIO_SET_DEBOUNCE(t, o, i) ((!!((t) & BIT(i))) << GPIO_OFFSET(o))
+#define GPIO_SET_DEBOUNCE1(t, o) _GPIO_SET_DEBOUNCE(t, o, 1)
+#define GPIO_SET_DEBOUNCE2(t, o) _GPIO_SET_DEBOUNCE(t, o, 0)
+
 static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
 {
 	unsigned int bank = GPIO_BANK(offset);
@@ -144,6 +181,7 @@ static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
 }
 
 #define have_irq(g, o) have_input((g), (o))
+#define have_debounce(g, o) have_input((g), (o))
 
 static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
 {
@@ -506,6 +544,231 @@ static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
 	pinctrl_free_gpio(chip->base + offset);
 }
 
+static inline void __iomem *bank_debounce_reg(struct aspeed_gpio *gpio,
+		const struct aspeed_gpio_bank *bank,
+		unsigned int reg)
+{
+	return gpio->base + bank->debounce_regs + reg;
+}
+
+static int usecs_to_cycles(struct aspeed_gpio *gpio, unsigned long usecs,
+		u32 *cycles)
+{
+	u64 rate;
+	u64 n;
+	u32 r;
+
+	rate = clk_get_rate(gpio->clk);
+	if (!rate)
+		return -ENOTSUPP;
+
+	n = rate * usecs;
+	r = do_div(n, 1000000);
+
+	if (n >= U32_MAX)
+		return -ERANGE;
+
+	/* At least as long as the requested time */
+	*cycles = n + (!!r);
+
+	return 0;
+}
+
+/* Call under gpio->lock */
+static int register_allocated_timer(struct aspeed_gpio *gpio,
+		unsigned int offset, unsigned int timer)
+{
+	if (WARN(gpio->offset_timer[offset] != 0,
+				"Offset %d already allocated timer %d\n",
+				offset, gpio->offset_timer[offset]))
+		return -EINVAL;
+
+	if (WARN(gpio->timer_users[timer] == UINT_MAX,
+				"Timer user count would overflow\n"))
+		return -EPERM;
+
+	gpio->offset_timer[offset] = timer;
+	gpio->timer_users[timer]++;
+
+	return 0;
+}
+
+/* Call under gpio->lock */
+static int unregister_allocated_timer(struct aspeed_gpio *gpio,
+		unsigned int offset)
+{
+	if (WARN(gpio->offset_timer[offset] == 0,
+				"No timer allocated to offset %d\n", offset))
+		return -EINVAL;
+
+	if (WARN(gpio->timer_users[gpio->offset_timer[offset]] == 0,
+				"No users recorded for timer %d\n",
+				gpio->offset_timer[offset]))
+		return -EINVAL;
+
+	gpio->timer_users[gpio->offset_timer[offset]]--;
+	gpio->offset_timer[offset] = 0;
+
+	return 0;
+}
+
+/* Call under gpio->lock */
+static inline bool timer_allocation_registered(struct aspeed_gpio *gpio,
+		unsigned int offset)
+{
+	return gpio->offset_timer[offset] > 0;
+}
+
+/* Call under gpio->lock */
+static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset,
+		unsigned int timer)
+{
+	const struct aspeed_gpio_bank *bank = to_bank(offset);
+	const u32 mask = GPIO_BIT(offset);
+	void __iomem *addr;
+	u32 val;
+
+	addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL1);
+	val = ioread32(addr);
+	iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE1(timer, offset), addr);
+
+	addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL2);
+	val = ioread32(addr);
+	iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE2(timer, offset), addr);
+}
+
+static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
+				    unsigned long usecs)
+{
+	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
+	u32 requested_cycles;
+	unsigned long flags;
+	int rc;
+	int i;
+
+	rc = usecs_to_cycles(gpio, usecs, &requested_cycles);
+	if (rc < 0) {
+		dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n",
+				usecs, clk_get_rate(gpio->clk), rc);
+		return rc;
+	}
+
+	spin_lock_irqsave(&gpio->lock, flags);
+
+	if (timer_allocation_registered(gpio, offset)) {
+		rc = unregister_allocated_timer(gpio, offset);
+		if (rc < 0)
+			goto out;
+	}
+
+	/* Try to find a timer already configured for the debounce period */
+	for (i = 1; i < ARRAY_SIZE(debounce_timers); i++) {
+		u32 cycles;
+
+		cycles = ioread32(gpio->base + debounce_timers[i]);
+		if (requested_cycles == cycles)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(debounce_timers)) {
+		int j;
+
+		/*
+		 * As there are no timers configured for the requested debounce
+		 * period, find an unused timer instead
+		 */
+		for (j = 1; j < ARRAY_SIZE(gpio->timer_users); j++) {
+			if (gpio->timer_users[j] == 0)
+				break;
+		}
+
+		if (j == ARRAY_SIZE(gpio->timer_users)) {
+			dev_warn(chip->parent,
+					"Debounce timers exhausted, cannot debounce for period %luus\n",
+					usecs);
+
+			rc = -EPERM;
+
+			/*
+			 * We already adjusted the accounting to remove @offset
+			 * as a user of its previous timer, so also configure
+			 * the hardware so @offset has timers disabled for
+			 * consistency.
+			 */
+			configure_timer(gpio, offset, 0);
+			goto out;
+		}
+
+		i = j;
+
+		iowrite32(requested_cycles, gpio->base + debounce_timers[i]);
+	}
+
+	if (WARN(i == 0, "Cannot register index of disabled timer\n")) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	register_allocated_timer(gpio, offset, i);
+	configure_timer(gpio, offset, i);
+
+out:
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return rc;
+}
+
+static int disable_debounce(struct gpio_chip *chip, unsigned int offset)
+{
+	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&gpio->lock, flags);
+
+	rc = unregister_allocated_timer(gpio, offset);
+	if (!rc)
+		configure_timer(gpio, offset, 0);
+
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return rc;
+}
+
+static int set_debounce(struct gpio_chip *chip, unsigned int offset,
+				    unsigned long usecs)
+{
+	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
+
+	if (!have_debounce(gpio, offset))
+		return -ENOTSUPP;
+
+	if (usecs)
+		return enable_debounce(chip, offset, usecs);
+
+	return disable_debounce(chip, offset);
+}
+
+static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+				  unsigned long config)
+{
+	unsigned long param = pinconf_to_config_param(config);
+	u32 arg = pinconf_to_config_argument(config);
+
+	if (param == PIN_CONFIG_INPUT_DEBOUNCE)
+		return set_debounce(chip, offset, arg);
+	else if (param == PIN_CONFIG_BIAS_DISABLE ||
+			param == PIN_CONFIG_BIAS_PULL_DOWN ||
+			param == PIN_CONFIG_DRIVE_STRENGTH)
+		return pinctrl_gpio_set_config(offset, config);
+	else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN ||
+			param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
+		/* Return -ENOTSUPP to trigger emulation, as per datasheet */
+		return -ENOTSUPP;
+
+	return -ENOTSUPP;
+}
+
 /*
  * Any banks not specified in a struct aspeed_bank_props array are assumed to
  * have the properties:
@@ -565,8 +828,16 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
 	if (!gpio_id)
 		return -EINVAL;
 
+	gpio->clk = of_clk_get(pdev->dev.of_node, 0);
+	if (IS_ERR(gpio->clk)) {
+		dev_warn(&pdev->dev,
+				"No HPLL clock phandle provided, debouncing disabled\n");
+		gpio->clk = NULL;
+	}
+
 	gpio->config = gpio_id->data;
 
+	gpio->chip.parent = &pdev->dev;
 	gpio->chip.ngpio = gpio->config->nr_gpios;
 	gpio->chip.parent = &pdev->dev;
 	gpio->chip.direction_input = aspeed_gpio_dir_in;
@@ -576,6 +847,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
 	gpio->chip.free = aspeed_gpio_free;
 	gpio->chip.get = aspeed_gpio_get;
 	gpio->chip.set = aspeed_gpio_set;
+	gpio->chip.set_config = aspeed_gpio_set_config;
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.base = -1;
 	gpio->chip.irq_need_valid_mask = true;
@@ -584,6 +856,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
 	if (rc < 0)
 		return rc;
 
+	gpio->offset_timer =
+		devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);
+
 	return aspeed_gpio_setup_irqs(gpio, pdev);
 }
 
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index dc37dbe4b46d8889bfaddeac0c492dd6ed56090c..f33d4a5fe6718e29484e9d42fdb439def1eb4666 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -32,7 +32,7 @@
 struct ath79_gpio_ctrl {
 	struct gpio_chip gc;
 	void __iomem *base;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned long both_edges;
 };
 
@@ -74,9 +74,9 @@ static void ath79_gpio_irq_unmask(struct irq_data *data)
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 
-	spin_lock_irqsave(&ctrl->lock, flags);
+	raw_spin_lock_irqsave(&ctrl->lock, flags);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
 static void ath79_gpio_irq_mask(struct irq_data *data)
@@ -85,9 +85,9 @@ static void ath79_gpio_irq_mask(struct irq_data *data)
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 
-	spin_lock_irqsave(&ctrl->lock, flags);
+	raw_spin_lock_irqsave(&ctrl->lock, flags);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
 static void ath79_gpio_irq_enable(struct irq_data *data)
@@ -96,10 +96,10 @@ static void ath79_gpio_irq_enable(struct irq_data *data)
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 
-	spin_lock_irqsave(&ctrl->lock, flags);
+	raw_spin_lock_irqsave(&ctrl->lock, flags);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
 static void ath79_gpio_irq_disable(struct irq_data *data)
@@ -108,10 +108,10 @@ static void ath79_gpio_irq_disable(struct irq_data *data)
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 
-	spin_lock_irqsave(&ctrl->lock, flags);
+	raw_spin_lock_irqsave(&ctrl->lock, flags);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0);
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 }
 
 static int ath79_gpio_irq_set_type(struct irq_data *data,
@@ -140,7 +140,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
 		return -EINVAL;
 	}
 
-	spin_lock_irqsave(&ctrl->lock, flags);
+	raw_spin_lock_irqsave(&ctrl->lock, flags);
 
 	if (flow_type == IRQ_TYPE_EDGE_BOTH) {
 		ctrl->both_edges |= mask;
@@ -165,7 +165,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
 		ath79_gpio_update_bits(
 			ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
 
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 
 	return 0;
 }
@@ -191,7 +191,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
 
 	chained_irq_enter(irqchip, desc);
 
-	spin_lock_irqsave(&ctrl->lock, flags);
+	raw_spin_lock_irqsave(&ctrl->lock, flags);
 
 	pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING);
 
@@ -203,7 +203,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
 				both_edges, ~state);
 	}
 
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 
 	if (pending) {
 		for_each_set_bit(irq, &pending, gc->ngpio)
@@ -262,7 +262,7 @@ static int ath79_gpio_probe(struct platform_device *pdev)
 	if (!ctrl->base)
 		return -ENOMEM;
 
-	spin_lock_init(&ctrl->lock);
+	raw_spin_lock_init(&ctrl->lock);
 	err = bgpio_init(&ctrl->gc, &pdev->dev, 4,
 			ctrl->base + AR71XX_GPIO_REG_IN,
 			ctrl->base + AR71XX_GPIO_REG_SET,
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index 41d0ac1425803eeeb5098c7a6f73d1c35aa17ce1..dfcf56ee3c6181fc64d0a074e2f5659fec35a6d8 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -67,7 +67,7 @@
 struct bcm_kona_gpio {
 	void __iomem *reg_base;
 	int num_bank;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	struct gpio_chip gpio_chip;
 	struct irq_domain *irq_domain;
 	struct bcm_kona_gpio_bank *banks;
@@ -95,13 +95,13 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
 	unsigned long flags;
 	int bank_id = GPIO_BANK(gpio);
 
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
 	val |= BIT(gpio);
 	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
 static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
@@ -111,13 +111,13 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
 	unsigned long flags;
 	int bank_id = GPIO_BANK(gpio);
 
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
 	val &= ~BIT(gpio);
 	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
 static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
@@ -141,7 +141,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
 
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	/* this function only applies to output pin */
 	if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
@@ -154,7 +154,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
 	writel(val, reg_base + reg_offset);
 
 out:
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
 static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
@@ -168,7 +168,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
 
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
 		reg_offset = GPIO_IN_STATUS(bank_id);
@@ -178,7 +178,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
 	/* read the GPIO bank status */
 	val = readl(reg_base + reg_offset);
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	/* return the specified bit status */
 	return !!(val & BIT(bit));
@@ -208,14 +208,14 @@ static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
 	val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
 	writel(val, reg_base + GPIO_CONTROL(gpio));
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
 }
@@ -232,7 +232,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
 
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
@@ -244,7 +244,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
 	val |= BIT(bit);
 	writel(val, reg_base + reg_offset);
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
 }
@@ -288,7 +288,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
 	}
 
 	/* spin lock for read-modify-write of the GPIO register */
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_DBR_MASK;
@@ -303,7 +303,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
 
 	writel(val, reg_base + GPIO_CONTROL(gpio));
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
 }
@@ -347,13 +347,13 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
 
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_INT_STATUS(bank_id));
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_STATUS(bank_id));
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
 static void bcm_kona_gpio_irq_mask(struct irq_data *d)
@@ -368,13 +368,13 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
 
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_INT_MASK(bank_id));
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_MASK(bank_id));
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
 static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
@@ -389,13 +389,13 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
 
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 }
 
 static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
@@ -431,14 +431,14 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 		return -EINVAL;
 	}
 
-	spin_lock_irqsave(&kona_gpio->lock, flags);
+	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_ITR_MASK;
 	val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
 	writel(val, reg_base + GPIO_CONTROL(gpio));
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 	return 0;
 }
@@ -655,7 +655,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
 						 bank);
 	}
 
-	spin_lock_init(&kona_gpio->lock);
+	raw_spin_lock_init(&kona_gpio->lock);
 
 	return 0;
 
diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c
new file mode 100644
index 0000000000000000000000000000000000000000..5224a946e8aba0f26dd9c7b50bc81735e866237b
--- /dev/null
+++ b/drivers/gpio/gpio-bd9571mwv.c
@@ -0,0 +1,144 @@
+/*
+ * ROHM BD9571MWV-M GPIO driver
+ *
+ * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License version 2 for more details.
+ *
+ * Based on the TPS65086 driver
+ *
+ * NOTE: Interrupts are not supported yet.
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/bd9571mwv.h>
+
+struct bd9571mwv_gpio {
+	struct gpio_chip chip;
+	struct bd9571mwv *bd;
+};
+
+static int bd9571mwv_gpio_get_direction(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
+	int ret, val;
+
+	ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_DIR, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(offset);
+}
+
+static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip,
+					 unsigned int offset)
+{
+	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
+
+	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR,
+			   BIT(offset), 0);
+
+	return 0;
+}
+
+static int bd9571mwv_gpio_direction_output(struct gpio_chip *chip,
+					  unsigned int offset, int value)
+{
+	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
+
+	/* Set the initial value */
+	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT,
+			   BIT(offset), value ? BIT(offset) : 0);
+	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR,
+			   BIT(offset), BIT(offset));
+
+	return 0;
+}
+
+static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
+	int ret, val;
+
+	ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_IN, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(offset);
+}
+
+static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset,
+			      int value)
+{
+	struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip);
+
+	regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT,
+			   BIT(offset), value ? BIT(offset) : 0);
+}
+
+static const struct gpio_chip template_chip = {
+	.label			= "bd9571mwv-gpio",
+	.owner			= THIS_MODULE,
+	.get_direction		= bd9571mwv_gpio_get_direction,
+	.direction_input	= bd9571mwv_gpio_direction_input,
+	.direction_output	= bd9571mwv_gpio_direction_output,
+	.get			= bd9571mwv_gpio_get,
+	.set			= bd9571mwv_gpio_set,
+	.base			= -1,
+	.ngpio			= 2,
+	.can_sleep		= true,
+};
+
+static int bd9571mwv_gpio_probe(struct platform_device *pdev)
+{
+	struct bd9571mwv_gpio *gpio;
+	int ret;
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, gpio);
+
+	gpio->bd = dev_get_drvdata(pdev->dev.parent);
+	gpio->chip = template_chip;
+	gpio->chip.parent = gpio->bd->dev;
+
+	ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id bd9571mwv_gpio_id_table[] = {
+	{ "bd9571mwv-gpio", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, bd9571mwv_gpio_id_table);
+
+static struct platform_driver bd9571mwv_gpio_driver = {
+	.driver = {
+		.name = "bd9571mwv-gpio",
+	},
+	.probe = bd9571mwv_gpio_probe,
+	.id_table = bd9571mwv_gpio_id_table,
+};
+module_platform_driver(bd9571mwv_gpio_driver);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
+MODULE_DESCRIPTION("BD9571MWV GPIO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 72f49d1e110dee2a3dadd4f3c136af1345ff103e..ac173575d3f69b07b31231f75cae8d721299addb 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -483,7 +483,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 	clk_prepare_enable(clk);
 
 	if (!pdata->gpio_unbanked) {
-		irq = irq_alloc_descs(-1, 0, ngpio, 0);
+		irq = devm_irq_alloc_descs(dev, -1, 0, ngpio, 0);
 		if (irq < 0) {
 			dev_err(dev, "Couldn't allocate IRQ numbers\n");
 			return irq;
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 9c15ee4ef4e9b3a560a537bf62447447f8a66732..f051c4552af570257b92bf5d7f80b2a706cbf721 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
@@ -55,6 +56,14 @@
 #define GPIO_SWPORT_DR_SIZE	(GPIO_SWPORTB_DR - GPIO_SWPORTA_DR)
 #define GPIO_SWPORT_DDR_SIZE	(GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR)
 
+#define GPIO_REG_OFFSET_V2	1
+
+#define GPIO_INTMASK_V2		0x44
+#define GPIO_INTTYPE_LEVEL_V2	0x34
+#define GPIO_INT_POLARITY_V2	0x38
+#define GPIO_INTSTATUS_V2	0x3c
+#define GPIO_PORTA_EOI_V2	0x40
+
 struct dwapb_gpio;
 
 #ifdef CONFIG_PM_SLEEP
@@ -87,14 +96,41 @@ struct dwapb_gpio {
 	struct dwapb_gpio_port	*ports;
 	unsigned int		nr_ports;
 	struct irq_domain	*domain;
+	unsigned int		flags;
 };
 
+static inline u32 gpio_reg_v2_convert(unsigned int offset)
+{
+	switch (offset) {
+	case GPIO_INTMASK:
+		return GPIO_INTMASK_V2;
+	case GPIO_INTTYPE_LEVEL:
+		return GPIO_INTTYPE_LEVEL_V2;
+	case GPIO_INT_POLARITY:
+		return GPIO_INT_POLARITY_V2;
+	case GPIO_INTSTATUS:
+		return GPIO_INTSTATUS_V2;
+	case GPIO_PORTA_EOI:
+		return GPIO_PORTA_EOI_V2;
+	}
+
+	return offset;
+}
+
+static inline u32 gpio_reg_convert(struct dwapb_gpio *gpio, unsigned int offset)
+{
+	if (gpio->flags & GPIO_REG_OFFSET_V2)
+		return gpio_reg_v2_convert(offset);
+
+	return offset;
+}
+
 static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset)
 {
 	struct gpio_chip *gc	= &gpio->ports[0].gc;
 	void __iomem *reg_base	= gpio->regs;
 
-	return gc->read_reg(reg_base + offset);
+	return gc->read_reg(reg_base + gpio_reg_convert(gpio, offset));
 }
 
 static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset,
@@ -103,7 +139,7 @@ static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset,
 	struct gpio_chip *gc	= &gpio->ports[0].gc;
 	void __iomem *reg_base	= gpio->regs;
 
-	gc->write_reg(reg_base + offset, val);
+	gc->write_reg(reg_base + gpio_reg_convert(gpio, offset), val);
 }
 
 static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
@@ -128,7 +164,7 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
 
 static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
 {
-	u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS);
+	u32 irq_status = dwapb_read(gpio, GPIO_INTSTATUS);
 	u32 ret = irq_status;
 
 	while (irq_status) {
@@ -348,8 +384,8 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
 		ct->chip.irq_disable = dwapb_irq_disable;
 		ct->chip.irq_request_resources = dwapb_irq_reqres;
 		ct->chip.irq_release_resources = dwapb_irq_relres;
-		ct->regs.ack = GPIO_PORTA_EOI;
-		ct->regs.mask = GPIO_INTMASK;
+		ct->regs.ack = gpio_reg_convert(gpio, GPIO_PORTA_EOI);
+		ct->regs.mask = gpio_reg_convert(gpio, GPIO_INTMASK);
 		ct->type = IRQ_TYPE_LEVEL_MASK;
 	}
 
@@ -532,6 +568,21 @@ dwapb_gpio_get_pdata(struct device *dev)
 	return pdata;
 }
 
+static const struct of_device_id dwapb_of_match[] = {
+	{ .compatible = "snps,dw-apb-gpio", .data = (void *)0},
+	{ .compatible = "apm,xgene-gpio-v2", .data = (void *)GPIO_REG_OFFSET_V2},
+	{ /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dwapb_of_match);
+
+static const struct acpi_device_id dwapb_acpi_match[] = {
+	{"HISI0181", 0},
+	{"APMC0D07", 0},
+	{"APMC0D81", GPIO_REG_OFFSET_V2},
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match);
+
 static int dwapb_gpio_probe(struct platform_device *pdev)
 {
 	unsigned int i;
@@ -567,6 +618,25 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(gpio->regs))
 		return PTR_ERR(gpio->regs);
 
+	gpio->flags = 0;
+	if (dev->of_node) {
+		const struct of_device_id *of_devid;
+
+		of_devid = of_match_device(dwapb_of_match, dev);
+		if (of_devid) {
+			if (of_devid->data)
+				gpio->flags = (uintptr_t)of_devid->data;
+		}
+	} else if (has_acpi_companion(dev)) {
+		const struct acpi_device_id *acpi_id;
+
+		acpi_id = acpi_match_device(dwapb_acpi_match, dev);
+		if (acpi_id) {
+			if (acpi_id->driver_data)
+				gpio->flags = acpi_id->driver_data;
+		}
+	}
+
 	for (i = 0; i < gpio->nr_ports; i++) {
 		err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
 		if (err)
@@ -593,19 +663,6 @@ static int dwapb_gpio_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id dwapb_of_match[] = {
-	{ .compatible = "snps,dw-apb-gpio" },
-	{ /* Sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, dwapb_of_match);
-
-static const struct acpi_device_id dwapb_acpi_match[] = {
-	{"HISI0181", 0},
-	{"APMC0D07", 0},
-	{ }
-};
-MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match);
-
 #ifdef CONFIG_PM_SLEEP
 static int dwapb_gpio_suspend(struct device *dev)
 {
diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c
index a254d5b07b941ecdb2c9e2fbe8a3ab54c946ee78..14c6aac267809baa0b8efd3f8ecc1bbb3db5693b 100644
--- a/drivers/gpio/gpio-etraxfs.c
+++ b/drivers/gpio/gpio-etraxfs.c
@@ -54,7 +54,7 @@
 struct etraxfs_gpio_info;
 
 struct etraxfs_gpio_block {
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	u32 mask;
 	u32 cfg;
 	u32 pins;
@@ -233,10 +233,10 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d)
 	struct etraxfs_gpio_block *block = chip->block;
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->mask &= ~BIT(grpirq);
 	writel(block->mask, block->regs + block->info->rw_intr_mask);
-	spin_unlock(&block->lock);
+	raw_spin_unlock(&block->lock);
 }
 
 static void etraxfs_gpio_irq_unmask(struct irq_data *d)
@@ -246,10 +246,10 @@ static void etraxfs_gpio_irq_unmask(struct irq_data *d)
 	struct etraxfs_gpio_block *block = chip->block;
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->mask |= BIT(grpirq);
 	writel(block->mask, block->regs + block->info->rw_intr_mask);
-	spin_unlock(&block->lock);
+	raw_spin_unlock(&block->lock);
 }
 
 static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
@@ -280,11 +280,11 @@ static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
 		return -EINVAL;
 	}
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->cfg &= ~(0x7 << (grpirq * 3));
 	block->cfg |= (cfg << (grpirq * 3));
 	writel(block->cfg, block->regs + block->info->rw_intr_cfg);
-	spin_unlock(&block->lock);
+	raw_spin_unlock(&block->lock);
 
 	return 0;
 }
@@ -297,7 +297,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 	int ret = -EBUSY;
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	if (block->group[grpirq])
 		goto out;
 
@@ -316,7 +316,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
 	}
 
 out:
-	spin_unlock(&block->lock);
+	raw_spin_unlock(&block->lock);
 	return ret;
 }
 
@@ -327,10 +327,10 @@ static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
 	struct etraxfs_gpio_block *block = chip->block;
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->group[grpirq] = 0;
 	gpiochip_unlock_as_irq(&chip->gc, d->hwirq);
-	spin_unlock(&block->lock);
+	raw_spin_unlock(&block->lock);
 }
 
 static struct irq_chip etraxfs_gpio_irq_chip = {
@@ -391,7 +391,7 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
 	if (!block)
 		return -ENOMEM;
 
-	spin_lock_init(&block->lock);
+	raw_spin_lock_init(&block->lock);
 
 	block->regs = regs;
 	block->info = info;
diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 05c8946d6446fe93ea0564b1638d6f502f14430f..08107677121708b806bf4cbe80f5e84392efa0e5 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -59,17 +59,6 @@ static int exar_set_direction(struct gpio_chip *chip, int direction,
 	return 0;
 }
 
-static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
-				 int value)
-{
-	return exar_set_direction(chip, 0, offset);
-}
-
-static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
-{
-	return exar_set_direction(chip, 1, offset);
-}
-
 static int exar_get(struct gpio_chip *chip, unsigned int reg)
 {
 	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
@@ -116,6 +105,18 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
 	exar_update(chip, addr, value, offset % 8);
 }
 
+static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
+				 int value)
+{
+	exar_set_value(chip, offset, value);
+	return exar_set_direction(chip, 0, offset);
+}
+
+static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+	return exar_set_direction(chip, 1, offset);
+}
+
 static int gpio_exar_probe(struct platform_device *pdev)
 {
 	struct pci_dev *pcidev = platform_get_drvdata(pdev);
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c
index 56bd76c337675e96aeeec8fecb6bec9161a9dadb..13350c9d7f5e88921773a9374277f7ed2358a9f8 100644
--- a/drivers/gpio/gpio-f7188x.c
+++ b/drivers/gpio/gpio-f7188x.c
@@ -37,14 +37,16 @@
 #define SIO_F71869A_ID		0x1007	/* F71869A chipset ID */
 #define SIO_F71882_ID		0x0541	/* F71882 chipset ID */
 #define SIO_F71889_ID		0x0909	/* F71889 chipset ID */
+#define SIO_F71889A_ID		0x1005	/* F71889A chipset ID */
 #define SIO_F81866_ID		0x1010	/* F81866 chipset ID */
 
-enum chips { f71869, f71869a, f71882fg, f71889f, f81866 };
+enum chips { f71869, f71869a, f71882fg, f71889a, f71889f, f81866 };
 
 static const char * const f7188x_names[] = {
 	"f71869",
 	"f71869a",
 	"f71882fg",
+	"f71889a",
 	"f71889f",
 	"f81866",
 };
@@ -187,6 +189,17 @@ static struct f7188x_gpio_bank f71882_gpio_bank[] = {
 	F7188X_GPIO_BANK(40, 4, 0xB0),
 };
 
+static struct f7188x_gpio_bank f71889a_gpio_bank[] = {
+	F7188X_GPIO_BANK(0, 7, 0xF0),
+	F7188X_GPIO_BANK(10, 7, 0xE0),
+	F7188X_GPIO_BANK(20, 8, 0xD0),
+	F7188X_GPIO_BANK(30, 8, 0xC0),
+	F7188X_GPIO_BANK(40, 8, 0xB0),
+	F7188X_GPIO_BANK(50, 5, 0xA0),
+	F7188X_GPIO_BANK(60, 8, 0x90),
+	F7188X_GPIO_BANK(70, 8, 0x80),
+};
+
 static struct f7188x_gpio_bank f71889_gpio_bank[] = {
 	F7188X_GPIO_BANK(0, 7, 0xF0),
 	F7188X_GPIO_BANK(10, 7, 0xE0),
@@ -382,6 +395,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
 		data->nr_bank = ARRAY_SIZE(f71882_gpio_bank);
 		data->bank = f71882_gpio_bank;
 		break;
+	case f71889a:
+		data->nr_bank = ARRAY_SIZE(f71889a_gpio_bank);
+		data->bank = f71889a_gpio_bank;
+		break;
 	case f71889f:
 		data->nr_bank = ARRAY_SIZE(f71889_gpio_bank);
 		data->bank = f71889_gpio_bank;
@@ -443,6 +460,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
 	case SIO_F71882_ID:
 		sio->type = f71882fg;
 		break;
+	case SIO_F71889A_ID:
+		sio->type = f71889a;
+		break;
 	case SIO_F71889_ID:
 		sio->type = f71889f;
 		break;
@@ -538,6 +558,6 @@ static void __exit f7188x_gpio_exit(void)
 }
 module_exit(f7188x_gpio_exit);
 
-MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889F and F81866");
+MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889A, F71889F and F81866");
 MODULE_AUTHOR("Simon Guinot <simon.guinot@sequanux.org>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-gemini.c b/drivers/gpio/gpio-ftgpio010.c
similarity index 73%
rename from drivers/gpio/gpio-gemini.c
rename to drivers/gpio/gpio-ftgpio010.c
index 962485163b7f0de3006c86e4b039f338dfcbafea..e9386f8b67f568e3b6d9ff4b0376c86b0874c442 100644
--- a/drivers/gpio/gpio-gemini.c
+++ b/drivers/gpio/gpio-ftgpio010.c
@@ -1,5 +1,5 @@
 /*
- * Gemini gpiochip and interrupt routines
+ * Faraday Technolog FTGPIO010 gpiochip and interrupt routines
  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
  *
  * Based on arch/arm/mach-gemini/gpio.c:
@@ -35,28 +35,28 @@
 #define GPIO_DEBOUNCE_PRESCALE	0x44
 
 /**
- * struct gemini_gpio - Gemini GPIO state container
+ * struct ftgpio_gpio - Gemini GPIO state container
  * @dev: containing device for this instance
  * @gc: gpiochip for this instance
  */
-struct gemini_gpio {
+struct ftgpio_gpio {
 	struct device *dev;
 	struct gpio_chip gc;
 	void __iomem *base;
 };
 
-static void gemini_gpio_ack_irq(struct irq_data *d)
+static void ftgpio_gpio_ack_irq(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct gemini_gpio *g = gpiochip_get_data(gc);
+	struct ftgpio_gpio *g = gpiochip_get_data(gc);
 
 	writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR);
 }
 
-static void gemini_gpio_mask_irq(struct irq_data *d)
+static void ftgpio_gpio_mask_irq(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct gemini_gpio *g = gpiochip_get_data(gc);
+	struct ftgpio_gpio *g = gpiochip_get_data(gc);
 	u32 val;
 
 	val = readl(g->base + GPIO_INT_EN);
@@ -64,10 +64,10 @@ static void gemini_gpio_mask_irq(struct irq_data *d)
 	writel(val, g->base + GPIO_INT_EN);
 }
 
-static void gemini_gpio_unmask_irq(struct irq_data *d)
+static void ftgpio_gpio_unmask_irq(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct gemini_gpio *g = gpiochip_get_data(gc);
+	struct ftgpio_gpio *g = gpiochip_get_data(gc);
 	u32 val;
 
 	val = readl(g->base + GPIO_INT_EN);
@@ -75,10 +75,10 @@ static void gemini_gpio_unmask_irq(struct irq_data *d)
 	writel(val, g->base + GPIO_INT_EN);
 }
 
-static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type)
+static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct gemini_gpio *g = gpiochip_get_data(gc);
+	struct ftgpio_gpio *g = gpiochip_get_data(gc);
 	u32 mask = BIT(irqd_to_hwirq(d));
 	u32 reg_both, reg_level, reg_type;
 
@@ -123,23 +123,23 @@ static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type)
 	writel(reg_level, g->base + GPIO_INT_LEVEL);
 	writel(reg_both, g->base + GPIO_INT_BOTH_EDGE);
 
-	gemini_gpio_ack_irq(d);
+	ftgpio_gpio_ack_irq(d);
 
 	return 0;
 }
 
-static struct irq_chip gemini_gpio_irqchip = {
-	.name = "GPIO",
-	.irq_ack = gemini_gpio_ack_irq,
-	.irq_mask = gemini_gpio_mask_irq,
-	.irq_unmask = gemini_gpio_unmask_irq,
-	.irq_set_type = gemini_gpio_set_irq_type,
+static struct irq_chip ftgpio_gpio_irqchip = {
+	.name = "FTGPIO010",
+	.irq_ack = ftgpio_gpio_ack_irq,
+	.irq_mask = ftgpio_gpio_mask_irq,
+	.irq_unmask = ftgpio_gpio_unmask_irq,
+	.irq_set_type = ftgpio_gpio_set_irq_type,
 };
 
-static void gemini_gpio_irq_handler(struct irq_desc *desc)
+static void ftgpio_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
-	struct gemini_gpio *g = gpiochip_get_data(gc);
+	struct ftgpio_gpio *g = gpiochip_get_data(gc);
 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
 	int offset;
 	unsigned long stat;
@@ -155,11 +155,11 @@ static void gemini_gpio_irq_handler(struct irq_desc *desc)
 	chained_irq_exit(irqchip, desc);
 }
 
-static int gemini_gpio_probe(struct platform_device *pdev)
+static int ftgpio_gpio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *res;
-	struct gemini_gpio *g;
+	struct ftgpio_gpio *g;
 	int irq;
 	int ret;
 
@@ -189,7 +189,7 @@ static int gemini_gpio_probe(struct platform_device *pdev)
 		dev_err(dev, "unable to init generic GPIO\n");
 		return ret;
 	}
-	g->gc.label = "Gemini";
+	g->gc.label = "FTGPIO010";
 	g->gc.base = -1;
 	g->gc.parent = dev;
 	g->gc.owner = THIS_MODULE;
@@ -204,33 +204,39 @@ static int gemini_gpio_probe(struct platform_device *pdev)
 	writel(0x0, g->base + GPIO_INT_MASK);
 	writel(~0x0, g->base + GPIO_INT_CLR);
 
-	ret = gpiochip_irqchip_add(&g->gc, &gemini_gpio_irqchip,
+	ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip,
 				   0, handle_bad_irq,
 				   IRQ_TYPE_NONE);
 	if (ret) {
 		dev_info(dev, "could not add irqchip\n");
 		return ret;
 	}
-	gpiochip_set_chained_irqchip(&g->gc, &gemini_gpio_irqchip,
-				     irq, gemini_gpio_irq_handler);
+	gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip,
+				     irq, ftgpio_gpio_irq_handler);
 
-	dev_info(dev, "Gemini GPIO @%p registered\n", g->base);
+	dev_info(dev, "FTGPIO010 @%p registered\n", g->base);
 
 	return 0;
 }
 
-static const struct of_device_id gemini_gpio_of_match[] = {
+static const struct of_device_id ftgpio_gpio_of_match[] = {
 	{
 		.compatible = "cortina,gemini-gpio",
 	},
+	{
+		.compatible = "moxa,moxart-gpio",
+	},
+	{
+		.compatible = "faraday,ftgpio010",
+	},
 	{},
 };
 
-static struct platform_driver gemini_gpio_driver = {
+static struct platform_driver ftgpio_gpio_driver = {
 	.driver = {
-		.name		= "gemini-gpio",
-		.of_match_table = of_match_ptr(gemini_gpio_of_match),
+		.name		= "ftgpio010-gpio",
+		.of_match_table = of_match_ptr(ftgpio_gpio_of_match),
 	},
-	.probe	= gemini_gpio_probe,
+	.probe	= ftgpio_gpio_probe,
 };
-builtin_platform_driver(gemini_gpio_driver);
+builtin_platform_driver(ftgpio_gpio_driver);
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index f40088d268c174e5cf26ef0a54c6838159d4a4d3..9dbdc3672f5e70514862ebb8e04a1ddce3b796b7 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -166,7 +166,7 @@ static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
 	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
 
-	return (readl(gpdr) & BIT(offset % 32)) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
+	return !(readl(gpdr) & BIT(offset % 32));
 }
 
 static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 796a5a4bc4f5e574a3dd05af6f546aa0775b01a2..78896a869fd9bb12c822f0e9a45f4d237ff72080 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -459,41 +459,31 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
 
 	chip = chip_save;
 	for (j = 0; j < 8; j++, chip++) {
-		irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j],
-					   NUMA_NO_NODE);
+		irq_base = devm_irq_alloc_descs(&pdev->dev, -1, IOH_IRQ_BASE,
+						num_ports[j], NUMA_NO_NODE);
 		if (irq_base < 0) {
 			dev_warn(&pdev->dev,
 				"ml_ioh_gpio: Failed to get IRQ base num\n");
-			chip->irq_base = -1;
 			ret = irq_base;
-			goto err_irq_alloc_descs;
+			goto err_gpiochip_add;
 		}
 		chip->irq_base = irq_base;
 		ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
 	}
 
 	chip = chip_save;
-	ret = request_irq(pdev->irq, ioh_gpio_handler,
-			     IRQF_SHARED, KBUILD_MODNAME, chip);
+	ret = devm_request_irq(&pdev->dev, pdev->irq, ioh_gpio_handler,
+			       IRQF_SHARED, KBUILD_MODNAME, chip);
 	if (ret != 0) {
 		dev_err(&pdev->dev,
 			"%s request_irq failed\n", __func__);
-		goto err_request_irq;
+		goto err_gpiochip_add;
 	}
 
 	pci_set_drvdata(pdev, chip);
 
 	return 0;
 
-err_request_irq:
-	chip = chip_save;
-err_irq_alloc_descs:
-	while (--j >= 0) {
-		chip--;
-		irq_free_descs(chip->irq_base, num_ports[j]);
-	}
-
-	chip = chip_save;
 err_gpiochip_add:
 	while (--i >= 0) {
 		chip--;
@@ -524,12 +514,8 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
 
 	chip_save = chip;
 
-	free_irq(pdev->irq, chip);
-
-	for (i = 0; i < 8; i++, chip++) {
-		irq_free_descs(chip->irq_base, num_ports[i]);
+	for (i = 0; i < 8; i++, chip++)
 		gpiochip_remove(&chip->gpio);
-	}
 
 	chip = chip_save;
 	pci_iounmap(pdev, chip->base);
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index d7d03ad052d007bd1d7531a015e4688e2f603754..f7da40e46c55c1f2103a7d7c2ff35da3ab82bbb4 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -575,6 +575,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 static const struct of_device_id bgpio_of_match[] = {
 	{ .compatible = "brcm,bcm6345-gpio" },
 	{ .compatible = "wd,mbl-gpio" },
+	{ .compatible = "ni,169445-nand-gpio" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, bgpio_of_match);
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
index d993386892138757b67be09b4df8a822e39e4017..c6dadac70593234c7e7be4e0a977c65446c9a11b 100644
--- a/drivers/gpio/gpio-mockup.c
+++ b/drivers/gpio/gpio-mockup.c
@@ -169,7 +169,7 @@ static int gpio_mockup_irqchip_setup(struct device *dev,
 	struct gpio_chip *gc = &chip->gc;
 	int irq_base, i;
 
-	irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0);
+	irq_base = devm_irq_alloc_descs(dev, -1, 0, gc->ngpio, 0);
 	if (irq_base < 0)
 		return irq_base;
 
@@ -372,25 +372,11 @@ static int gpio_mockup_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int gpio_mockup_remove(struct platform_device *pdev)
-{
-	struct gpio_mockup_chip *chips;
-	int i;
-
-	chips = platform_get_drvdata(pdev);
-
-	for (i = 0; i < gpio_mockup_params_nr >> 1; i++)
-		irq_free_descs(chips[i].gc.irq_base, chips[i].gc.ngpio);
-
-	return 0;
-}
-
 static struct platform_driver gpio_mockup_driver = {
 	.driver = {
 		.name = GPIO_MOCKUP_NAME,
 	},
 	.probe = gpio_mockup_probe,
-	.remove = gpio_mockup_remove,
 };
 
 static struct platform_device *pdev;
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
deleted file mode 100644
index d58d38906ba6a2335fe7bd4c1745c0716cecba50..0000000000000000000000000000000000000000
--- a/drivers/gpio/gpio-moxart.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * MOXA ART SoCs GPIO driver.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen@gmail.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/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/bitops.h>
-#include <linux/gpio/driver.h>
-
-#define GPIO_DATA_OUT		0x00
-#define GPIO_DATA_IN		0x04
-#define GPIO_PIN_DIRECTION	0x08
-
-static int moxart_gpio_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *res;
-	struct gpio_chip *gc;
-	void __iomem *base;
-	int ret;
-
-	gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
-			 base + GPIO_DATA_OUT, NULL,
-			 base + GPIO_PIN_DIRECTION, NULL,
-			 BGPIOF_READ_OUTPUT_REG_SET);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return ret;
-	}
-
-	gc->label = "moxart-gpio";
-	gc->request = gpiochip_generic_request;
-	gc->free = gpiochip_generic_free;
-	gc->base = 0;
-	gc->owner = THIS_MODULE;
-
-	ret = devm_gpiochip_add_data(dev, gc, NULL);
-	if (ret) {
-		dev_err(dev, "%s: gpiochip_add failed\n",
-			dev->of_node->full_name);
-		return ret;
-	}
-
-	return ret;
-}
-
-static const struct of_device_id moxart_gpio_match[] = {
-	{ .compatible = "moxa,moxart-gpio" },
-	{ }
-};
-
-static struct platform_driver moxart_gpio_driver = {
-	.driver	= {
-		.name		= "moxart-gpio",
-		.of_match_table	= moxart_gpio_match,
-	},
-	.probe	= moxart_gpio_probe,
-};
-builtin_platform_driver(moxart_gpio_driver);
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index a649556ac3ca8f488cd7462a253ade1157bbb1c1..19a92efabbef705b8826441c966cca4c55838bfd 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -42,29 +42,44 @@
 #include <linux/io.h>
 #include <linux/of_irq.h>
 #include <linux/of_device.h>
+#include <linux/pwm.h>
 #include <linux/clk.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+
+#include "gpiolib.h"
 
 /*
  * GPIO unit register offsets.
  */
-#define GPIO_OUT_OFF		0x0000
-#define GPIO_IO_CONF_OFF	0x0004
-#define GPIO_BLINK_EN_OFF	0x0008
-#define GPIO_IN_POL_OFF		0x000c
-#define GPIO_DATA_IN_OFF	0x0010
-#define GPIO_EDGE_CAUSE_OFF	0x0014
-#define GPIO_EDGE_MASK_OFF	0x0018
-#define GPIO_LEVEL_MASK_OFF	0x001c
+#define GPIO_OUT_OFF			0x0000
+#define GPIO_IO_CONF_OFF		0x0004
+#define GPIO_BLINK_EN_OFF		0x0008
+#define GPIO_IN_POL_OFF			0x000c
+#define GPIO_DATA_IN_OFF		0x0010
+#define GPIO_EDGE_CAUSE_OFF		0x0014
+#define GPIO_EDGE_MASK_OFF		0x0018
+#define GPIO_LEVEL_MASK_OFF		0x001c
+#define GPIO_BLINK_CNT_SELECT_OFF	0x0020
+
+/*
+ * PWM register offsets.
+ */
+#define PWM_BLINK_ON_DURATION_OFF	0x0
+#define PWM_BLINK_OFF_DURATION_OFF	0x4
+
 
 /* The MV78200 has per-CPU registers for edge mask and level mask */
 #define GPIO_EDGE_MASK_MV78200_OFF(cpu)	  ((cpu) ? 0x30 : 0x18)
 #define GPIO_LEVEL_MASK_MV78200_OFF(cpu)  ((cpu) ? 0x34 : 0x1C)
 
-/* The Armada XP has per-CPU registers for interrupt cause, interrupt
+/*
+ * The Armada XP has per-CPU registers for interrupt cause, interrupt
  * mask and interrupt level mask. Those are relative to the
- * percpu_membase. */
+ * percpu_membase.
+ */
 #define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
 #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu)  (0x10 + (cpu) * 0x4)
 #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
@@ -75,6 +90,20 @@
 
 #define MVEBU_MAX_GPIO_PER_BANK		32
 
+struct mvebu_pwm {
+	void __iomem		*membase;
+	unsigned long		 clk_rate;
+	struct gpio_desc	*gpiod;
+	struct pwm_chip		 chip;
+	spinlock_t		 lock;
+	struct mvebu_gpio_chip	*mvchip;
+
+	/* Used to preserve GPIO/PWM registers across suspend/resume */
+	u32			 blink_select;
+	u32			 blink_on_duration;
+	u32			 blink_off_duration;
+};
+
 struct mvebu_gpio_chip {
 	struct gpio_chip   chip;
 	spinlock_t	   lock;
@@ -84,48 +113,55 @@ struct mvebu_gpio_chip {
 	struct irq_domain *domain;
 	int		   soc_variant;
 
+	/* Used for PWM support */
+	struct clk	  *clk;
+	struct mvebu_pwm  *mvpwm;
+
 	/* Used to preserve GPIO registers across suspend/resume */
-	u32                out_reg;
-	u32                io_conf_reg;
-	u32                blink_en_reg;
-	u32                in_pol_reg;
-	u32                edge_mask_regs[4];
-	u32                level_mask_regs[4];
+	u32		   out_reg;
+	u32		   io_conf_reg;
+	u32		   blink_en_reg;
+	u32		   in_pol_reg;
+	u32		   edge_mask_regs[4];
+	u32		   level_mask_regs[4];
 };
 
 /*
  * Functions returning addresses of individual registers for a given
  * GPIO controller.
  */
-static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
+static 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)
+static 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)
+static void __iomem *mvebu_gpioreg_blink_counter_select(struct mvebu_gpio_chip
+							*mvchip)
+{
+	return mvchip->membase + GPIO_BLINK_CNT_SELECT_OFF;
+}
+
+static void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
 {
 	return mvchip->membase + GPIO_IO_CONF_OFF;
 }
 
-static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
+static void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
 {
 	return mvchip->membase + GPIO_IN_POL_OFF;
 }
 
-static inline void __iomem *
-mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
+static void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
 {
 	return mvchip->membase + GPIO_DATA_IN_OFF;
 }
 
-static inline void __iomem *
-mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
+static void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
 {
 	int cpu;
 
@@ -142,8 +178,7 @@ mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
 	}
 }
 
-static inline void __iomem *
-mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
+static void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
 {
 	int cpu;
 
@@ -182,10 +217,23 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
 }
 
 /*
- * Functions implementing the gpio_chip methods
+ * Functions returning addresses of individual registers for a given
+ * PWM controller.
  */
+static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm)
+{
+	return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF;
+}
+
+static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
+{
+	return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF;
+}
 
-static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
+/*
+ * Functions implementing the gpio_chip methods
+ */
+static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value)
 {
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	unsigned long flags;
@@ -194,19 +242,19 @@ static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_out(mvchip));
 	if (value)
-		u |= 1 << pin;
+		u |= BIT(pin);
 	else
-		u &= ~(1 << pin);
+		u &= ~BIT(pin);
 	writel_relaxed(u, mvebu_gpioreg_out(mvchip));
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 }
 
-static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
+static int mvebu_gpio_get(struct gpio_chip *chip, unsigned int pin)
 {
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	u32 u;
 
-	if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) {
+	if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin)) {
 		u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
 			readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
 	} else {
@@ -216,7 +264,8 @@ 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)
+static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned int pin,
+			     int value)
 {
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	unsigned long flags;
@@ -225,36 +274,38 @@ static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
 	if (value)
-		u |= 1 << pin;
+		u |= BIT(pin);
 	else
-		u &= ~(1 << pin);
+		u &= ~BIT(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)
+static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
 {
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	unsigned long flags;
 	int ret;
 	u32 u;
 
-	/* Check with the pinctrl driver whether this pin is usable as
-	 * an input GPIO */
+	/*
+	 * Check with the pinctrl driver whether this pin is usable as
+	 * an input GPIO
+	 */
 	ret = pinctrl_gpio_direction_input(chip->base + pin);
 	if (ret)
 		return ret;
 
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
-	u |= 1 << pin;
+	u |= BIT(pin);
 	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 
 	return 0;
 }
 
-static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
 				       int value)
 {
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
@@ -262,8 +313,10 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
 	int ret;
 	u32 u;
 
-	/* Check with the pinctrl driver whether this pin is usable as
-	 * an output GPIO */
+	/*
+	 * Check with the pinctrl driver whether this pin is usable as
+	 * an output GPIO
+	 */
 	ret = pinctrl_gpio_direction_output(chip->base + pin);
 	if (ret)
 		return ret;
@@ -273,16 +326,17 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
 
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
-	u &= ~(1 << pin);
+	u &= ~BIT(pin);
 	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 
 	return 0;
 }
 
-static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin)
 {
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
+
 	return irq_create_mapping(mvchip->domain, pin);
 }
 
@@ -389,7 +443,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 
 	pin = d->hwirq;
 
-	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin);
+	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin);
 	if (!u)
 		return -EINVAL;
 
@@ -409,13 +463,13 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 	case IRQ_TYPE_EDGE_RISING:
 	case IRQ_TYPE_LEVEL_HIGH:
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
-		u &= ~(1 << pin);
+		u &= ~BIT(pin);
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
 	case IRQ_TYPE_LEVEL_LOW:
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
-		u |= 1 << pin;
+		u |= BIT(pin);
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		break;
 	case IRQ_TYPE_EDGE_BOTH: {
@@ -428,10 +482,10 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 		 * set initial polarity based on current input level
 		 */
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
-		if (v & (1 << pin))
-			u |= 1 << pin;		/* falling */
+		if (v & BIT(pin))
+			u |= BIT(pin);		/* falling */
 		else
-			u &= ~(1 << pin);	/* rising */
+			u &= ~BIT(pin);		/* rising */
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		break;
 	}
@@ -461,7 +515,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
 
 		irq = irq_find_mapping(mvchip->domain, i);
 
-		if (!(cause & (1 << i)))
+		if (!(cause & BIT(i)))
 			continue;
 
 		type = irq_get_trigger_type(irq);
@@ -470,7 +524,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
 			u32 polarity;
 
 			polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
-			polarity ^= 1 << i;
+			polarity ^= BIT(i);
 			writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
 		}
 
@@ -480,6 +534,246 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
 	chained_irq_exit(chip, desc);
 }
 
+/*
+ * Functions implementing the pwm_chip methods
+ */
+static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
+{
+	return container_of(chip, struct mvebu_pwm, chip);
+}
+
+static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
+	struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
+	struct gpio_desc *desc;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&mvpwm->lock, flags);
+
+	if (mvpwm->gpiod) {
+		ret = -EBUSY;
+	} else {
+		desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm);
+		if (!desc) {
+			ret = -ENODEV;
+			goto out;
+		}
+
+		ret = gpiod_request(desc, "mvebu-pwm");
+		if (ret)
+			goto out;
+
+		ret = gpiod_direction_output(desc, 0);
+		if (ret) {
+			gpiod_free(desc);
+			goto out;
+		}
+
+		mvpwm->gpiod = desc;
+	}
+out:
+	spin_unlock_irqrestore(&mvpwm->lock, flags);
+	return ret;
+}
+
+static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mvpwm->lock, flags);
+	gpiod_free(mvpwm->gpiod);
+	mvpwm->gpiod = NULL;
+	spin_unlock_irqrestore(&mvpwm->lock, flags);
+}
+
+static void mvebu_pwm_get_state(struct pwm_chip *chip,
+				struct pwm_device *pwm,
+				struct pwm_state *state) {
+
+	struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
+	struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
+	unsigned long long val;
+	unsigned long flags;
+	u32 u;
+
+	spin_lock_irqsave(&mvpwm->lock, flags);
+
+	val = (unsigned long long)
+		readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
+	val *= NSEC_PER_SEC;
+	do_div(val, mvpwm->clk_rate);
+	if (val > UINT_MAX)
+		state->duty_cycle = UINT_MAX;
+	else if (val)
+		state->duty_cycle = val;
+	else
+		state->duty_cycle = 1;
+
+	val = (unsigned long long)
+		readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
+	val *= NSEC_PER_SEC;
+	do_div(val, mvpwm->clk_rate);
+	if (val < state->duty_cycle) {
+		state->period = 1;
+	} else {
+		val -= state->duty_cycle;
+		if (val > UINT_MAX)
+			state->period = UINT_MAX;
+		else if (val)
+			state->period = val;
+		else
+			state->period = 1;
+	}
+
+	u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+	if (u)
+		state->enabled = true;
+	else
+		state->enabled = false;
+
+	spin_unlock_irqrestore(&mvpwm->lock, flags);
+}
+
+static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			   struct pwm_state *state)
+{
+	struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
+	struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
+	unsigned long long val;
+	unsigned long flags;
+	unsigned int on, off;
+
+	val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle;
+	do_div(val, NSEC_PER_SEC);
+	if (val > UINT_MAX)
+		return -EINVAL;
+	if (val)
+		on = val;
+	else
+		on = 1;
+
+	val = (unsigned long long) mvpwm->clk_rate *
+		(state->period - state->duty_cycle);
+	do_div(val, NSEC_PER_SEC);
+	if (val > UINT_MAX)
+		return -EINVAL;
+	if (val)
+		off = val;
+	else
+		off = 1;
+
+	spin_lock_irqsave(&mvpwm->lock, flags);
+
+	writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm));
+	writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm));
+	if (state->enabled)
+		mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1);
+	else
+		mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0);
+
+	spin_unlock_irqrestore(&mvpwm->lock, flags);
+
+	return 0;
+}
+
+static const struct pwm_ops mvebu_pwm_ops = {
+	.request = mvebu_pwm_request,
+	.free = mvebu_pwm_free,
+	.get_state = mvebu_pwm_get_state,
+	.apply = mvebu_pwm_apply,
+	.owner = THIS_MODULE,
+};
+
+static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
+{
+	struct mvebu_pwm *mvpwm = mvchip->mvpwm;
+
+	mvpwm->blink_select =
+		readl_relaxed(mvebu_gpioreg_blink_counter_select(mvchip));
+	mvpwm->blink_on_duration =
+		readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
+	mvpwm->blink_off_duration =
+		readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
+}
+
+static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
+{
+	struct mvebu_pwm *mvpwm = mvchip->mvpwm;
+
+	writel_relaxed(mvpwm->blink_select,
+		       mvebu_gpioreg_blink_counter_select(mvchip));
+	writel_relaxed(mvpwm->blink_on_duration,
+		       mvebu_pwmreg_blink_on_duration(mvpwm));
+	writel_relaxed(mvpwm->blink_off_duration,
+		       mvebu_pwmreg_blink_off_duration(mvpwm));
+}
+
+static int mvebu_pwm_probe(struct platform_device *pdev,
+			   struct mvebu_gpio_chip *mvchip,
+			   int id)
+{
+	struct device *dev = &pdev->dev;
+	struct mvebu_pwm *mvpwm;
+	struct resource *res;
+	u32 set;
+
+	if (!of_device_is_compatible(mvchip->chip.of_node,
+				     "marvell,armada-370-xp-gpio"))
+		return 0;
+
+	if (IS_ERR(mvchip->clk))
+		return PTR_ERR(mvchip->clk);
+
+	/*
+	 * There are only two sets of PWM configuration registers for
+	 * all the GPIO lines on those SoCs which this driver reserves
+	 * for the first two GPIO chips. So if the resource is missing
+	 * we can't treat it as an error.
+	 */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm");
+	if (!res)
+		return 0;
+
+	/*
+	 * Use set A for lines of GPIO chip with id 0, B for GPIO chip
+	 * with id 1. Don't allow further GPIO chips to be used for PWM.
+	 */
+	if (id == 0)
+		set = 0;
+	else if (id == 1)
+		set = U32_MAX;
+	else
+		return -EINVAL;
+	writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip));
+
+	mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
+	if (!mvpwm)
+		return -ENOMEM;
+	mvchip->mvpwm = mvpwm;
+	mvpwm->mvchip = mvchip;
+
+	mvpwm->membase = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mvpwm->membase))
+		return PTR_ERR(mvpwm->membase);
+
+	mvpwm->clk_rate = clk_get_rate(mvchip->clk);
+	if (!mvpwm->clk_rate) {
+		dev_err(dev, "failed to get clock rate\n");
+		return -EINVAL;
+	}
+
+	mvpwm->chip.dev = dev;
+	mvpwm->chip.ops = &mvebu_pwm_ops;
+	mvpwm->chip.npwm = mvchip->chip.ngpio;
+
+	spin_lock_init(&mvpwm->lock);
+
+	return pwmchip_add(&mvpwm->chip);
+}
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/seq_file.h>
 
@@ -507,7 +801,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 		if (!label)
 			continue;
 
-		msk = 1 << i;
+		msk = BIT(i);
 		is_out = !(io_conf & msk);
 
 		seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label);
@@ -550,6 +844,10 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
 		.compatible = "marvell,armadaxp-gpio",
 		.data	    = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
 	},
+	{
+		.compatible = "marvell,armada-370-xp-gpio",
+		.data	    = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
+	},
 	{
 		/* sentinel */
 	},
@@ -596,6 +894,9 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
 		BUG();
 	}
 
+	if (IS_ENABLED(CONFIG_PWM))
+		mvebu_pwm_suspend(mvchip);
+
 	return 0;
 }
 
@@ -639,6 +940,9 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
 		BUG();
 	}
 
+	if (IS_ENABLED(CONFIG_PWM))
+		mvebu_pwm_resume(mvchip);
+
 	return 0;
 }
 
@@ -650,7 +954,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
-	struct clk *clk;
 	unsigned int ngpios;
 	bool have_irqs;
 	int soc_variant;
@@ -684,10 +987,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 		return id;
 	}
 
-	clk = devm_clk_get(&pdev->dev, NULL);
+	mvchip->clk = devm_clk_get(&pdev->dev, NULL);
 	/* Not all SoCs require a clock.*/
-	if (!IS_ERR(clk))
-		clk_prepare_enable(clk);
+	if (!IS_ERR(mvchip->clk))
+		clk_prepare_enable(mvchip->clk);
 
 	mvchip->soc_variant = soc_variant;
 	mvchip->chip.label = dev_name(&pdev->dev);
@@ -712,8 +1015,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(mvchip->membase))
 		return PTR_ERR(mvchip->membase);
 
-	/* The Armada XP has a second range of registers for the
-	 * per-CPU registers */
+	/*
+	 * The Armada XP has a second range of registers for the
+	 * per-CPU registers
+	 */
 	if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
@@ -780,7 +1085,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 		goto err_domain;
 	}
 
-	/* NOTE: The common accessors cannot be used because of the percpu
+	/*
+	 * NOTE: The common accessors cannot be used because of the percpu
 	 * access to the mask registers
 	 */
 	gc = irq_get_domain_generic_chip(mvchip->domain, 0);
@@ -801,7 +1107,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	ct->handler = handle_edge_irq;
 	ct->chip.name = mvchip->chip.label;
 
-	/* Setup the interrupt handlers. Each chip can have up to 4
+	/*
+	 * Setup the interrupt handlers. Each chip can have up to 4
 	 * interrupt handlers, with each handler dealing with 8 GPIO
 	 * pins.
 	 */
@@ -814,6 +1121,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 						 mvchip);
 	}
 
+	/* Armada 370/XP has simple PWM support for GPIO lines */
+	if (IS_ENABLED(CONFIG_PWM))
+		return mvebu_pwm_probe(pdev, mvchip, id);
+
 	return 0;
 
 err_domain:
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index c1a1e00b8cb024f12d6243226fc01de4aa37064a..3abea3f0b307e143848686dd935ee0745a414eec 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -471,7 +471,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 	if (err)
 		goto out_bgio;
 
-	irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
+	irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
 	if (irq_base < 0) {
 		err = irq_base;
 		goto out_bgio;
@@ -481,7 +481,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 					     &irq_domain_simple_ops, NULL);
 	if (!port->domain) {
 		err = -ENODEV;
-		goto out_irqdesc_free;
+		goto out_bgio;
 	}
 
 	/* gpio-mxc can be a generic irq chip */
@@ -495,8 +495,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 
 out_irqdomain_remove:
 	irq_domain_remove(port->domain);
-out_irqdesc_free:
-	irq_free_descs(irq_base, 32);
 out_bgio:
 	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
 	return err;
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index 2292742eac8f5441642469f8fa05e04ca0979afb..6ae583f36733a1d94efeb2ee846f0d436d9487fd 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -328,7 +328,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 	/* clear address has to be used to clear IRQSTAT bits */
 	writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
 
-	irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
+	irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
 	if (irq_base < 0) {
 		err = irq_base;
 		goto out_iounmap;
@@ -338,7 +338,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 					     &irq_domain_simple_ops, NULL);
 	if (!port->domain) {
 		err = -ENODEV;
-		goto out_irqdesc_free;
+		goto out_iounmap;
 	}
 
 	/* gpio-mxs can be a generic irq chip */
@@ -370,8 +370,6 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 
 out_irqdomain_remove:
 	irq_domain_remove(port->domain);
-out_irqdesc_free:
-	irq_free_descs(irq_base, 32);
 out_iounmap:
 	iounmap(port->base);
 	return err;
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index efc85a279d5473b18079e43d4a5f51ef15f1d328..f8c550de6c72b5549b00ce49fb6290d26368498e 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -208,9 +208,11 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
  * OMAP's debounce time is in 31us steps
  *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
  * so we need to convert and round up to the closest unit.
+ *
+ * Return: 0 on success, negative error otherwise.
  */
-static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
-				    unsigned debounce)
+static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
+				   unsigned debounce)
 {
 	void __iomem		*reg;
 	u32			val;
@@ -218,11 +220,12 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
 	bool			enable = !!debounce;
 
 	if (!bank->dbck_flag)
-		return;
+		return -ENOTSUPP;
 
 	if (enable) {
 		debounce = DIV_ROUND_UP(debounce, 31) - 1;
-		debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
+		if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce)
+			return -EINVAL;
 	}
 
 	l = BIT(offset);
@@ -255,6 +258,8 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
 		bank->context.debounce = debounce;
 		bank->context.debounce_en = val;
 	}
+
+	return 0;
 }
 
 /**
@@ -964,14 +969,20 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
+	int ret;
 
 	bank = gpiochip_get_data(chip);
 
 	raw_spin_lock_irqsave(&bank->lock, flags);
-	omap2_set_gpio_debounce(bank, offset, debounce);
+	ret = omap2_set_gpio_debounce(bank, offset, debounce);
 	raw_spin_unlock_irqrestore(&bank->lock, flags);
 
-	return 0;
+	if (ret)
+		dev_info(chip->parent,
+			 "Could not set line %u debounce to %u microseconds (%d)",
+			 offset, debounce, ret);
+
+	return ret;
 }
 
 static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
@@ -1085,7 +1096,8 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
 	 * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
 	 * irq_alloc_descs() since a base IRQ offset will no longer be needed.
 	 */
-	irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
+	irq_base = devm_irq_alloc_descs(bank->chip.parent,
+					-1, 0, bank->width, 0);
 	if (irq_base < 0) {
 		dev_err(bank->chip.parent, "Couldn't allocate IRQ numbers\n");
 		return -ENODEV;
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index d44232aadb6c2224301f45aa665af998e4aa9a4b..4c9e21300a262170499a4e009af3638b79536579 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -11,18 +11,19 @@
  *  the Free Software Foundation; version 2 of the License.
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
+#include <linux/acpi.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
-#include <linux/interrupt.h>
 #include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
 #include <linux/platform_data/pca953x.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+
 #include <asm/unaligned.h>
-#include <linux/of_platform.h>
-#include <linux/acpi.h>
-#include <linux/regulator/consumer.h>
 
 #define PCA953X_INPUT		0
 #define PCA953X_OUTPUT		1
@@ -81,6 +82,7 @@ static const struct i2c_device_id pca953x_id[] = {
 	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
 	{ "tca9539", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "tca9554", 8  | PCA953X_TYPE | PCA_INT, },
 	{ "xra1202", 8  | PCA953X_TYPE },
 	{ }
 };
@@ -363,6 +365,21 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 	mutex_unlock(&chip->i2c_lock);
 }
 
+static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
+{
+	struct pca953x_chip *chip = gpiochip_get_data(gc);
+	u32 reg_val;
+	int ret;
+
+	mutex_lock(&chip->i2c_lock);
+	ret = pca953x_read_single(chip, chip->regs->direction, &reg_val, off);
+	mutex_unlock(&chip->i2c_lock);
+	if (ret < 0)
+		return ret;
+
+	return !!(reg_val & (1u << (off % BANK_SZ)));
+}
+
 static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
 				      unsigned long *mask, unsigned long *bits)
 {
@@ -408,6 +425,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
 	gc->direction_output = pca953x_gpio_direction_output;
 	gc->get = pca953x_gpio_get_value;
 	gc->set = pca953x_gpio_set_value;
+	gc->get_direction = pca953x_gpio_get_direction;
 	gc->set_multiple = pca953x_gpio_set_multiple;
 	gc->can_sleep = true;
 
@@ -760,7 +778,13 @@ static int pca953x_probe(struct i2c_client *client,
 		chip->gpio_start = -1;
 		irq_base = 0;
 
-		/* See if we need to de-assert a reset pin */
+		/*
+		 * See if we need to de-assert a reset pin.
+		 *
+		 * There is no known ACPI-enabled platforms that are
+		 * using "reset" GPIO. Otherwise any of those platform
+		 * must use _DSD method with corresponding property.
+		 */
 		reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
 						     GPIOD_OUT_LOW);
 		if (IS_ERR(reset_gpio))
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 895af42a4513581ae1b9f1059384ce866777f9f7..8ddf9302ce3b079adcd727c09ad56f9ce4b60883 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -46,7 +46,6 @@ static const struct i2c_device_id pcf857x_id[] = {
 	{ "pca9675", 16 },
 	{ "max7328", 8 },
 	{ "max7329", 8 },
-	{ "tca9554", 8 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcf857x_id);
@@ -66,7 +65,6 @@ static const struct of_device_id pcf857x_of_table[] = {
 	{ .compatible = "nxp,pca9675" },
 	{ .compatible = "maxim,max7328" },
 	{ .compatible = "maxim,max7329" },
-	{ .compatible = "ti,tca9554" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pcf857x_of_table);
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 7c7135da5d4a547fc21993781690631315285cbc..71bc6da1133727eaa59d8d0c52a3c84d02eea6ff 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -403,7 +403,8 @@ static int pch_gpio_probe(struct pci_dev *pdev,
 		goto err_gpiochip_add;
 	}
 
-	irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE);
+	irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0,
+					gpio_pins[chip->ioh], NUMA_NO_NODE);
 	if (irq_base < 0) {
 		dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
 		chip->irq_base = -1;
@@ -416,8 +417,8 @@ static int pch_gpio_probe(struct pci_dev *pdev,
 	iowrite32(msk, &chip->reg->imask);
 	iowrite32(msk, &chip->reg->ien);
 
-	ret = request_irq(pdev->irq, pch_gpio_handler,
-			  IRQF_SHARED, KBUILD_MODNAME, chip);
+	ret = devm_request_irq(&pdev->dev, pdev->irq, pch_gpio_handler,
+			       IRQF_SHARED, KBUILD_MODNAME, chip);
 	if (ret != 0) {
 		dev_err(&pdev->dev,
 			"%s request_irq failed\n", __func__);
@@ -430,7 +431,6 @@ static int pch_gpio_probe(struct pci_dev *pdev,
 	return 0;
 
 err_request_irq:
-	irq_free_descs(irq_base, gpio_pins[chip->ioh]);
 	gpiochip_remove(&chip->gpio);
 
 err_gpiochip_add:
@@ -452,12 +452,6 @@ static void pch_gpio_remove(struct pci_dev *pdev)
 {
 	struct pch_gpio *chip = pci_get_drvdata(pdev);
 
-	if (chip->irq_base != -1) {
-		free_irq(pdev->irq, chip);
-
-		irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
-	}
-
 	gpiochip_remove(&chip->gpio);
 	pci_iounmap(pdev, chip->base);
 	pci_release_regions(pdev);
diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c
index 269ab628634b2b35e2fbbf8a475a04c1c6c30d5c..7de4f6a2cb494a47f81517fc46ac9fdbcc997ab2 100644
--- a/drivers/gpio/gpio-pci-idio-16.c
+++ b/drivers/gpio/gpio-pci-idio-16.c
@@ -59,7 +59,7 @@ struct idio_16_gpio_reg {
  */
 struct idio_16_gpio {
 	struct gpio_chip chip;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	struct idio_16_gpio_reg __iomem *reg;
 	unsigned long irq_mask;
 };
@@ -121,7 +121,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	} else
 		base = &idio16gpio->reg->out0_7;
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 	if (value)
 		out_state = ioread8(base) | mask;
@@ -130,7 +130,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
 
 	iowrite8(out_state, base);
 
-	spin_unlock_irqrestore(&idio16gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 }
 
 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
@@ -140,7 +140,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 	unsigned long flags;
 	unsigned int out_state;
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 	/* process output lines 0-7 */
 	if (*mask & 0xFF) {
@@ -160,7 +160,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 		iowrite8(out_state, &idio16gpio->reg->out8_15);
 	}
 
-	spin_unlock_irqrestore(&idio16gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 }
 
 static void idio_16_irq_ack(struct irq_data *data)
@@ -177,11 +177,11 @@ static void idio_16_irq_mask(struct irq_data *data)
 	idio16gpio->irq_mask &= ~mask;
 
 	if (!idio16gpio->irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 		iowrite8(0, &idio16gpio->reg->irq_ctl);
 
-		spin_unlock_irqrestore(&idio16gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 	}
 }
 
@@ -196,11 +196,11 @@ static void idio_16_irq_unmask(struct irq_data *data)
 	idio16gpio->irq_mask |= mask;
 
 	if (!prev_irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 		ioread8(&idio16gpio->reg->irq_ctl);
 
-		spin_unlock_irqrestore(&idio16gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
 	}
 }
 
@@ -229,11 +229,11 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 	struct gpio_chip *const chip = &idio16gpio->chip;
 	int gpio;
 
-	spin_lock(&idio16gpio->lock);
+	raw_spin_lock(&idio16gpio->lock);
 
 	irq_status = ioread8(&idio16gpio->reg->irq_status);
 
-	spin_unlock(&idio16gpio->lock);
+	raw_spin_unlock(&idio16gpio->lock);
 
 	/* Make sure our device generated IRQ */
 	if (!(irq_status & 0x3) || !(irq_status & 0x4))
@@ -242,12 +242,12 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
 		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
 
-	spin_lock(&idio16gpio->lock);
+	raw_spin_lock(&idio16gpio->lock);
 
 	/* Clear interrupt */
 	iowrite8(0, &idio16gpio->reg->in0_7);
 
-	spin_unlock(&idio16gpio->lock);
+	raw_spin_unlock(&idio16gpio->lock);
 
 	return IRQ_HANDLED;
 }
@@ -302,7 +302,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	idio16gpio->chip.set = idio_16_gpio_set;
 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 
-	spin_lock_init(&idio16gpio->lock);
+	raw_spin_lock_init(&idio16gpio->lock);
 
 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 	if (err) {
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 0a6bfd2b06e5d869cf220ffdeb3587c93afdac03..3d3d6b6645a7a5a5cf16c1d2647864939c080cb8 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -50,7 +50,7 @@ struct pl061_context_save_regs {
 #endif
 
 struct pl061 {
-	spinlock_t		lock;
+	raw_spinlock_t		lock;
 
 	void __iomem		*base;
 	struct gpio_chip	gc;
@@ -74,11 +74,11 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
 	unsigned long flags;
 	unsigned char gpiodir;
 
-	spin_lock_irqsave(&pl061->lock, flags);
+	raw_spin_lock_irqsave(&pl061->lock, flags);
 	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir &= ~(BIT(offset));
 	writeb(gpiodir, pl061->base + GPIODIR);
-	spin_unlock_irqrestore(&pl061->lock, flags);
+	raw_spin_unlock_irqrestore(&pl061->lock, flags);
 
 	return 0;
 }
@@ -90,7 +90,7 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
 	unsigned long flags;
 	unsigned char gpiodir;
 
-	spin_lock_irqsave(&pl061->lock, flags);
+	raw_spin_lock_irqsave(&pl061->lock, flags);
 	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
 	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir |= BIT(offset);
@@ -101,7 +101,7 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
 	 * a gpio pin before configuring it in OUT mode.
 	 */
 	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
-	spin_unlock_irqrestore(&pl061->lock, flags);
+	raw_spin_unlock_irqrestore(&pl061->lock, flags);
 
 	return 0;
 }
@@ -143,7 +143,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 	}
 
 
-	spin_lock_irqsave(&pl061->lock, flags);
+	raw_spin_lock_irqsave(&pl061->lock, flags);
 
 	gpioiev = readb(pl061->base + GPIOIEV);
 	gpiois = readb(pl061->base + GPIOIS);
@@ -203,7 +203,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 	writeb(gpioibe, pl061->base + GPIOIBE);
 	writeb(gpioiev, pl061->base + GPIOIEV);
 
-	spin_unlock_irqrestore(&pl061->lock, flags);
+	raw_spin_unlock_irqrestore(&pl061->lock, flags);
 
 	return 0;
 }
@@ -235,10 +235,10 @@ static void pl061_irq_mask(struct irq_data *d)
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 	u8 gpioie;
 
-	spin_lock(&pl061->lock);
+	raw_spin_lock(&pl061->lock);
 	gpioie = readb(pl061->base + GPIOIE) & ~mask;
 	writeb(gpioie, pl061->base + GPIOIE);
-	spin_unlock(&pl061->lock);
+	raw_spin_unlock(&pl061->lock);
 }
 
 static void pl061_irq_unmask(struct irq_data *d)
@@ -248,10 +248,10 @@ static void pl061_irq_unmask(struct irq_data *d)
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 	u8 gpioie;
 
-	spin_lock(&pl061->lock);
+	raw_spin_lock(&pl061->lock);
 	gpioie = readb(pl061->base + GPIOIE) | mask;
 	writeb(gpioie, pl061->base + GPIOIE);
-	spin_unlock(&pl061->lock);
+	raw_spin_unlock(&pl061->lock);
 }
 
 /**
@@ -268,9 +268,9 @@ static void pl061_irq_ack(struct irq_data *d)
 	struct pl061 *pl061 = gpiochip_get_data(gc);
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 
-	spin_lock(&pl061->lock);
+	raw_spin_lock(&pl061->lock);
 	writeb(mask, pl061->base + GPIOIC);
-	spin_unlock(&pl061->lock);
+	raw_spin_unlock(&pl061->lock);
 }
 
 static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)
@@ -304,7 +304,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 	if (IS_ERR(pl061->base))
 		return PTR_ERR(pl061->base);
 
-	spin_lock_init(&pl061->lock);
+	raw_spin_lock_init(&pl061->lock);
 	if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
 		pl061->gc.request = gpiochip_generic_request;
 		pl061->gc.free = gpiochip_generic_free;
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 76ac906b4d78d262ab5473771e377c9c244b76b3..832f3e46ba9fa2d99e37d2152cbedfa3bfdb3bcc 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -601,7 +601,7 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev,
 	nr_gpios = gpio_id->gpio_nums;
 	pxa_last_gpio = nr_gpios - 1;
 
-	irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0);
+	irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, nr_gpios, 0);
 	if (irq_base < 0) {
 		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
 		return irq_base;
diff --git a/drivers/gpio/gpio-reg.c b/drivers/gpio/gpio-reg.c
new file mode 100644
index 0000000000000000000000000000000000000000..e85903eddc68ecd5930df5ded45efbc398aa57ca
--- /dev/null
+++ b/drivers/gpio/gpio-reg.c
@@ -0,0 +1,185 @@
+/*
+ * gpio-reg: single register individually fixed-direction GPIOs
+ *
+ * Copyright (C) 2016 Russell King
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ */
+#include <linux/gpio/driver.h>
+#include <linux/gpio/gpio-reg.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct gpio_reg {
+	struct gpio_chip gc;
+	spinlock_t lock;
+	u32 direction;
+	u32 out;
+	void __iomem *reg;
+	struct irq_domain *irqdomain;
+	const int *irqs;
+};
+
+#define to_gpio_reg(x) container_of(x, struct gpio_reg, gc)
+
+static int gpio_reg_get_direction(struct gpio_chip *gc, unsigned offset)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+
+	return r->direction & BIT(offset) ? 1 : 0;
+}
+
+static int gpio_reg_direction_output(struct gpio_chip *gc, unsigned offset,
+	int value)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+
+	if (r->direction & BIT(offset))
+		return -ENOTSUPP;
+
+	gc->set(gc, offset, value);
+	return 0;
+}
+
+static int gpio_reg_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+
+	return r->direction & BIT(offset) ? 0 : -ENOTSUPP;
+}
+
+static void gpio_reg_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+	unsigned long flags;
+	u32 val, mask = BIT(offset);
+
+	spin_lock_irqsave(&r->lock, flags);
+	val = r->out;
+	if (value)
+		val |= mask;
+	else
+		val &= ~mask;
+	r->out = val;
+	writel_relaxed(val, r->reg);
+	spin_unlock_irqrestore(&r->lock, flags);
+}
+
+static int gpio_reg_get(struct gpio_chip *gc, unsigned offset)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+	u32 val, mask = BIT(offset);
+
+	if (r->direction & mask) {
+		/*
+		 * double-read the value, some registers latch after the
+		 * first read.
+		 */
+		readl_relaxed(r->reg);
+		val = readl_relaxed(r->reg);
+	} else {
+		val = r->out;
+	}
+	return !!(val & mask);
+}
+
+static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask,
+	unsigned long *bits)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&r->lock, flags);
+	r->out = (r->out & ~*mask) | (*bits & *mask);
+	writel_relaxed(r->out, r->reg);
+	spin_unlock_irqrestore(&r->lock, flags);
+}
+
+static int gpio_reg_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+	int irq = r->irqs[offset];
+
+	if (irq >= 0 && r->irqdomain)
+		irq = irq_find_mapping(r->irqdomain, irq);
+
+	return irq;
+}
+
+/**
+ * gpio_reg_init - add a fixed in/out register as gpio
+ * @dev: optional struct device associated with this register
+ * @base: start gpio number, or -1 to allocate
+ * @num: number of GPIOs, maximum 32
+ * @label: GPIO chip label
+ * @direction: bitmask of fixed direction, one per GPIO signal, 1 = in
+ * @def_out: initial GPIO output value
+ * @names: array of %num strings describing each GPIO signal or %NULL
+ * @irqdom: irq domain or %NULL
+ * @irqs: array of %num ints describing the interrupt mapping for each
+ *        GPIO signal, or %NULL.  If @irqdom is %NULL, then this
+ *        describes the Linux interrupt number, otherwise it describes
+ *        the hardware interrupt number in the specified irq domain.
+ *
+ * Add a single-register GPIO device containing up to 32 GPIO signals,
+ * where each GPIO has a fixed input or output configuration.  Only
+ * input GPIOs are assumed to be readable from the register, and only
+ * then after a double-read.  Output values are assumed not to be
+ * readable.
+ */
+struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg,
+	int base, int num, const char *label, u32 direction, u32 def_out,
+	const char *const *names, struct irq_domain *irqdom, const int *irqs)
+{
+	struct gpio_reg *r;
+	int ret;
+
+	if (dev)
+		r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL);
+	else
+		r = kzalloc(sizeof(*r), GFP_KERNEL);
+
+	if (!r)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock_init(&r->lock);
+
+	r->gc.label = label;
+	r->gc.get_direction = gpio_reg_get_direction;
+	r->gc.direction_input = gpio_reg_direction_input;
+	r->gc.direction_output = gpio_reg_direction_output;
+	r->gc.set = gpio_reg_set;
+	r->gc.get = gpio_reg_get;
+	r->gc.set_multiple = gpio_reg_set_multiple;
+	if (irqs)
+		r->gc.to_irq = gpio_reg_to_irq;
+	r->gc.base = base;
+	r->gc.ngpio = num;
+	r->gc.names = names;
+	r->direction = direction;
+	r->out = def_out;
+	r->reg = reg;
+	r->irqs = irqs;
+
+	if (dev)
+		ret = devm_gpiochip_add_data(dev, &r->gc, r);
+	else
+		ret = gpiochip_add_data(&r->gc, r);
+
+	return ret ? ERR_PTR(ret) : &r->gc;
+}
+
+int gpio_reg_resume(struct gpio_chip *gc)
+{
+	struct gpio_reg *r = to_gpio_reg(gc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&r->lock, flags);
+	writel_relaxed(r->out, r->reg);
+	spin_unlock_irqrestore(&r->lock, flags);
+
+	return 0;
+}
diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c
index 8d8ee0ebf14c03dc96b95b8d98c2f2d2c73352c9..249f433aa62df60de4c60a051fc205ec583875a4 100644
--- a/drivers/gpio/gpio-sa1100.c
+++ b/drivers/gpio/gpio-sa1100.c
@@ -12,57 +12,97 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/syscore_ops.h>
+#include <soc/sa1100/pwer.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
+struct sa1100_gpio_chip {
+	struct gpio_chip chip;
+	void __iomem *membase;
+	int irqbase;
+	u32 irqmask;
+	u32 irqrising;
+	u32 irqfalling;
+	u32 irqwake;
+};
+
+#define sa1100_gpio_chip(x) container_of(x, struct sa1100_gpio_chip, chip)
+
+enum {
+	R_GPLR = 0x00,
+	R_GPDR = 0x04,
+	R_GPSR = 0x08,
+	R_GPCR = 0x0c,
+	R_GRER = 0x10,
+	R_GFER = 0x14,
+	R_GEDR = 0x18,
+	R_GAFR = 0x1c,
+};
+
 static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	return !!(GPLR & GPIO_GPIO(offset));
+	return readl_relaxed(sa1100_gpio_chip(chip)->membase + R_GPLR) &
+		BIT(offset);
 }
 
 static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	if (value)
-		GPSR = GPIO_GPIO(offset);
-	else
-		GPCR = GPIO_GPIO(offset);
+	int reg = value ? R_GPSR : R_GPCR;
+
+	writel_relaxed(BIT(offset), sa1100_gpio_chip(chip)->membase + reg);
+}
+
+static int sa1100_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
+
+	return !(readl_relaxed(gpdr) & BIT(offset));
 }
 
 static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
 {
+	void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	GPDR &= ~GPIO_GPIO(offset);
+	writel_relaxed(readl_relaxed(gpdr) & ~BIT(offset), gpdr);
 	local_irq_restore(flags);
+
 	return 0;
 }
 
 static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 {
+	void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
 	unsigned long flags;
 
 	local_irq_save(flags);
 	sa1100_gpio_set(chip, offset, value);
-	GPDR |= GPIO_GPIO(offset);
+	writel_relaxed(readl_relaxed(gpdr) | BIT(offset), gpdr);
 	local_irq_restore(flags);
+
 	return 0;
 }
 
 static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	return IRQ_GPIO0 + offset;
+	return sa1100_gpio_chip(chip)->irqbase + offset;
 }
 
-static struct gpio_chip sa1100_gpio_chip = {
-	.label			= "gpio",
-	.direction_input	= sa1100_direction_input,
-	.direction_output	= sa1100_direction_output,
-	.set			= sa1100_gpio_set,
-	.get			= sa1100_gpio_get,
-	.to_irq			= sa1100_to_irq,
-	.base			= 0,
-	.ngpio			= GPIO_MAX + 1,
+static struct sa1100_gpio_chip sa1100_gpio_chip = {
+	.chip = {
+		.label			= "gpio",
+		.get_direction		= sa1100_get_direction,
+		.direction_input	= sa1100_direction_input,
+		.direction_output	= sa1100_direction_output,
+		.set			= sa1100_gpio_set,
+		.get			= sa1100_gpio_get,
+		.to_irq			= sa1100_to_irq,
+		.base			= 0,
+		.ngpio			= GPIO_MAX + 1,
+	},
+	.membase = (void *)&GPLR,
+	.irqbase = IRQ_GPIO0,
 };
 
 /*
@@ -70,33 +110,39 @@ static struct gpio_chip sa1100_gpio_chip = {
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
  * Use this instead of directly setting GRER/GFER.
  */
-static int GPIO_IRQ_rising_edge;
-static int GPIO_IRQ_falling_edge;
-static int GPIO_IRQ_mask;
+static void sa1100_update_edge_regs(struct sa1100_gpio_chip *sgc)
+{
+	void *base = sgc->membase;
+	u32 grer, gfer;
+
+	grer = sgc->irqrising & sgc->irqmask;
+	gfer = sgc->irqfalling & sgc->irqmask;
+
+	writel_relaxed(grer, base + R_GRER);
+	writel_relaxed(gfer, base + R_GFER);
+}
 
 static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
 {
-	unsigned int mask;
-
-	mask = BIT(d->hwirq);
+	struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
+	unsigned int mask = BIT(d->hwirq);
 
 	if (type == IRQ_TYPE_PROBE) {
-		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
+		if ((sgc->irqrising | sgc->irqfalling) & mask)
 			return 0;
 		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
 	}
 
 	if (type & IRQ_TYPE_EDGE_RISING)
-		GPIO_IRQ_rising_edge |= mask;
+		sgc->irqrising |= mask;
 	else
-		GPIO_IRQ_rising_edge &= ~mask;
+		sgc->irqrising &= ~mask;
 	if (type & IRQ_TYPE_EDGE_FALLING)
-		GPIO_IRQ_falling_edge |= mask;
+		sgc->irqfalling |= mask;
 	else
-		GPIO_IRQ_falling_edge &= ~mask;
+		sgc->irqfalling &= ~mask;
 
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+	sa1100_update_edge_regs(sgc);
 
 	return 0;
 }
@@ -106,36 +152,42 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
  */
 static void sa1100_gpio_ack(struct irq_data *d)
 {
-	GEDR = BIT(d->hwirq);
+	struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
+
+	writel_relaxed(BIT(d->hwirq), sgc->membase + R_GEDR);
 }
 
 static void sa1100_gpio_mask(struct irq_data *d)
 {
+	struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
 	unsigned int mask = BIT(d->hwirq);
 
-	GPIO_IRQ_mask &= ~mask;
+	sgc->irqmask &= ~mask;
 
-	GRER &= ~mask;
-	GFER &= ~mask;
+	sa1100_update_edge_regs(sgc);
 }
 
 static void sa1100_gpio_unmask(struct irq_data *d)
 {
+	struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
 	unsigned int mask = BIT(d->hwirq);
 
-	GPIO_IRQ_mask |= mask;
+	sgc->irqmask |= mask;
 
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+	sa1100_update_edge_regs(sgc);
 }
 
 static int sa1100_gpio_wake(struct irq_data *d, unsigned int on)
 {
-	if (on)
-		PWER |= BIT(d->hwirq);
-	else
-		PWER &= ~BIT(d->hwirq);
-	return 0;
+	struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d);
+	int ret = sa11x0_gpio_set_wake(d->hwirq, on);
+	if (!ret) {
+		if (on)
+			sgc->irqwake |= BIT(d->hwirq);
+		else
+			sgc->irqwake &= ~BIT(d->hwirq);
+	}
+	return ret;
 }
 
 /*
@@ -153,8 +205,10 @@ static struct irq_chip sa1100_gpio_irq_chip = {
 static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
 		unsigned int irq, irq_hw_number_t hwirq)
 {
-	irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip,
-				 handle_edge_irq);
+	struct sa1100_gpio_chip *sgc = d->host_data;
+
+	irq_set_chip_data(irq, sgc);
+	irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, handle_edge_irq);
 	irq_set_probe(irq);
 
 	return 0;
@@ -174,17 +228,19 @@ static struct irq_domain *sa1100_gpio_irqdomain;
  */
 static void sa1100_gpio_handler(struct irq_desc *desc)
 {
+	struct sa1100_gpio_chip *sgc = irq_desc_get_handler_data(desc);
 	unsigned int irq, mask;
+	void __iomem *gedr = sgc->membase + R_GEDR;
 
-	mask = GEDR;
+	mask = readl_relaxed(gedr);
 	do {
 		/*
 		 * clear down all currently active IRQ sources.
 		 * We will be processing them all.
 		 */
-		GEDR = mask;
+		writel_relaxed(mask, gedr);
 
-		irq = IRQ_GPIO0;
+		irq = sgc->irqbase;
 		do {
 			if (mask & 1)
 				generic_handle_irq(irq);
@@ -192,30 +248,32 @@ static void sa1100_gpio_handler(struct irq_desc *desc)
 			irq++;
 		} while (mask);
 
-		mask = GEDR;
+		mask = readl_relaxed(gedr);
 	} while (mask);
 }
 
 static int sa1100_gpio_suspend(void)
 {
+	struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip;
+
 	/*
 	 * Set the appropriate edges for wakeup.
 	 */
-	GRER = PWER & GPIO_IRQ_rising_edge;
-	GFER = PWER & GPIO_IRQ_falling_edge;
+	writel_relaxed(sgc->irqwake & sgc->irqrising, sgc->membase + R_GRER);
+	writel_relaxed(sgc->irqwake & sgc->irqfalling, sgc->membase + R_GFER);
 
 	/*
 	 * Clear any pending GPIO interrupts.
 	 */
-	GEDR = GEDR;
+	writel_relaxed(readl_relaxed(sgc->membase + R_GEDR),
+		       sgc->membase + R_GEDR);
 
 	return 0;
 }
 
 static void sa1100_gpio_resume(void)
 {
-	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
-	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+	sa1100_update_edge_regs(&sa1100_gpio_chip);
 }
 
 static struct syscore_ops sa1100_gpio_syscore_ops = {
@@ -231,36 +289,40 @@ static int __init sa1100_gpio_init_devicefs(void)
 
 device_initcall(sa1100_gpio_init_devicefs);
 
+static const int sa1100_gpio_irqs[] __initconst = {
+	/* Install handlers for GPIO 0-10 edge detect interrupts */
+	IRQ_GPIO0_SC,
+	IRQ_GPIO1_SC,
+	IRQ_GPIO2_SC,
+	IRQ_GPIO3_SC,
+	IRQ_GPIO4_SC,
+	IRQ_GPIO5_SC,
+	IRQ_GPIO6_SC,
+	IRQ_GPIO7_SC,
+	IRQ_GPIO8_SC,
+	IRQ_GPIO9_SC,
+	IRQ_GPIO10_SC,
+	/* Install handler for GPIO 11-27 edge detect interrupts */
+	IRQ_GPIO11_27,
+};
+
 void __init sa1100_init_gpio(void)
 {
+	struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip;
+	int i;
+
 	/* clear all GPIO edge detects */
-	GFER = 0;
-	GRER = 0;
-	GEDR = -1;
+	writel_relaxed(0, sgc->membase + R_GFER);
+	writel_relaxed(0, sgc->membase + R_GRER);
+	writel_relaxed(-1, sgc->membase + R_GEDR);
 
-	gpiochip_add_data(&sa1100_gpio_chip, NULL);
+	gpiochip_add_data(&sa1100_gpio_chip.chip, NULL);
 
 	sa1100_gpio_irqdomain = irq_domain_add_simple(NULL,
 			28, IRQ_GPIO0,
-			&sa1100_gpio_irqdomain_ops, NULL);
-
-	/*
-	 * Install handlers for GPIO 0-10 edge detect interrupts
-	 */
-	irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler);
-	irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler);
-	/*
-	 * Install handler for GPIO 11-27 edge detect interrupts
-	 */
-	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler);
+			&sa1100_gpio_irqdomain_ops, sgc);
 
+	for (i = 0; i < ARRAY_SIZE(sa1100_gpio_irqs); i++)
+		irq_set_chained_handler_and_data(sa1100_gpio_irqs[i],
+						 sa1100_gpio_handler, sgc);
 }
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 7da9e6c4546a01e4c28e3ecbff3e0bbc4e6a3717..f60da83349ef7145ac0fe113d1a6fee233428833 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -135,7 +135,8 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
 	struct irq_chip_type *ct;
 	int ret;
 
-	sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1);
+	sd->irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0,
+					    SDV_NUM_PUB_GPIOS, -1);
 	if (sd->irq_base < 0)
 		return sd->irq_base;
 
@@ -143,10 +144,11 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
 	writel(0, sd->gpio_pub_base + GPIO_INT);
 	writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR);
 
-	ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED,
-			"sdv_gpio", sd);
+	ret = devm_request_irq(&pdev->dev, pdev->irq,
+			       sdv_gpio_pub_irq_handler, IRQF_SHARED,
+			       "sdv_gpio", sd);
 	if (ret)
-		goto out_free_desc;
+		return ret;
 
 	/*
 	 * This gpio irq controller latches level irqs. Testing shows that if
@@ -155,10 +157,8 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
 	 */
 	sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base,
 			sd->gpio_pub_base, handle_fasteoi_irq);
-	if (!sd->gc) {
-		ret = -ENOMEM;
-		goto out_free_irq;
-	}
+	if (!sd->gc)
+		return -ENOMEM;
 
 	sd->gc->private = sd;
 	ct = sd->gc->chip_types;
@@ -176,16 +176,10 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
 
 	sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS,
 				sd->irq_base, 0, &irq_domain_sdv_ops, sd);
-	if (!sd->id) {
-		ret = -ENODEV;
-		goto out_free_irq;
-	}
+	if (!sd->id)
+		return -ENODEV;
+
 	return 0;
-out_free_irq:
-	free_irq(pdev->irq, sd);
-out_free_desc:
-	irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
-	return ret;
 }
 
 static int sdv_gpio_probe(struct pci_dev *pdev,
diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c
index 853ca23cad889e0040d9df57fff4807ec5197cd9..39df0620fa38d1d45a006659f7ddf1c5fdec1e04 100644
--- a/drivers/gpio/gpio-sta2x11.c
+++ b/drivers/gpio/gpio-sta2x11.c
@@ -392,7 +392,8 @@ static int gsta_probe(struct platform_device *dev)
 			gsta_set_config(chip, i, gpio_pdata->pinconfig[i]);
 
 	/* 384 was used in previous code: be compatible for other drivers */
-	err = irq_alloc_descs(-1, 384, GSTA_NR_GPIO, NUMA_NO_NODE);
+	err = devm_irq_alloc_descs(&dev->dev, -1, 384,
+				   GSTA_NR_GPIO, NUMA_NO_NODE);
 	if (err < 0) {
 		dev_warn(&dev->dev, "sta2x11 gpio: Can't get irq base (%i)\n",
 			 -err);
@@ -401,29 +402,23 @@ static int gsta_probe(struct platform_device *dev)
 	chip->irq_base = err;
 	gsta_alloc_irq_chip(chip);
 
-	err = request_irq(pdev->irq, gsta_gpio_handler,
-			     IRQF_SHARED, KBUILD_MODNAME, chip);
+	err = devm_request_irq(&dev->dev, pdev->irq, gsta_gpio_handler,
+			       IRQF_SHARED, KBUILD_MODNAME, chip);
 	if (err < 0) {
 		dev_err(&dev->dev, "sta2x11 gpio: Can't request irq (%i)\n",
 			-err);
-		goto err_free_descs;
+		return err;
 	}
 
 	err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip);
 	if (err < 0) {
 		dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n",
 			-err);
-		goto err_free_irq;
+		return err;
 	}
 
 	platform_set_drvdata(dev, chip);
 	return 0;
-
-err_free_irq:
-	free_irq(pdev->irq, chip);
-err_free_descs:
-	irq_free_descs(chip->irq_base, GSTA_NR_GPIO);
-	return err;
 }
 
 static struct platform_driver sta2x11_gpio_platform_driver = {
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index dfcfbba74416016c6bc4a936b4072dc4cd9bec00..24f388ed46d4c42781bc2eb2eb0a7e6335a772e9 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -485,7 +485,8 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
 		goto no_irqs;
 	}
 
-	irq_base = irq_alloc_descs(-1, 0, TWL4030_GPIO_MAX, 0);
+	irq_base = devm_irq_alloc_descs(&pdev->dev, -1,
+					0, TWL4030_GPIO_MAX, 0);
 	if (irq_base < 0) {
 		dev_err(&pdev->dev, "Failed to alloc irq_descs\n");
 		return irq_base;
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
index 97613de5304e27fc0ee89d6f63c26bbfcb19d71e..7b1bc20be209a3ca6ba37a20e7be137195eaddc5 100644
--- a/drivers/gpio/gpio-wcove.c
+++ b/drivers/gpio/gpio-wcove.c
@@ -51,6 +51,8 @@
 #define GROUP1_NR_IRQS		6
 #define IRQ_MASK_BASE		0x4e19
 #define IRQ_STATUS_BASE		0x4e0b
+#define GPIO_IRQ0_MASK		GENMASK(6, 0)
+#define GPIO_IRQ1_MASK		GENMASK(5, 0)
 #define UPDATE_IRQ_TYPE		BIT(0)
 #define UPDATE_IRQ_MASK		BIT(1)
 
@@ -309,7 +311,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
 		return IRQ_NONE;
 	}
 
-	pending = p[0] | (p[1] << 8);
+	pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
 	if (!pending)
 		return IRQ_NONE;
 
@@ -317,7 +319,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
 	while (pending) {
 		/* One iteration is for all pending bits */
 		for_each_set_bit(gpio, (const unsigned long *)&pending,
-						 GROUP0_NR_IRQS) {
+						 WCOVE_GPIO_NUM) {
 			offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0;
 			mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) :
 								BIT(gpio);
@@ -333,7 +335,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
 			break;
 		}
 
-		pending = p[0] | (p[1] << 8);
+		pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
 	}
 
 	return IRQ_HANDLED;
diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c
index 901b5ccb032ddd53eb7e20b04044a68eb721ce9d..87d63695dfcf796d73c04c795ab2eaf17d2acb74 100644
--- a/drivers/gpio/gpio-ws16c48.c
+++ b/drivers/gpio/gpio-ws16c48.c
@@ -51,7 +51,7 @@ struct ws16c48_gpio {
 	struct gpio_chip chip;
 	unsigned char io_state[6];
 	unsigned char out_state[6];
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned long irq_mask;
 	unsigned long flow_mask;
 	unsigned base;
@@ -73,13 +73,13 @@ static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	const unsigned mask = BIT(offset % 8);
 	unsigned long flags;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	ws16c48gpio->io_state[port] |= mask;
 	ws16c48gpio->out_state[port] &= ~mask;
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 	return 0;
 }
@@ -92,7 +92,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip,
 	const unsigned mask = BIT(offset % 8);
 	unsigned long flags;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	ws16c48gpio->io_state[port] &= ~mask;
 	if (value)
@@ -101,7 +101,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip,
 		ws16c48gpio->out_state[port] &= ~mask;
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 	return 0;
 }
@@ -114,17 +114,17 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset)
 	unsigned long flags;
 	unsigned port_state;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	/* ensure that GPIO is set for input */
 	if (!(ws16c48gpio->io_state[port] & mask)) {
-		spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 		return -EINVAL;
 	}
 
 	port_state = inb(ws16c48gpio->base + port);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 	return !!(port_state & mask);
 }
@@ -136,11 +136,11 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	const unsigned mask = BIT(offset % 8);
 	unsigned long flags;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	/* ensure that GPIO is set for output */
 	if (ws16c48gpio->io_state[port] & mask) {
-		spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 		return;
 	}
 
@@ -150,7 +150,7 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 		ws16c48gpio->out_state[port] &= ~mask;
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 }
 
 static void ws16c48_gpio_set_multiple(struct gpio_chip *chip,
@@ -178,14 +178,14 @@ static void ws16c48_gpio_set_multiple(struct gpio_chip *chip,
 		iomask = mask[BIT_WORD(i)] & ~ws16c48gpio->io_state[port];
 		bitmask = iomask & bits[BIT_WORD(i)];
 
-		spin_lock_irqsave(&ws16c48gpio->lock, flags);
+		raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 		/* update output state data and set device gpio register */
 		ws16c48gpio->out_state[port] &= ~iomask;
 		ws16c48gpio->out_state[port] |= bitmask;
 		outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 
-		spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 		/* prepare for next gpio register set */
 		mask[BIT_WORD(i)] >>= gpio_reg_size;
@@ -207,7 +207,7 @@ static void ws16c48_irq_ack(struct irq_data *data)
 	if (port > 2)
 		return;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	port_state = ws16c48gpio->irq_mask >> (8*port);
 
@@ -216,7 +216,7 @@ static void ws16c48_irq_ack(struct irq_data *data)
 	outb(port_state | mask, ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 }
 
 static void ws16c48_irq_mask(struct irq_data *data)
@@ -232,7 +232,7 @@ static void ws16c48_irq_mask(struct irq_data *data)
 	if (port > 2)
 		return;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	ws16c48gpio->irq_mask &= ~mask;
 
@@ -240,7 +240,7 @@ static void ws16c48_irq_mask(struct irq_data *data)
 	outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 }
 
 static void ws16c48_irq_unmask(struct irq_data *data)
@@ -256,7 +256,7 @@ static void ws16c48_irq_unmask(struct irq_data *data)
 	if (port > 2)
 		return;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	ws16c48gpio->irq_mask |= mask;
 
@@ -264,7 +264,7 @@ static void ws16c48_irq_unmask(struct irq_data *data)
 	outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 }
 
 static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
@@ -280,7 +280,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
 	if (port > 2)
 		return -EINVAL;
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 	switch (flow_type) {
 	case IRQ_TYPE_NONE:
@@ -292,7 +292,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
 		ws16c48gpio->flow_mask &= ~mask;
 		break;
 	default:
-		spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 		return -EINVAL;
 	}
 
@@ -300,7 +300,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type)
 	outb(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 	return 0;
 }
@@ -387,7 +387,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id)
 	ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple;
 	ws16c48gpio->base = base[id];
 
-	spin_lock_init(&ws16c48gpio->lock);
+	raw_spin_lock_init(&ws16c48gpio->lock);
 
 	err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio);
 	if (err) {
diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c
index 4620d050e5a8e06db39bbe69457d6d9c9b5390d1..d857e1d8e731e7f6e61023e38d960edc6c7c9e8c 100644
--- a/drivers/gpio/gpio-xlp.c
+++ b/drivers/gpio/gpio-xlp.c
@@ -404,7 +404,9 @@ static int xlp_gpio_probe(struct platform_device *pdev)
 
 	/* XLP(MIPS) has fixed range for GPIO IRQs, Vulcan(ARM64) does not */
 	if (soc_type != GPIO_VARIANT_VULCAN) {
-		irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
+		irq_base = devm_irq_alloc_descs(&pdev->dev, -1,
+						XLP_GPIO_IRQ_BASE,
+						gc->ngpio, 0);
 		if (irq_base < 0) {
 			dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
 			return irq_base;
@@ -415,7 +417,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
 
 	err = gpiochip_add_data(gc, priv);
 	if (err < 0)
-		goto out_free_desc;
+		return err;
 
 	err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base,
 				handle_level_irq, IRQ_TYPE_NONE);
@@ -433,14 +435,13 @@ static int xlp_gpio_probe(struct platform_device *pdev)
 
 out_gpio_remove:
 	gpiochip_remove(gc);
-out_free_desc:
-	irq_free_descs(irq_base, gc->ngpio);
 	return err;
 }
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xlp_gpio_acpi_match[] = {
 	{ "BRCM9006", GPIO_VARIANT_VULCAN },
+	{ "CAV9006",  GPIO_VARIANT_VULCAN },
 	{},
 };
 MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match);
diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c
index 93de8be0d885fc7b1a9991d496cd0e0160b71725..be3a87da8438016ff2f5ea800434ec9d8febeecb 100644
--- a/drivers/gpio/gpio-zx.c
+++ b/drivers/gpio/gpio-zx.c
@@ -41,7 +41,7 @@
 #define ZX_GPIO_NR	16
 
 struct zx_gpio {
-	spinlock_t		lock;
+	raw_spinlock_t		lock;
 
 	void __iomem		*base;
 	struct gpio_chip	gc;
@@ -56,11 +56,11 @@ static int zx_direction_input(struct gpio_chip *gc, unsigned offset)
 	if (offset >= gc->ngpio)
 		return -EINVAL;
 
-	spin_lock_irqsave(&chip->lock, flags);
+	raw_spin_lock_irqsave(&chip->lock, flags);
 	gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
 	gpiodir &= ~BIT(offset);
 	writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
-	spin_unlock_irqrestore(&chip->lock, flags);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
 
 	return 0;
 }
@@ -75,7 +75,7 @@ static int zx_direction_output(struct gpio_chip *gc, unsigned offset,
 	if (offset >= gc->ngpio)
 		return -EINVAL;
 
-	spin_lock_irqsave(&chip->lock, flags);
+	raw_spin_lock_irqsave(&chip->lock, flags);
 	gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
 	gpiodir |= BIT(offset);
 	writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
@@ -84,7 +84,7 @@ static int zx_direction_output(struct gpio_chip *gc, unsigned offset,
 		writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1);
 	else
 		writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0);
-	spin_unlock_irqrestore(&chip->lock, flags);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
 
 	return 0;
 }
@@ -118,7 +118,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger)
 	if (offset < 0 || offset >= ZX_GPIO_NR)
 		return -EINVAL;
 
-	spin_lock_irqsave(&chip->lock, flags);
+	raw_spin_lock_irqsave(&chip->lock, flags);
 
 	gpioiev = readw_relaxed(chip->base + ZX_GPIO_IV);
 	gpiois = readw_relaxed(chip->base + ZX_GPIO_IVE);
@@ -151,7 +151,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger)
 	writew_relaxed(gpioi_epos, chip->base + ZX_GPIO_IEP);
 	writew_relaxed(gpioi_eneg, chip->base + ZX_GPIO_IEN);
 	writew_relaxed(gpioiev, chip->base + ZX_GPIO_IV);
-	spin_unlock_irqrestore(&chip->lock, flags);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
 
 	return 0;
 }
@@ -184,12 +184,12 @@ static void zx_irq_mask(struct irq_data *d)
 	u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
 	u16 gpioie;
 
-	spin_lock(&chip->lock);
+	raw_spin_lock(&chip->lock);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) | mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) & ~mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
-	spin_unlock(&chip->lock);
+	raw_spin_unlock(&chip->lock);
 }
 
 static void zx_irq_unmask(struct irq_data *d)
@@ -199,12 +199,12 @@ static void zx_irq_unmask(struct irq_data *d)
 	u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
 	u16 gpioie;
 
-	spin_lock(&chip->lock);
+	raw_spin_lock(&chip->lock);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) & ~mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) | mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
-	spin_unlock(&chip->lock);
+	raw_spin_unlock(&chip->lock);
 }
 
 static struct irq_chip zx_irqchip = {
@@ -230,7 +230,7 @@ static int zx_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(chip->base))
 		return PTR_ERR(chip->base);
 
-	spin_lock_init(&chip->lock);
+	raw_spin_lock_init(&chip->lock);
 	if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
 		chip->gc.request = gpiochip_generic_request;
 		chip->gc.free = gpiochip_generic_free;
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 2bd683e2be022dd2c9a2b5c6cd7285d4c68e69eb..2185232da823e658c326063dda45aaa2d9a66f71 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -368,6 +368,37 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev,
 }
 EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
 
+static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res)
+{
+	acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev));
+}
+
+int devm_acpi_dev_add_driver_gpios(struct device *dev,
+				   const struct acpi_gpio_mapping *gpios)
+{
+	void *res;
+	int ret;
+
+	res = devres_alloc(devm_acpi_dev_release_driver_gpios, 0, GFP_KERNEL);
+	if (!res)
+		return -ENOMEM;
+
+	ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), gpios);
+	if (ret) {
+		devres_free(res);
+		return ret;
+	}
+	devres_add(dev, res);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_acpi_dev_add_driver_gpios);
+
+void devm_acpi_dev_remove_driver_gpios(struct device *dev)
+{
+	WARN_ON(devres_release(dev, devm_acpi_dev_release_driver_gpios, NULL, NULL));
+}
+EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios);
+
 static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
 				      const char *name, int index,
 				      struct acpi_reference_args *args)
@@ -661,20 +692,24 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 {
 	int idx, i;
 	unsigned int irq_flags;
-	int ret = -ENOENT;
 
 	for (i = 0, idx = 0; idx <= index; i++) {
 		struct acpi_gpio_info info;
 		struct gpio_desc *desc;
 
 		desc = acpi_get_gpiod_by_index(adev, NULL, i, &info);
-		if (IS_ERR(desc)) {
-			ret = PTR_ERR(desc);
-			break;
-		}
+
+		/* Ignore -EPROBE_DEFER, it only matters if idx matches */
+		if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
+			return PTR_ERR(desc);
+
 		if (info.gpioint && idx++ == index) {
-			int irq = gpiod_to_irq(desc);
+			int irq;
 
+			if (IS_ERR(desc))
+				return PTR_ERR(desc);
+
+			irq = gpiod_to_irq(desc);
 			if (irq < 0)
 				return irq;
 
@@ -690,7 +725,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 		}
 
 	}
-	return ret;
+	return -ENOENT;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get);
 
@@ -1075,7 +1110,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
 					break;
 				}
 		}
-		if (count >= 0)
+		if (count > 0)
 			break;
 	}
 
@@ -1091,7 +1126,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
 		if (crs_count > 0)
 			count = crs_count;
 	}
-	return count;
+	return count ? count : -ENOENT;
 }
 
 struct acpi_crs_lookup {
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 975b9f6cf4082dfcfde1d98e8a868dd935b867bd..b13b7c7c335f415b6d952fb084250f5c18bfa5e0 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -147,7 +147,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
 		*flags |= GPIO_ACTIVE_LOW;
 
 	if (of_flags & OF_GPIO_SINGLE_ENDED) {
-		if (of_flags & OF_GPIO_ACTIVE_LOW)
+		if (of_flags & OF_GPIO_OPEN_DRAIN)
 			*flags |= GPIO_OPEN_DRAIN;
 		else
 			*flags |= GPIO_OPEN_SOURCE;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 8b4d721d6d6342cbc226b719f60a8c99d826a99b..1d1fa7248d63e52fe1050596e1df615f007f96c5 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1522,7 +1522,7 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
  */
 static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
 					  struct irq_chip *irqchip,
-					  int parent_irq,
+					  unsigned int parent_irq,
 					  irq_flow_handler_t parent_handler)
 {
 	unsigned int offset;
@@ -1571,7 +1571,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
  */
 void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 				  struct irq_chip *irqchip,
-				  int parent_irq,
+				  unsigned int parent_irq,
 				  irq_flow_handler_t parent_handler)
 {
 	gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
@@ -1588,7 +1588,7 @@ EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
  */
 void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
 				 struct irq_chip *irqchip,
-				 int parent_irq)
+				 unsigned int parent_irq)
 {
 	if (!gpiochip->irq_nested) {
 		chip_err(gpiochip, "tried to nest a chained gpiochip\n");
@@ -3122,10 +3122,10 @@ static int dt_gpio_count(struct device *dev, const char *con_id)
 				 gpio_suffixes[i]);
 
 		ret = of_gpio_named_count(dev->of_node, propname);
-		if (ret >= 0)
+		if (ret > 0)
 			break;
 	}
-	return ret;
+	return ret ? ret : -ENOENT;
 }
 
 static int platform_gpio_count(struct device *dev, const char *con_id)
@@ -3326,7 +3326,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_index);
  * underlying firmware interface and then makes sure that the GPIO
  * descriptor is requested before it is returned to the caller.
  *
- * On successfull request the GPIO pin is configured in accordance with
+ * On successful request the GPIO pin is configured in accordance with
  * provided @dflags.
  *
  * In case of error an ERR_PTR() is returned.
@@ -3340,6 +3340,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
 	unsigned long lflags = 0;
 	bool active_low = false;
 	bool single_ended = false;
+	bool open_drain = false;
 	int ret;
 
 	if (!fwnode)
@@ -3353,6 +3354,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
 		if (!IS_ERR(desc)) {
 			active_low = flags & OF_GPIO_ACTIVE_LOW;
 			single_ended = flags & OF_GPIO_SINGLE_ENDED;
+			open_drain = flags & OF_GPIO_OPEN_DRAIN;
 		}
 	} else if (is_acpi_node(fwnode)) {
 		struct acpi_gpio_info info;
@@ -3373,7 +3375,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
 		lflags |= GPIO_ACTIVE_LOW;
 
 	if (single_ended) {
-		if (active_low)
+		if (open_drain)
 			lflags |= GPIO_OPEN_DRAIN;
 		else
 			lflags |= GPIO_OPEN_SOURCE;
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index f210a33225598f19ac0891eec7d48c8cc152af75..e37d37273182097d412f30a3878ea0303f9f7a5b 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -320,9 +320,10 @@ static int soc_button_probe(struct platform_device *pdev)
 		button_info = (struct soc_button_info *)id->driver_data;
 	}
 
-	if (gpiod_count(dev, NULL) <= 0) {
+	error = gpiod_count(dev, NULL);
+	if (error < 0) {
 		dev_dbg(dev, "no GPIO attached, ignoring...\n");
-		return -ENODEV;
+		return error;
 	}
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
diff --git a/drivers/platform/x86/surface3_button.c b/drivers/platform/x86/surface3_button.c
index 8bfd7f613d362190c90e2df294a93931361c8a7e..57f51476bb65e5b560444a4f6bdce0d48fe8d2f0 100644
--- a/drivers/platform/x86/surface3_button.c
+++ b/drivers/platform/x86/surface3_button.c
@@ -196,9 +196,10 @@ static int surface3_button_probe(struct i2c_client *client,
 		    strlen(SURFACE_BUTTON_OBJ_NAME)))
 		return -ENODEV;
 
-	if (gpiod_count(dev, KBUILD_MODNAME) <= 0) {
+	error = gpiod_count(dev, NULL);
+	if (error < 0) {
 		dev_dbg(dev, "no GPIO attached, ignoring...\n");
-		return -ENODEV;
+		return error;
 	}
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index cce0a220b6b0437f23102da3fa56f4f7373f9082..a15ec71d04233a3ac9e93fe5d9063edb0a4d89af 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -125,8 +125,10 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
 		if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
 			struct gpio_desc *gpio;
 
-			acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
+			ret = devm_acpi_dev_add_driver_gpios(&pdev->dev,
 					acpi_dwc3_byt_gpios);
+			if (ret)
+				dev_dbg(&pdev->dev, "failed to add mapping table\n");
 
 			/*
 			 * These GPIOs will turn on the USB2 PHY. Note that we have to
@@ -242,7 +244,6 @@ static void dwc3_pci_remove(struct pci_dev *pci)
 
 	device_init_wakeup(&pci->dev, false);
 	pm_runtime_get(&pci->dev);
-	acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev));
 	platform_device_unregister(dwc->dwc3);
 }
 
diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
index c673d2c87c604ae86fc6bfd523a580308752148a..b4f54da694eb4a65ecff5a6a34c3ed2db1c088db 100644
--- a/include/dt-bindings/gpio/gpio.h
+++ b/include/dt-bindings/gpio/gpio.h
@@ -17,11 +17,15 @@
 #define GPIO_PUSH_PULL 0
 #define GPIO_SINGLE_ENDED 2
 
+/* Bit 2 express Open drain or open source */
+#define GPIO_LINE_OPEN_SOURCE 0
+#define GPIO_LINE_OPEN_DRAIN 4
+
 /*
- * Open Drain/Collector is the combination of single-ended active low,
- * Open Source/Emitter is the combination of single-ended active high.
+ * Open Drain/Collector is the combination of single-ended open drain interface.
+ * Open Source/Emitter is the combination of single-ended open source interface.
  */
-#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_ACTIVE_LOW)
-#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_ACTIVE_HIGH)
+#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN)
+#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE)
 
 #endif
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index f729adaac18bf143f18844009e4aa376da47d510..0f9de30d725fc225e686ec95c5c73e5ccee9b572 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -957,6 +957,10 @@ static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
 		adev->driver_gpios = NULL;
 }
 
+int devm_acpi_dev_add_driver_gpios(struct device *dev,
+				   const struct acpi_gpio_mapping *gpios);
+void devm_acpi_dev_remove_driver_gpios(struct device *dev);
+
 int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index);
 #else
 static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
@@ -966,6 +970,13 @@ static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
 }
 static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {}
 
+static inline int devm_acpi_dev_add_driver_gpios(struct device *dev,
+			      const struct acpi_gpio_mapping *gpios)
+{
+	return -ENXIO;
+}
+static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {}
+
 static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 {
 	return -ENXIO;
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 933d936566055de430f9db64ae152eb31785b7ff..8f702fcbe4853e349235813c3438493b362fea3c 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -170,14 +170,14 @@ static inline struct gpio_desc *__must_check
 gpiod_get_optional(struct device *dev, const char *con_id,
 		   enum gpiod_flags flags)
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 
 static inline struct gpio_desc *__must_check
 gpiod_get_index_optional(struct device *dev, const char *con_id,
 			 unsigned int index, enum gpiod_flags flags)
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 
 static inline struct gpio_descs *__must_check
@@ -191,7 +191,7 @@ static inline struct gpio_descs *__must_check
 gpiod_get_array_optional(struct device *dev, const char *con_id,
 			 enum gpiod_flags flags)
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 
 static inline void gpiod_put(struct gpio_desc *desc)
@@ -231,14 +231,14 @@ static inline struct gpio_desc *__must_check
 devm_gpiod_get_optional(struct device *dev, const char *con_id,
 			  enum gpiod_flags flags)
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 
 static inline struct gpio_desc *__must_check
 devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
 				unsigned int index, enum gpiod_flags flags)
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 
 static inline struct gpio_descs *__must_check
@@ -252,7 +252,7 @@ static inline struct gpio_descs *__must_check
 devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
 			      enum gpiod_flags flags)
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 
 static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 846f3b9894805c482242c8b0117fe2537842e5bb..393582867afddb17e2969a659bedcb975f710208 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -168,7 +168,7 @@ struct gpio_chip {
 	unsigned int		irq_base;
 	irq_flow_handler_t	irq_handler;
 	unsigned int		irq_default_type;
-	int			irq_chained_parent;
+	unsigned int		irq_chained_parent;
 	bool			irq_nested;
 	bool			irq_need_valid_mask;
 	unsigned long		*irq_valid_mask;
@@ -244,12 +244,12 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
 
 void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 		struct irq_chip *irqchip,
-		int parent_irq,
+		unsigned int parent_irq,
 		irq_flow_handler_t parent_handler);
 
 void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
 		struct irq_chip *irqchip,
-		int parent_irq);
+		unsigned int parent_irq);
 
 int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 			     struct irq_chip *irqchip,
diff --git a/include/linux/gpio/gpio-reg.h b/include/linux/gpio/gpio-reg.h
new file mode 100644
index 0000000000000000000000000000000000000000..90e0b9060e6dfc4c6d4ecf5781f0487ee283b657
--- /dev/null
+++ b/include/linux/gpio/gpio-reg.h
@@ -0,0 +1,13 @@
+#ifndef GPIO_REG_H
+#define GPIO_REG_H
+
+struct device;
+struct irq_domain;
+
+struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg,
+	int base, int num, const char *label, u32 direction, u32 def_out,
+	const char *const *names, struct irq_domain *irqdom, const int *irqs);
+
+int gpio_reg_resume(struct gpio_chip *gc);
+
+#endif
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 3f87ea5b8bee24d0e5cfa78517cfaf338a2bf051..1e089d5a182beb076d9021e41ab9672820dcfb82 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -30,6 +30,7 @@ struct device_node;
 enum of_gpio_flags {
 	OF_GPIO_ACTIVE_LOW = 0x1,
 	OF_GPIO_SINGLE_ENDED = 0x2,
+	OF_GPIO_OPEN_DRAIN = 0x4,
 };
 
 #ifdef CONFIG_OF_GPIO