Pārlūkot izejas kodu

Merge tag 'gpio-v4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.12 kernel cycle.

  Core changes:

   - Return NULL from gpiod_get_optional() when GPIOLIB is disabled.
     This was a much discussed change. It affects use cases where people
     write drivers that might or might not be using GPIO resources. I
     have decided that this is the lesser evil right now.

   - Make gpiod_count() behave consistently across different hardware
     descriptions.

   - Fix the syntax around open drain/open source to not infer active
     high/low semantics.

  New drivers:

   - A new single-register fixed-direction framework driver for hardware
     that have lines controlled by a single register that just work in
     one direction (out or in), including IRQ support.

   - Support the Fintek F71889A GPIO SuperIO controller.

   - Support the National NI 169445 MMIO GPIO.

   - Support for the X-Gene derivative of the DWC GPIO controller

   - Support for the Rohm BD9571MWV-M PMIC GPIO controller.

   - Refactor the Gemini GPIO driver to a generic Faraday FTGPIO driver
     and replace both the Gemini and the Moxa ART custom drivers with
     this driver.

  Driver improvements:

   - A whole slew of drivers have their spinlocks chaned to raw
     spinlocks as they provide irqchips, and thus we are progressing on
     realtime compliance.

   - Use devm_irq_alloc_descs() in a slew of drivers, getting managed
     resources.

   - Support for the embedded PWM controller inside the MVEBU driver.

   - Debounce, open source and open drain support for the Aspeed driver.

   - Misc smaller fixes like spelling and syntax and whatnot"

* tag 'gpio-v4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (77 commits)
  gpio: f7188x: Add a missing break
  gpio: omap: return error if requested debounce time is not possible
  gpio: Add ROHM BD9571MWV-M PMIC GPIO driver
  gpio: gpio-wcove: fix GPIO IRQ status mask
  gpio: DT bindings, move tca9554 from pcf857x to pca953x
  gpio: move tca9554 from pcf857x to pca953x
  gpio: arizona: Correct check whether the pin is an input
  gpio: Add XRA1403 DTS binding documentation
  dt-bindings: add exar to vendor prefixes list
  gpio: gpio-wcove: fix irq pending status bit width
  gpio: dwapb: use dwapb_read instead of readl_relaxed
  gpio: aspeed: Add open-source and open-drain support
  gpio: aspeed: Add debounce support
  gpio: aspeed: dt: Add optional clocks property
  gpio: aspeed: dt: Fix description alignment in bindings document
  gpio: mvebu: Add limited PWM support
  gpio: Use unsigned int for interrupt numbers
  gpio: f7188x: Add F71889A GPIO support.
  gpio: core: Decouple open drain/source flag with active low/high
  gpio: arizona: Correct handling for reading input GPIOs
  ...
Linus Torvalds 8 gadi atpakaļ
vecāks
revīzija
2bd8040174
66 mainītis faili ar 1860 papildinājumiem un 648 dzēšanām
  1. 6 3
      Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt
  2. 2 1
      Documentation/devicetree/bindings/gpio/gpio-aspeed.txt
  3. 32 0
      Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
  4. 1 0
      Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
  5. 0 1
      Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
  6. 27 0
      Documentation/devicetree/bindings/gpio/gpio-thunderx.txt
  7. 46 0
      Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
  8. 0 19
      Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt
  9. 38 0
      Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt
  10. 1 0
      Documentation/devicetree/bindings/vendor-prefixes.txt
  11. 6 0
      Documentation/gpio/consumer.txt
  12. 2 0
      MAINTAINERS
  13. 28 18
      drivers/gpio/Kconfig
  14. 3 2
      drivers/gpio/Makefile
  15. 1 1
      drivers/gpio/devres.c
  16. 19 19
      drivers/gpio/gpio-104-dio-48e.c
  17. 10 8
      drivers/gpio/gpio-104-idi-48.c
  18. 12 12
      drivers/gpio/gpio-104-idio-16.c
  19. 12 12
      drivers/gpio/gpio-altera.c
  20. 28 2
      drivers/gpio/gpio-arizona.c
  21. 280 5
      drivers/gpio/gpio-aspeed.c
  22. 14 14
      drivers/gpio/gpio-ath79.c
  23. 24 24
      drivers/gpio/gpio-bcm-kona.c
  24. 144 0
      drivers/gpio/gpio-bd9571mwv.c
  25. 1 1
      drivers/gpio/gpio-davinci.c
  26. 75 18
      drivers/gpio/gpio-dwapb.c
  27. 12 12
      drivers/gpio/gpio-etraxfs.c
  28. 12 11
      drivers/gpio/gpio-exar.c
  29. 22 2
      drivers/gpio/gpio-f7188x.c
  30. 39 33
      drivers/gpio/gpio-ftgpio010.c
  31. 1 1
      drivers/gpio/gpio-merrifield.c
  32. 7 21
      drivers/gpio/gpio-ml-ioh.c
  33. 1 0
      drivers/gpio/gpio-mmio.c
  34. 1 15
      drivers/gpio/gpio-mockup.c
  35. 0 84
      drivers/gpio/gpio-moxart.c
  36. 373 62
      drivers/gpio/gpio-mvebu.c
  37. 2 4
      drivers/gpio/gpio-mxc.c
  38. 2 4
      drivers/gpio/gpio-mxs.c
  39. 19 7
      drivers/gpio/gpio-omap.c
  40. 31 7
      drivers/gpio/gpio-pca953x.c
  41. 0 2
      drivers/gpio/gpio-pcf857x.c
  42. 4 10
      drivers/gpio/gpio-pch.c
  43. 14 14
      drivers/gpio/gpio-pci-idio-16.c
  44. 14 14
      drivers/gpio/gpio-pl061.c
  45. 1 1
      drivers/gpio/gpio-pxa.c
  46. 185 0
      drivers/gpio/gpio-reg.c
  47. 139 77
      drivers/gpio/gpio-sa1100.c
  48. 11 17
      drivers/gpio/gpio-sodaville.c
  49. 6 11
      drivers/gpio/gpio-sta2x11.c
  50. 2 1
      drivers/gpio/gpio-twl4030.c
  51. 5 3
      drivers/gpio/gpio-wcove.c
  52. 23 23
      drivers/gpio/gpio-ws16c48.c
  53. 5 4
      drivers/gpio/gpio-xlp.c
  54. 12 12
      drivers/gpio/gpio-zx.c
  55. 44 9
      drivers/gpio/gpiolib-acpi.c
  56. 1 1
      drivers/gpio/gpiolib-of.c
  57. 9 7
      drivers/gpio/gpiolib.c
  58. 3 2
      drivers/input/misc/soc_button_array.c
  59. 3 2
      drivers/platform/x86/surface3_button.c
  60. 3 2
      drivers/usb/dwc3/dwc3-pci.c
  61. 8 4
      include/dt-bindings/gpio/gpio.h
  62. 11 0
      include/linux/acpi.h
  63. 6 6
      include/linux/gpio/consumer.h
  64. 3 3
      include/linux/gpio/driver.h
  65. 13 0
      include/linux/gpio/gpio-reg.h
  66. 1 0
      include/linux/of_gpio.h

+ 6 - 3
Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt → Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt

@@ -1,8 +1,11 @@
-Cortina Systems Gemini GPIO Controller
+Faraday Technology FTGPIO010 GPIO Controller
 
 
 Required properties:
 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
 - reg : Should contain registers location and length
 - interrupts : Should contain the interrupt line for the GPIO block
 - interrupts : Should contain the interrupt line for the GPIO block
 - gpio-controller : marks this as a GPIO controller
 - gpio-controller : marks this as a GPIO controller
@@ -14,7 +17,7 @@ Required properties:
 Example:
 Example:
 
 
 gpio@4d000000 {
 gpio@4d000000 {
-	compatible = "cortina,gemini-gpio";
+	compatible = "cortina,gemini-gpio", "faraday,ftgpio010";
 	reg = <0x4d000000 0x100>;
 	reg = <0x4d000000 0x100>;
 	interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
 	interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
 	gpio-controller;
 	gpio-controller;

+ 2 - 1
Documentation/devicetree/bindings/gpio/gpio-aspeed.txt

@@ -17,7 +17,8 @@ Required properties:
 
 
 Optional 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
 The gpio and interrupt properties are further described in their respective
 bindings documentation:
 bindings documentation:

+ 32 - 0
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
 - #gpio-cells: Should be two. The first cell is the pin number. The
   second cell is reserved for flags, unused at the moment.
   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:
 Example:
 
 
 		gpio0: gpio@d0018100 {
 		gpio0: gpio@d0018100 {
@@ -51,3 +69,17 @@ Example:
 			#interrupt-cells = <2>;
 			#interrupt-cells = <2>;
 			interrupts = <16>, <17>, <18>, <19>;
 			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>;
+		};

+ 1 - 0
Documentation/devicetree/bindings/gpio/gpio-pca953x.txt

@@ -26,6 +26,7 @@ Required properties:
 	ti,tca6416
 	ti,tca6416
 	ti,tca6424
 	ti,tca6424
 	ti,tca9539
 	ti,tca9539
+	ti,tca9554
 	onsemi,pca9654
 	onsemi,pca9654
 	exar,xra1202
 	exar,xra1202
 
 

+ 0 - 1
Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt

@@ -25,7 +25,6 @@ Required Properties:
     - "nxp,pcf8574": For the NXP PCF8574
     - "nxp,pcf8574": For the NXP PCF8574
     - "nxp,pcf8574a": For the NXP PCF8574A
     - "nxp,pcf8574a": For the NXP PCF8574A
     - "nxp,pcf8575": For the NXP PCF8575
     - "nxp,pcf8575": For the NXP PCF8575
-    - "ti,tca9554": For the TI TCA9554
 
 
   - reg: I2C slave address.
   - reg: I2C slave address.
 
 

+ 27 - 0
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>;
+};

+ 46 - 0
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>;
+	};

+ 0 - 19
Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt

@@ -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>;
-	};

+ 38 - 0
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;
+	};

+ 1 - 0
Documentation/devicetree/bindings/vendor-prefixes.txt

@@ -103,6 +103,7 @@ ettus	NI Ettus Research
 eukrea  Eukréa Electromatique
 eukrea  Eukréa Electromatique
 everest	Everest Semiconductor Co. Ltd.
 everest	Everest Semiconductor Co. Ltd.
 everspin	Everspin Technologies, Inc.
 everspin	Everspin Technologies, Inc.
+exar	Exar Corporation
 excito	Excito
 excito	Excito
 ezchip	EZchip Semiconductor
 ezchip	EZchip Semiconductor
 faraday	Faraday Technology Corporation
 faraday	Faraday Technology Corporation

+ 6 - 0
Documentation/gpio/consumer.txt

@@ -70,6 +70,12 @@ instead of -ENOENT if no GPIO has been assigned to the requested function:
 						   unsigned int index,
 						   unsigned int index,
 						   enum gpiod_flags flags)
 						   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:
 For a function using multiple GPIOs all of those can be obtained with one call:
 
 
 	struct gpio_descs *gpiod_get_array(struct device *dev,
 	struct gpio_descs *gpiod_get_array(struct device *dev,

+ 2 - 0
MAINTAINERS

@@ -10315,6 +10315,8 @@ F:	include/linux/pwm.h
 F:	drivers/pwm/
 F:	drivers/pwm/
 F:	drivers/video/backlight/pwm_bl.c
 F:	drivers/video/backlight/pwm_bl.c
 F:	include/linux/pwm_backlight.h
 F:	include/linux/pwm_backlight.h
+F:	drivers/gpio/gpio-mvebu.c
+F:	Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
 
 
 PXA2xx/PXA3xx SUPPORT
 PXA2xx/PXA3xx SUPPORT
 M:	Daniel Mack <daniel@zonque.org>
 M:	Daniel Mack <daniel@zonque.org>

+ 28 - 18
drivers/gpio/Kconfig

@@ -204,14 +204,15 @@ config GPIO_GE_FPGA
 	  and write pin state) for GPIO implemented in a number of GE single
 	  and write pin state) for GPIO implemented in a number of GE single
 	  board computers.
 	  board computers.
 
 
-config GPIO_GEMINI
-	bool "Gemini GPIO"
-	depends on ARCH_GEMINI
+config GPIO_FTGPIO010
+	bool "Faraday FTGPIO010 GPIO"
 	depends on OF_GPIO
 	depends on OF_GPIO
 	select GPIO_GENERIC
 	select GPIO_GENERIC
 	select GPIOLIB_IRQCHIP
 	select GPIOLIB_IRQCHIP
+	default (ARCH_GEMINI || ARCH_MOXART)
 	help
 	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
 config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
 	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
 	  tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
 	  it.
 	  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
 config GPIO_MPC5200
 	def_bool y
 	def_bool y
 	depends on PPC_MPC52xx
 	depends on PPC_MPC52xx
@@ -387,6 +380,12 @@ config GPIO_RCAR
 	help
 	help
 	  Say yes here to support GPIO on Renesas R-Car SoCs.
 	  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
 config GPIO_SPEAR_SPICS
 	bool "ST SPEAr13xx SPI Chip Select as GPIO support"
 	bool "ST SPEAr13xx SPI Chip Select as GPIO support"
 	depends on PLAT_SPEAR
 	depends on PLAT_SPEAR
@@ -505,7 +504,7 @@ config GPIO_XILINX
 
 
 config GPIO_XLP
 config GPIO_XLP
 	tristate "Netlogic XLP GPIO support"
 	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
 	select GPIOLIB_IRQCHIP
 	help
 	help
 	  This driver provides support for GPIO interface on Netlogic XLP MIPS64
 	  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
 config GPIO_104_DIO_48E
 	tristate "ACCES 104-DIO-48E GPIO support"
 	tristate "ACCES 104-DIO-48E GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	select GPIOLIB_IRQCHIP
 	help
 	help
 	  Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
 	  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
 config GPIO_104_IDIO_16
 	tristate "ACCES 104-IDIO-16 GPIO support"
 	tristate "ACCES 104-IDIO-16 GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	select GPIOLIB_IRQCHIP
 	help
 	help
 	  Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
 	  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
 config GPIO_104_IDI_48
 	tristate "ACCES 104-IDI-48 GPIO support"
 	tristate "ACCES 104-IDI-48 GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	select GPIOLIB_IRQCHIP
 	help
 	help
 	  Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
 	  Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
@@ -598,7 +597,7 @@ config GPIO_F7188X
 
 
 config GPIO_GPIO_MM
 config GPIO_GPIO_MM
 	tristate "Diamond Systems GPIO-MM GPIO support"
 	tristate "Diamond Systems GPIO-MM GPIO support"
-	depends on ISA_BUS_API
+	depends on PC104 && ISA_BUS_API
 	help
 	help
 	  Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12.
 	  Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12.
 
 
@@ -753,7 +752,7 @@ config GPIO_PCA953X
 	  4 bits:	pca9536, pca9537
 	  4 bits:	pca9536, pca9537
 
 
 	  8 bits:	max7310, max7315, pca6107, pca9534, pca9538, pca9554,
 	  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,
 	  16 bits:	max7312, max7313, pca9535, pca9539, pca9555, pca9575,
 			tca6416
 			tca6416
@@ -845,6 +844,17 @@ config GPIO_ARIZONA
 	help
 	help
 	  Support for GPIOs on Wolfson Arizona class devices.
 	  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
 config GPIO_CRYSTAL_COVE
 	tristate "GPIO support for Crystal Cove PMIC"
 	tristate "GPIO support for Crystal Cove PMIC"
 	depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
 	depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC

+ 3 - 2
drivers/gpio/Makefile

@@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_ASPEED)	+= gpio-aspeed.o
 obj-$(CONFIG_GPIO_ASPEED)	+= gpio-aspeed.o
 obj-$(CONFIG_GPIO_AXP209)	+= gpio-axp209.o
 obj-$(CONFIG_GPIO_AXP209)	+= gpio-axp209.o
 obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.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_BRCMSTB)	+= gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.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_ETRAXFS)	+= gpio-etraxfs.o
 obj-$(CONFIG_GPIO_EXAR)		+= gpio-exar.o
 obj-$(CONFIG_GPIO_EXAR)		+= gpio-exar.o
 obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.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_GE_FPGA)	+= gpio-ge.o
-obj-$(CONFIG_GPIO_GEMINI)	+= gpio-gemini.o
 obj-$(CONFIG_GPIO_GPIO_MM)	+= gpio-gpio-mm.o
 obj-$(CONFIG_GPIO_GPIO_MM)	+= gpio-gpio-mm.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_HTC_EGPIO)		+= gpio-htc-egpio.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_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
 obj-$(CONFIG_GPIO_MOCKUP)      += gpio-mockup.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_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.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_RC5T583)	+= gpio-rc5t583.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
 obj-$(CONFIG_GPIO_RCAR)		+= gpio-rcar.o
 obj-$(CONFIG_GPIO_RCAR)		+= gpio-rcar.o
+obj-$(CONFIG_GPIO_REG)		+= gpio-reg.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_SCH311X)	+= gpio-sch311x.o
 obj-$(CONFIG_GPIO_SCH311X)	+= gpio-sch311x.o

+ 1 - 1
drivers/gpio/devres.c

@@ -136,7 +136,7 @@ EXPORT_SYMBOL(devm_gpiod_get_index);
  * GPIO descriptors returned from this function are automatically disposed on
  * GPIO descriptors returned from this function are automatically disposed on
  * driver detach.
  * 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.
  * provided @flags.
  */
  */
 struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
 struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,

+ 19 - 19
drivers/gpio/gpio-104-dio-48e.c

@@ -55,7 +55,7 @@ struct dio48e_gpio {
 	unsigned char io_state[6];
 	unsigned char io_state[6];
 	unsigned char out_state[6];
 	unsigned char out_state[6];
 	unsigned char control[2];
 	unsigned char control[2];
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned base;
 	unsigned base;
 	unsigned char irq_mask;
 	unsigned char irq_mask;
 };
 };
@@ -78,7 +78,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	unsigned long flags;
 	unsigned long flags;
 	unsigned control;
 	unsigned control;
 
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 
 	/* Check if configuring Port C */
 	/* Check if configuring Port C */
 	if (io_port == 2 || io_port == 5) {
 	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);
 	control &= ~BIT(7);
 	outb(control, control_addr);
 	outb(control, control_addr);
 
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -120,7 +120,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 	unsigned long flags;
 	unsigned long flags;
 	unsigned control;
 	unsigned control;
 
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 
 	/* Check if configuring Port C */
 	/* Check if configuring Port C */
 	if (io_port == 2 || io_port == 5) {
 	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);
 	control &= ~BIT(7);
 	outb(control, control_addr);
 	outb(control, control_addr);
 
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -167,17 +167,17 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset)
 	unsigned long flags;
 	unsigned long flags;
 	unsigned port_state;
 	unsigned port_state;
 
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 
 	/* ensure that GPIO is set for input */
 	/* ensure that GPIO is set for input */
 	if (!(dio48egpio->io_state[port] & mask)) {
 	if (!(dio48egpio->io_state[port] & mask)) {
-		spin_unlock_irqrestore(&dio48egpio->lock, flags);
+		raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
 	port_state = inb(dio48egpio->base + in_port);
 	port_state = inb(dio48egpio->base + in_port);
 
 
-	spin_unlock_irqrestore(&dio48egpio->lock, flags);
+	raw_spin_unlock_irqrestore(&dio48egpio->lock, flags);
 
 
 	return !!(port_state & mask);
 	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;
 	const unsigned out_port = (port > 2) ? port + 1 : port;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 
 	if (value)
 	if (value)
 		dio48egpio->out_state[port] |= mask;
 		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);
 	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,
 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;
 		out_port = (port > 2) ? port + 1 : port;
 		bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
 		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 */
 		/* update output state data and set device gpio register */
 		dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)];
 		dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)];
 		dio48egpio->out_state[port] |= bitmask;
 		dio48egpio->out_state[port] |= bitmask;
 		outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
 		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 */
 		/* prepare for next gpio register set */
 		mask[BIT_WORD(i)] >>= gpio_reg_size;
 		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)
 	if (offset != 19 && offset != 43)
 		return;
 		return;
 
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 
 	if (offset == 19)
 	if (offset == 19)
 		dio48egpio->irq_mask &= ~BIT(0);
 		dio48egpio->irq_mask &= ~BIT(0);
@@ -266,7 +266,7 @@ static void dio48e_irq_mask(struct irq_data *data)
 		/* disable interrupts */
 		/* disable interrupts */
 		inb(dio48egpio->base + 0xB);
 		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)
 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)
 	if (offset != 19 && offset != 43)
 		return;
 		return;
 
 
-	spin_lock_irqsave(&dio48egpio->lock, flags);
+	raw_spin_lock_irqsave(&dio48egpio->lock, flags);
 
 
 	if (!dio48egpio->irq_mask) {
 	if (!dio48egpio->irq_mask) {
 		/* enable interrupts */
 		/* enable interrupts */
@@ -293,7 +293,7 @@ static void dio48e_irq_unmask(struct irq_data *data)
 	else
 	else
 		dio48egpio->irq_mask |= BIT(1);
 		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)
 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,
 		generic_handle_irq(irq_find_mapping(chip->irqdomain,
 			19 + gpio*24));
 			19 + gpio*24));
 
 
-	spin_lock(&dio48egpio->lock);
+	raw_spin_lock(&dio48egpio->lock);
 
 
 	outb(0x00, dio48egpio->base + 0xF);
 	outb(0x00, dio48egpio->base + 0xF);
 
 
-	spin_unlock(&dio48egpio->lock);
+	raw_spin_unlock(&dio48egpio->lock);
 
 
 	return IRQ_HANDLED;
 	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->chip.set_multiple = dio48e_gpio_set_multiple;
 	dio48egpio->base = base[id];
 	dio48egpio->base = base[id];
 
 
-	spin_lock_init(&dio48egpio->lock);
+	raw_spin_lock_init(&dio48egpio->lock);
 
 
 	err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio);
 	err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio);
 	if (err) {
 	if (err) {

+ 10 - 8
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 idi_48_gpio {
 	struct gpio_chip chip;
 	struct gpio_chip chip;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	spinlock_t ack_lock;
 	spinlock_t ack_lock;
 	unsigned char irq_mask[6];
 	unsigned char irq_mask[6];
 	unsigned base;
 	unsigned base;
@@ -112,11 +112,12 @@ static void idi_48_irq_mask(struct irq_data *data)
 			if (!idi48gpio->irq_mask[boundary]) {
 			if (!idi48gpio->irq_mask[boundary]) {
 				idi48gpio->cos_enb &= ~BIT(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);
 				outb(idi48gpio->cos_enb, idi48gpio->base + 7);
 
 
-				spin_unlock_irqrestore(&idi48gpio->lock, flags);
+				raw_spin_unlock_irqrestore(&idi48gpio->lock,
+						           flags);
 			}
 			}
 
 
 			return;
 			return;
@@ -145,11 +146,12 @@ static void idi_48_irq_unmask(struct irq_data *data)
 			if (!prev_irq_mask) {
 			if (!prev_irq_mask) {
 				idi48gpio->cos_enb |= BIT(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);
 				outb(idi48gpio->cos_enb, idi48gpio->base + 7);
 
 
-				spin_unlock_irqrestore(&idi48gpio->lock, flags);
+				raw_spin_unlock_irqrestore(&idi48gpio->lock,
+						           flags);
 			}
 			}
 
 
 			return;
 			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->ack_lock);
 
 
-	spin_lock(&idi48gpio->lock);
+	raw_spin_lock(&idi48gpio->lock);
 
 
 	cos_status = inb(idi48gpio->base + 7);
 	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) */
 	/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
 	if (cos_status & BIT(6)) {
 	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->chip.get = idi_48_gpio_get;
 	idi48gpio->base = base[id];
 	idi48gpio->base = base[id];
 
 
-	spin_lock_init(&idi48gpio->lock);
+	raw_spin_lock_init(&idi48gpio->lock);
 	spin_lock_init(&idi48gpio->ack_lock);
 	spin_lock_init(&idi48gpio->ack_lock);
 
 
 	err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
 	err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);

+ 12 - 12
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 idio_16_gpio {
 	struct gpio_chip chip;
 	struct gpio_chip chip;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned long irq_mask;
 	unsigned long irq_mask;
 	unsigned base;
 	unsigned base;
 	unsigned out_state;
 	unsigned out_state;
@@ -99,7 +99,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	if (offset > 15)
 	if (offset > 15)
 		return;
 		return;
 
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 	if (value)
 	if (value)
 		idio16gpio->out_state |= mask;
 		idio16gpio->out_state |= mask;
@@ -111,7 +111,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	else
 	else
 		outb(idio16gpio->out_state, idio16gpio->base);
 		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,
 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);
 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 	idio16gpio->out_state &= ~*mask;
 	idio16gpio->out_state &= ~*mask;
 	idio16gpio->out_state |= *mask & *bits;
 	idio16gpio->out_state |= *mask & *bits;
@@ -130,7 +130,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
 	if ((*mask >> 8) & 0xFF)
 	if ((*mask >> 8) & 0xFF)
 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
 		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)
 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;
 	idio16gpio->irq_mask &= ~mask;
 
 
 	if (!idio16gpio->irq_mask) {
 	if (!idio16gpio->irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 		outb(0, idio16gpio->base + 2);
 		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;
 	idio16gpio->irq_mask |= mask;
 
 
 	if (!prev_irq_mask) {
 	if (!prev_irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 		inb(idio16gpio->base + 2);
 		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)
 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
 		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
 		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
 
 
-	spin_lock(&idio16gpio->lock);
+	raw_spin_lock(&idio16gpio->lock);
 
 
 	outb(0, idio16gpio->base + 1);
 	outb(0, idio16gpio->base + 1);
 
 
-	spin_unlock(&idio16gpio->lock);
+	raw_spin_unlock(&idio16gpio->lock);
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
@@ -249,7 +249,7 @@ static int idio_16_probe(struct device *dev, unsigned int id)
 	idio16gpio->base = base[id];
 	idio16gpio->base = base[id];
 	idio16gpio->out_state = 0xFFFF;
 	idio16gpio->out_state = 0xFFFF;
 
 
-	spin_lock_init(&idio16gpio->lock);
+	raw_spin_lock_init(&idio16gpio->lock);
 
 
 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 	if (err) {
 	if (err) {

+ 12 - 12
drivers/gpio/gpio-altera.c

@@ -38,7 +38,7 @@
 */
 */
 struct altera_gpio_chip {
 struct altera_gpio_chip {
 	struct of_mm_gpio_chip mmchip;
 	struct of_mm_gpio_chip mmchip;
-	spinlock_t gpio_lock;
+	raw_spinlock_t gpio_lock;
 	int interrupt_trigger;
 	int interrupt_trigger;
 	int mapped_irq;
 	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));
 	altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
 	mm_gc = &altera_gc->mmchip;
 	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);
 	intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
 	/* Set ALTERA_GPIO_IRQ_MASK bit to unmask */
 	/* Set ALTERA_GPIO_IRQ_MASK bit to unmask */
 	intmask |= BIT(irqd_to_hwirq(d));
 	intmask |= BIT(irqd_to_hwirq(d));
 	writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
 	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)
 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));
 	altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d));
 	mm_gc = &altera_gc->mmchip;
 	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);
 	intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
 	/* Clear ALTERA_GPIO_IRQ_MASK bit to mask */
 	/* Clear ALTERA_GPIO_IRQ_MASK bit to mask */
 	intmask &= ~BIT(irqd_to_hwirq(d));
 	intmask &= ~BIT(irqd_to_hwirq(d));
 	writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK);
 	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);
 	mm_gc = to_of_mm_gpio_chip(gc);
 	chip = gpiochip_get_data(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);
 	data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
 	if (value)
 	if (value)
 		data_reg |= BIT(offset);
 		data_reg |= BIT(offset);
 	else
 	else
 		data_reg &= ~BIT(offset);
 		data_reg &= ~BIT(offset);
 	writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA);
 	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)
 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);
 	mm_gc = to_of_mm_gpio_chip(gc);
 	chip = gpiochip_get_data(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 */
 	/* Set pin as input, assumes software controlled IP */
 	gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
 	gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR);
 	gpio_ddr &= ~BIT(offset);
 	gpio_ddr &= ~BIT(offset);
 	writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
 	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;
 	return 0;
 }
 }
@@ -181,7 +181,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc,
 	mm_gc = to_of_mm_gpio_chip(gc);
 	mm_gc = to_of_mm_gpio_chip(gc);
 	chip = gpiochip_get_data(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 */
 	/* Sets the GPIO value */
 	data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
 	data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA);
 	if (value)
 	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 = readl(mm_gc->regs + ALTERA_GPIO_DIR);
 	gpio_ddr |= BIT(offset);
 	gpio_ddr |= BIT(offset);
 	writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR);
 	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;
 	return 0;
 }
 }
@@ -262,7 +262,7 @@ static int altera_gpio_probe(struct platform_device *pdev)
 	if (!altera_gc)
 	if (!altera_gc)
 		return -ENOMEM;
 		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))
 	if (of_property_read_u32(node, "altr,ngpio", &reg))
 		/* By default assume maximum ngpio */
 		/* By default assume maximum ngpio */

+ 28 - 2
drivers/gpio/gpio-arizona.c

@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/seq_file.h>
 #include <linux/seq_file.h>
 
 
 #include <linux/mfd/arizona/core.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_gpio *arizona_gpio = gpiochip_get_data(chip);
 	struct arizona *arizona = arizona_gpio->arizona;
 	struct arizona *arizona = arizona_gpio->arizona;
-	unsigned int val;
+	unsigned int reg, val;
 	int ret;
 	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)
 	if (ret < 0)
 		return ret;
 		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)
 	if (val & ARIZONA_GPN_LVL)
 		return 1;
 		return 1;
 	else
 	else

+ 280 - 5
drivers/gpio/gpio-aspeed.c

@@ -9,14 +9,18 @@
  * 2 of the License, or (at your option) any later version.
  * 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/init.h>
 #include <linux/io.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/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
 
 
 struct aspeed_bank_props {
 struct aspeed_bank_props {
 	unsigned int bank;
 	unsigned int bank;
@@ -29,59 +33,85 @@ struct aspeed_gpio_config {
 	const struct aspeed_bank_props *props;
 	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 aspeed_gpio {
 	struct gpio_chip chip;
 	struct gpio_chip chip;
 	spinlock_t lock;
 	spinlock_t lock;
 	void __iomem *base;
 	void __iomem *base;
 	int irq;
 	int irq;
 	const struct aspeed_gpio_config *config;
 	const struct aspeed_gpio_config *config;
+
+	u8 *offset_timer;
+	unsigned int timer_users[4];
+	struct clk *clk;
 };
 };
 
 
 struct aspeed_gpio_bank {
 struct aspeed_gpio_bank {
 	uint16_t	val_regs;
 	uint16_t	val_regs;
 	uint16_t	irq_regs;
 	uint16_t	irq_regs;
+	uint16_t	debounce_regs;
 	const char	names[4][3];
 	const char	names[4][3];
 };
 };
 
 
+static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 };
+
 static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
 static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
 	{
 	{
 		.val_regs = 0x0000,
 		.val_regs = 0x0000,
 		.irq_regs = 0x0008,
 		.irq_regs = 0x0008,
+		.debounce_regs = 0x0040,
 		.names = { "A", "B", "C", "D" },
 		.names = { "A", "B", "C", "D" },
 	},
 	},
 	{
 	{
 		.val_regs = 0x0020,
 		.val_regs = 0x0020,
 		.irq_regs = 0x0028,
 		.irq_regs = 0x0028,
+		.debounce_regs = 0x0048,
 		.names = { "E", "F", "G", "H" },
 		.names = { "E", "F", "G", "H" },
 	},
 	},
 	{
 	{
 		.val_regs = 0x0070,
 		.val_regs = 0x0070,
 		.irq_regs = 0x0098,
 		.irq_regs = 0x0098,
+		.debounce_regs = 0x00b0,
 		.names = { "I", "J", "K", "L" },
 		.names = { "I", "J", "K", "L" },
 	},
 	},
 	{
 	{
 		.val_regs = 0x0078,
 		.val_regs = 0x0078,
 		.irq_regs = 0x00e8,
 		.irq_regs = 0x00e8,
+		.debounce_regs = 0x0100,
 		.names = { "M", "N", "O", "P" },
 		.names = { "M", "N", "O", "P" },
 	},
 	},
 	{
 	{
 		.val_regs = 0x0080,
 		.val_regs = 0x0080,
 		.irq_regs = 0x0118,
 		.irq_regs = 0x0118,
+		.debounce_regs = 0x0130,
 		.names = { "Q", "R", "S", "T" },
 		.names = { "Q", "R", "S", "T" },
 	},
 	},
 	{
 	{
 		.val_regs = 0x0088,
 		.val_regs = 0x0088,
 		.irq_regs = 0x0148,
 		.irq_regs = 0x0148,
+		.debounce_regs = 0x0160,
 		.names = { "U", "V", "W", "X" },
 		.names = { "U", "V", "W", "X" },
 	},
 	},
 	{
 	{
 		.val_regs = 0x01E0,
 		.val_regs = 0x01E0,
 		.irq_regs = 0x0178,
 		.irq_regs = 0x0178,
+		.debounce_regs = 0x0190,
 		.names = { "Y", "Z", "AA", "AB" },
 		.names = { "Y", "Z", "AA", "AB" },
 	},
 	},
 	{
 	{
 		.val_regs = 0x01E8,
 		.val_regs = 0x01E8,
 		.irq_regs = 0x01A8,
 		.irq_regs = 0x01A8,
+		.debounce_regs = 0x01c0,
 		.names = { "AC", "", "", "" },
 		.names = { "AC", "", "", "" },
 	},
 	},
 };
 };
@@ -99,6 +129,13 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
 #define GPIO_IRQ_TYPE2	0x0c
 #define GPIO_IRQ_TYPE2	0x0c
 #define GPIO_IRQ_STATUS	0x10
 #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)
 static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
 {
 {
 	unsigned int bank = GPIO_BANK(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_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)
 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);
 	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
  * Any banks not specified in a struct aspeed_bank_props array are assumed to
  * have the properties:
  * have the properties:
@@ -565,8 +828,16 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
 	if (!gpio_id)
 	if (!gpio_id)
 		return -EINVAL;
 		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->config = gpio_id->data;
 
 
+	gpio->chip.parent = &pdev->dev;
 	gpio->chip.ngpio = gpio->config->nr_gpios;
 	gpio->chip.ngpio = gpio->config->nr_gpios;
 	gpio->chip.parent = &pdev->dev;
 	gpio->chip.parent = &pdev->dev;
 	gpio->chip.direction_input = aspeed_gpio_dir_in;
 	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.free = aspeed_gpio_free;
 	gpio->chip.get = aspeed_gpio_get;
 	gpio->chip.get = aspeed_gpio_get;
 	gpio->chip.set = aspeed_gpio_set;
 	gpio->chip.set = aspeed_gpio_set;
+	gpio->chip.set_config = aspeed_gpio_set_config;
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.base = -1;
 	gpio->chip.base = -1;
 	gpio->chip.irq_need_valid_mask = true;
 	gpio->chip.irq_need_valid_mask = true;
@@ -584,6 +856,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
 	if (rc < 0)
 	if (rc < 0)
 		return rc;
 		return rc;
 
 
+	gpio->offset_timer =
+		devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);
+
 	return aspeed_gpio_setup_irqs(gpio, pdev);
 	return aspeed_gpio_setup_irqs(gpio, pdev);
 }
 }
 
 

+ 14 - 14
drivers/gpio/gpio-ath79.c

@@ -32,7 +32,7 @@
 struct ath79_gpio_ctrl {
 struct ath79_gpio_ctrl {
 	struct gpio_chip gc;
 	struct gpio_chip gc;
 	void __iomem *base;
 	void __iomem *base;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned long both_edges;
 	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));
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 	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);
 	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)
 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));
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 	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_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)
 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));
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 	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_ENABLE, mask, mask);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, 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)
 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));
 	u32 mask = BIT(irqd_to_hwirq(data));
 	unsigned long flags;
 	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_MASK, mask, 0);
 	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, 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,
 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;
 		return -EINVAL;
 	}
 	}
 
 
-	spin_lock_irqsave(&ctrl->lock, flags);
+	raw_spin_lock_irqsave(&ctrl->lock, flags);
 
 
 	if (flow_type == IRQ_TYPE_EDGE_BOTH) {
 	if (flow_type == IRQ_TYPE_EDGE_BOTH) {
 		ctrl->both_edges |= mask;
 		ctrl->both_edges |= mask;
@@ -165,7 +165,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data,
 		ath79_gpio_update_bits(
 		ath79_gpio_update_bits(
 			ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
 			ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
 
 
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -191,7 +191,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc)
 
 
 	chained_irq_enter(irqchip, 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);
 	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);
 				both_edges, ~state);
 	}
 	}
 
 
-	spin_unlock_irqrestore(&ctrl->lock, flags);
+	raw_spin_unlock_irqrestore(&ctrl->lock, flags);
 
 
 	if (pending) {
 	if (pending) {
 		for_each_set_bit(irq, &pending, gc->ngpio)
 		for_each_set_bit(irq, &pending, gc->ngpio)
@@ -262,7 +262,7 @@ static int ath79_gpio_probe(struct platform_device *pdev)
 	if (!ctrl->base)
 	if (!ctrl->base)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	spin_lock_init(&ctrl->lock);
+	raw_spin_lock_init(&ctrl->lock);
 	err = bgpio_init(&ctrl->gc, &pdev->dev, 4,
 	err = bgpio_init(&ctrl->gc, &pdev->dev, 4,
 			ctrl->base + AR71XX_GPIO_REG_IN,
 			ctrl->base + AR71XX_GPIO_REG_IN,
 			ctrl->base + AR71XX_GPIO_REG_SET,
 			ctrl->base + AR71XX_GPIO_REG_SET,

+ 24 - 24
drivers/gpio/gpio-bcm-kona.c

@@ -67,7 +67,7 @@
 struct bcm_kona_gpio {
 struct bcm_kona_gpio {
 	void __iomem *reg_base;
 	void __iomem *reg_base;
 	int num_bank;
 	int num_bank;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	struct gpio_chip gpio_chip;
 	struct gpio_chip gpio_chip;
 	struct irq_domain *irq_domain;
 	struct irq_domain *irq_domain;
 	struct bcm_kona_gpio_bank *banks;
 	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;
 	unsigned long flags;
 	int bank_id = GPIO_BANK(gpio);
 	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 = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
 	val |= BIT(gpio);
 	val |= BIT(gpio);
 	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
 	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,
 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;
 	unsigned long flags;
 	int bank_id = GPIO_BANK(gpio);
 	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 = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
 	val &= ~BIT(gpio);
 	val &= ~BIT(gpio);
 	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
 	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)
 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);
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
 	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 */
 	/* this function only applies to output pin */
 	if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
 	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);
 	writel(val, reg_base + reg_offset);
 
 
 out:
 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)
 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);
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
 	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)
 	if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN)
 		reg_offset = GPIO_IN_STATUS(bank_id);
 		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 */
 	/* read the GPIO bank status */
 	val = readl(reg_base + reg_offset);
 	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 the specified bit status */
 	return !!(val & BIT(bit));
 	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);
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
 	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 = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
 	val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
 	val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
 	writel(val, reg_base + GPIO_CONTROL(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;
 	return 0;
 }
 }
@@ -232,7 +232,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
 
 
 	kona_gpio = gpiochip_get_data(chip);
 	kona_gpio = gpiochip_get_data(chip);
 	reg_base = kona_gpio->reg_base;
 	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 = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
 	val &= ~GPIO_GPCTR0_IOTR_MASK;
@@ -244,7 +244,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
 	val |= BIT(bit);
 	val |= BIT(bit);
 	writel(val, reg_base + reg_offset);
 	writel(val, reg_base + reg_offset);
 
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 
 	return 0;
 	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 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 = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_DBR_MASK;
 	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));
 	writel(val, reg_base + GPIO_CONTROL(gpio));
 
 
-	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
 
 
 	return 0;
 	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);
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
 	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 = readl(reg_base + GPIO_INT_STATUS(bank_id));
 	val |= BIT(bit);
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_STATUS(bank_id));
 	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)
 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);
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
 	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 = readl(reg_base + GPIO_INT_MASK(bank_id));
 	val |= BIT(bit);
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_MASK(bank_id));
 	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)
 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);
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
 	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 = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
 	val |= BIT(bit);
 	val |= BIT(bit);
 	writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
 	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)
 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;
 		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 = readl(reg_base + GPIO_CONTROL(gpio));
 	val &= ~GPIO_GPCTR0_ITR_MASK;
 	val &= ~GPIO_GPCTR0_ITR_MASK;
 	val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
 	val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
 	writel(val, reg_base + GPIO_CONTROL(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;
 	return 0;
 }
 }
@@ -655,7 +655,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
 						 bank);
 						 bank);
 	}
 	}
 
 
-	spin_lock_init(&kona_gpio->lock);
+	raw_spin_lock_init(&kona_gpio->lock);
 
 
 	return 0;
 	return 0;
 
 

+ 144 - 0
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");

+ 1 - 1
drivers/gpio/gpio-davinci.c

@@ -483,7 +483,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 	clk_prepare_enable(clk);
 	clk_prepare_enable(clk);
 
 
 	if (!pdata->gpio_unbanked) {
 	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) {
 		if (irq < 0) {
 			dev_err(dev, "Couldn't allocate IRQ numbers\n");
 			dev_err(dev, "Couldn't allocate IRQ numbers\n");
 			return irq;
 			return irq;

+ 75 - 18
drivers/gpio/gpio-dwapb.c

@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/property.h>
@@ -55,6 +56,14 @@
 #define GPIO_SWPORT_DR_SIZE	(GPIO_SWPORTB_DR - GPIO_SWPORTA_DR)
 #define GPIO_SWPORT_DR_SIZE	(GPIO_SWPORTB_DR - GPIO_SWPORTA_DR)
 #define GPIO_SWPORT_DDR_SIZE	(GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR)
 #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;
 struct dwapb_gpio;
 
 
 #ifdef CONFIG_PM_SLEEP
 #ifdef CONFIG_PM_SLEEP
@@ -87,14 +96,41 @@ struct dwapb_gpio {
 	struct dwapb_gpio_port	*ports;
 	struct dwapb_gpio_port	*ports;
 	unsigned int		nr_ports;
 	unsigned int		nr_ports;
 	struct irq_domain	*domain;
 	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)
 static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset)
 {
 {
 	struct gpio_chip *gc	= &gpio->ports[0].gc;
 	struct gpio_chip *gc	= &gpio->ports[0].gc;
 	void __iomem *reg_base	= gpio->regs;
 	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,
 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;
 	struct gpio_chip *gc	= &gpio->ports[0].gc;
 	void __iomem *reg_base	= gpio->regs;
 	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)
 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)
 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;
 	u32 ret = irq_status;
 
 
 	while (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_disable = dwapb_irq_disable;
 		ct->chip.irq_request_resources = dwapb_irq_reqres;
 		ct->chip.irq_request_resources = dwapb_irq_reqres;
 		ct->chip.irq_release_resources = dwapb_irq_relres;
 		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;
 		ct->type = IRQ_TYPE_LEVEL_MASK;
 	}
 	}
 
 
@@ -532,6 +568,21 @@ dwapb_gpio_get_pdata(struct device *dev)
 	return pdata;
 	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)
 static int dwapb_gpio_probe(struct platform_device *pdev)
 {
 {
 	unsigned int i;
 	unsigned int i;
@@ -567,6 +618,25 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(gpio->regs))
 	if (IS_ERR(gpio->regs))
 		return PTR_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++) {
 	for (i = 0; i < gpio->nr_ports; i++) {
 		err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
 		err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);
 		if (err)
 		if (err)
@@ -593,19 +663,6 @@ static int dwapb_gpio_remove(struct platform_device *pdev)
 	return 0;
 	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
 #ifdef CONFIG_PM_SLEEP
 static int dwapb_gpio_suspend(struct device *dev)
 static int dwapb_gpio_suspend(struct device *dev)
 {
 {

+ 12 - 12
drivers/gpio/gpio-etraxfs.c

@@ -54,7 +54,7 @@
 struct etraxfs_gpio_info;
 struct etraxfs_gpio_info;
 
 
 struct etraxfs_gpio_block {
 struct etraxfs_gpio_block {
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	u32 mask;
 	u32 mask;
 	u32 cfg;
 	u32 cfg;
 	u32 pins;
 	u32 pins;
@@ -233,10 +233,10 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d)
 	struct etraxfs_gpio_block *block = chip->block;
 	struct etraxfs_gpio_block *block = chip->block;
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->mask &= ~BIT(grpirq);
 	block->mask &= ~BIT(grpirq);
 	writel(block->mask, block->regs + block->info->rw_intr_mask);
 	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)
 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;
 	struct etraxfs_gpio_block *block = chip->block;
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->mask |= BIT(grpirq);
 	block->mask |= BIT(grpirq);
 	writel(block->mask, block->regs + block->info->rw_intr_mask);
 	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)
 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;
 		return -EINVAL;
 	}
 	}
 
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->cfg &= ~(0x7 << (grpirq * 3));
 	block->cfg &= ~(0x7 << (grpirq * 3));
 	block->cfg |= (cfg << (grpirq * 3));
 	block->cfg |= (cfg << (grpirq * 3));
 	writel(block->cfg, block->regs + block->info->rw_intr_cfg);
 	writel(block->cfg, block->regs + block->info->rw_intr_cfg);
-	spin_unlock(&block->lock);
+	raw_spin_unlock(&block->lock);
 
 
 	return 0;
 	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);
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 	int ret = -EBUSY;
 	int ret = -EBUSY;
 
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	if (block->group[grpirq])
 	if (block->group[grpirq])
 		goto out;
 		goto out;
 
 
@@ -316,7 +316,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
 	}
 	}
 
 
 out:
 out:
-	spin_unlock(&block->lock);
+	raw_spin_unlock(&block->lock);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -327,10 +327,10 @@ static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
 	struct etraxfs_gpio_block *block = chip->block;
 	struct etraxfs_gpio_block *block = chip->block;
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 	unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
 
 
-	spin_lock(&block->lock);
+	raw_spin_lock(&block->lock);
 	block->group[grpirq] = 0;
 	block->group[grpirq] = 0;
 	gpiochip_unlock_as_irq(&chip->gc, d->hwirq);
 	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 = {
 static struct irq_chip etraxfs_gpio_irq_chip = {
@@ -391,7 +391,7 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
 	if (!block)
 	if (!block)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	spin_lock_init(&block->lock);
+	raw_spin_lock_init(&block->lock);
 
 
 	block->regs = regs;
 	block->regs = regs;
 	block->info = info;
 	block->info = info;

+ 12 - 11
drivers/gpio/gpio-exar.c

@@ -59,17 +59,6 @@ static int exar_set_direction(struct gpio_chip *chip, int direction,
 	return 0;
 	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)
 static int exar_get(struct gpio_chip *chip, unsigned int reg)
 {
 {
 	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
 	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);
 	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)
 static int gpio_exar_probe(struct platform_device *pdev)
 {
 {
 	struct pci_dev *pcidev = platform_get_drvdata(pdev);
 	struct pci_dev *pcidev = platform_get_drvdata(pdev);

+ 22 - 2
drivers/gpio/gpio-f7188x.c

@@ -37,14 +37,16 @@
 #define SIO_F71869A_ID		0x1007	/* F71869A chipset ID */
 #define SIO_F71869A_ID		0x1007	/* F71869A chipset ID */
 #define SIO_F71882_ID		0x0541	/* F71882 chipset ID */
 #define SIO_F71882_ID		0x0541	/* F71882 chipset ID */
 #define SIO_F71889_ID		0x0909	/* F71889 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 */
 #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[] = {
 static const char * const f7188x_names[] = {
 	"f71869",
 	"f71869",
 	"f71869a",
 	"f71869a",
 	"f71882fg",
 	"f71882fg",
+	"f71889a",
 	"f71889f",
 	"f71889f",
 	"f81866",
 	"f81866",
 };
 };
@@ -187,6 +189,17 @@ static struct f7188x_gpio_bank f71882_gpio_bank[] = {
 	F7188X_GPIO_BANK(40, 4, 0xB0),
 	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[] = {
 static struct f7188x_gpio_bank f71889_gpio_bank[] = {
 	F7188X_GPIO_BANK(0, 7, 0xF0),
 	F7188X_GPIO_BANK(0, 7, 0xF0),
 	F7188X_GPIO_BANK(10, 7, 0xE0),
 	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->nr_bank = ARRAY_SIZE(f71882_gpio_bank);
 		data->bank = f71882_gpio_bank;
 		data->bank = f71882_gpio_bank;
 		break;
 		break;
+	case f71889a:
+		data->nr_bank = ARRAY_SIZE(f71889a_gpio_bank);
+		data->bank = f71889a_gpio_bank;
+		break;
 	case f71889f:
 	case f71889f:
 		data->nr_bank = ARRAY_SIZE(f71889_gpio_bank);
 		data->nr_bank = ARRAY_SIZE(f71889_gpio_bank);
 		data->bank = 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:
 	case SIO_F71882_ID:
 		sio->type = f71882fg;
 		sio->type = f71882fg;
 		break;
 		break;
+	case SIO_F71889A_ID:
+		sio->type = f71889a;
+		break;
 	case SIO_F71889_ID:
 	case SIO_F71889_ID:
 		sio->type = f71889f;
 		sio->type = f71889f;
 		break;
 		break;
@@ -538,6 +558,6 @@ static void __exit f7188x_gpio_exit(void)
 }
 }
 module_exit(f7188x_gpio_exit);
 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_AUTHOR("Simon Guinot <simon.guinot@sequanux.org>");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 39 - 33
drivers/gpio/gpio-gemini.c → 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>
  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
  *
  *
  * Based on arch/arm/mach-gemini/gpio.c:
  * Based on arch/arm/mach-gemini/gpio.c:
@@ -35,28 +35,28 @@
 #define GPIO_DEBOUNCE_PRESCALE	0x44
 #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
  * @dev: containing device for this instance
  * @gc: gpiochip for this instance
  * @gc: gpiochip for this instance
  */
  */
-struct gemini_gpio {
+struct ftgpio_gpio {
 	struct device *dev;
 	struct device *dev;
 	struct gpio_chip gc;
 	struct gpio_chip gc;
 	void __iomem *base;
 	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 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);
 	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 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;
 	u32 val;
 
 
 	val = readl(g->base + GPIO_INT_EN);
 	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);
 	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 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;
 	u32 val;
 
 
 	val = readl(g->base + GPIO_INT_EN);
 	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);
 	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 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 mask = BIT(irqd_to_hwirq(d));
 	u32 reg_both, reg_level, reg_type;
 	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_level, g->base + GPIO_INT_LEVEL);
 	writel(reg_both, g->base + GPIO_INT_BOTH_EDGE);
 	writel(reg_both, g->base + GPIO_INT_BOTH_EDGE);
 
 
-	gemini_gpio_ack_irq(d);
+	ftgpio_gpio_ack_irq(d);
 
 
 	return 0;
 	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 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);
 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
 	int offset;
 	int offset;
 	unsigned long stat;
 	unsigned long stat;
@@ -155,11 +155,11 @@ static void gemini_gpio_irq_handler(struct irq_desc *desc)
 	chained_irq_exit(irqchip, 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 device *dev = &pdev->dev;
 	struct resource *res;
 	struct resource *res;
-	struct gemini_gpio *g;
+	struct ftgpio_gpio *g;
 	int irq;
 	int irq;
 	int ret;
 	int ret;
 
 
@@ -189,7 +189,7 @@ static int gemini_gpio_probe(struct platform_device *pdev)
 		dev_err(dev, "unable to init generic GPIO\n");
 		dev_err(dev, "unable to init generic GPIO\n");
 		return ret;
 		return ret;
 	}
 	}
-	g->gc.label = "Gemini";
+	g->gc.label = "FTGPIO010";
 	g->gc.base = -1;
 	g->gc.base = -1;
 	g->gc.parent = dev;
 	g->gc.parent = dev;
 	g->gc.owner = THIS_MODULE;
 	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_MASK);
 	writel(~0x0, g->base + GPIO_INT_CLR);
 	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,
 				   0, handle_bad_irq,
 				   IRQ_TYPE_NONE);
 				   IRQ_TYPE_NONE);
 	if (ret) {
 	if (ret) {
 		dev_info(dev, "could not add irqchip\n");
 		dev_info(dev, "could not add irqchip\n");
 		return ret;
 		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;
 	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 = "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 = {
 	.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);

+ 1 - 1
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);
 	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,
 static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,

+ 7 - 21
drivers/gpio/gpio-ml-ioh.c

@@ -459,41 +459,31 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
 
 
 	chip = chip_save;
 	chip = chip_save;
 	for (j = 0; j < 8; j++, chip++) {
 	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) {
 		if (irq_base < 0) {
 			dev_warn(&pdev->dev,
 			dev_warn(&pdev->dev,
 				"ml_ioh_gpio: Failed to get IRQ base num\n");
 				"ml_ioh_gpio: Failed to get IRQ base num\n");
-			chip->irq_base = -1;
 			ret = irq_base;
 			ret = irq_base;
-			goto err_irq_alloc_descs;
+			goto err_gpiochip_add;
 		}
 		}
 		chip->irq_base = irq_base;
 		chip->irq_base = irq_base;
 		ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
 		ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]);
 	}
 	}
 
 
 	chip = chip_save;
 	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) {
 	if (ret != 0) {
 		dev_err(&pdev->dev,
 		dev_err(&pdev->dev,
 			"%s request_irq failed\n", __func__);
 			"%s request_irq failed\n", __func__);
-		goto err_request_irq;
+		goto err_gpiochip_add;
 	}
 	}
 
 
 	pci_set_drvdata(pdev, chip);
 	pci_set_drvdata(pdev, chip);
 
 
 	return 0;
 	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:
 err_gpiochip_add:
 	while (--i >= 0) {
 	while (--i >= 0) {
 		chip--;
 		chip--;
@@ -524,12 +514,8 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
 
 
 	chip_save = chip;
 	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);
 		gpiochip_remove(&chip->gpio);
-	}
 
 
 	chip = chip_save;
 	chip = chip_save;
 	pci_iounmap(pdev, chip->base);
 	pci_iounmap(pdev, chip->base);

+ 1 - 0
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[] = {
 static const struct of_device_id bgpio_of_match[] = {
 	{ .compatible = "brcm,bcm6345-gpio" },
 	{ .compatible = "brcm,bcm6345-gpio" },
 	{ .compatible = "wd,mbl-gpio" },
 	{ .compatible = "wd,mbl-gpio" },
+	{ .compatible = "ni,169445-nand-gpio" },
 	{ }
 	{ }
 };
 };
 MODULE_DEVICE_TABLE(of, bgpio_of_match);
 MODULE_DEVICE_TABLE(of, bgpio_of_match);

+ 1 - 15
drivers/gpio/gpio-mockup.c

@@ -169,7 +169,7 @@ static int gpio_mockup_irqchip_setup(struct device *dev,
 	struct gpio_chip *gc = &chip->gc;
 	struct gpio_chip *gc = &chip->gc;
 	int irq_base, i;
 	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)
 	if (irq_base < 0)
 		return irq_base;
 		return irq_base;
 
 
@@ -372,25 +372,11 @@ static int gpio_mockup_probe(struct platform_device *pdev)
 	return 0;
 	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 = {
 static struct platform_driver gpio_mockup_driver = {
 	.driver = {
 	.driver = {
 		.name = GPIO_MOCKUP_NAME,
 		.name = GPIO_MOCKUP_NAME,
 	},
 	},
 	.probe = gpio_mockup_probe,
 	.probe = gpio_mockup_probe,
-	.remove = gpio_mockup_remove,
 };
 };
 
 
 static struct platform_device *pdev;
 static struct platform_device *pdev;

+ 0 - 84
drivers/gpio/gpio-moxart.c

@@ -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);

+ 373 - 62
drivers/gpio/gpio-mvebu.c

@@ -42,29 +42,44 @@
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/of_irq.h>
 #include <linux/of_irq.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
+#include <linux/pwm.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+
+#include "gpiolib.h"
 
 
 /*
 /*
  * GPIO unit register offsets.
  * 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 */
 /* The MV78200 has per-CPU registers for edge mask and level mask */
 #define GPIO_EDGE_MASK_MV78200_OFF(cpu)	  ((cpu) ? 0x30 : 0x18)
 #define GPIO_EDGE_MASK_MV78200_OFF(cpu)	  ((cpu) ? 0x30 : 0x18)
 #define GPIO_LEVEL_MASK_MV78200_OFF(cpu)  ((cpu) ? 0x34 : 0x1C)
 #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
  * 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_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
 #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu)  (0x10 + (cpu) * 0x4)
 #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu)  (0x10 + (cpu) * 0x4)
 #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
 #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
@@ -75,6 +90,20 @@
 
 
 #define MVEBU_MAX_GPIO_PER_BANK		32
 #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 mvebu_gpio_chip {
 	struct gpio_chip   chip;
 	struct gpio_chip   chip;
 	spinlock_t	   lock;
 	spinlock_t	   lock;
@@ -84,48 +113,55 @@ struct mvebu_gpio_chip {
 	struct irq_domain *domain;
 	struct irq_domain *domain;
 	int		   soc_variant;
 	int		   soc_variant;
 
 
+	/* Used for PWM support */
+	struct clk	  *clk;
+	struct mvebu_pwm  *mvpwm;
+
 	/* Used to preserve GPIO registers across suspend/resume */
 	/* 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
  * Functions returning addresses of individual registers for a given
  * GPIO controller.
  * 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;
 	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;
 	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;
 	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;
 	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;
 	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;
 	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;
 	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);
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	unsigned long flags;
 	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);
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_out(mvchip));
 	u = readl_relaxed(mvebu_gpioreg_out(mvchip));
 	if (value)
 	if (value)
-		u |= 1 << pin;
+		u |= BIT(pin);
 	else
 	else
-		u &= ~(1 << pin);
+		u &= ~BIT(pin);
 	writel_relaxed(u, mvebu_gpioreg_out(mvchip));
 	writel_relaxed(u, mvebu_gpioreg_out(mvchip));
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 	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);
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	u32 u;
 	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)) ^
 		u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
 			readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
 			readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
 	} else {
 	} else {
@@ -216,7 +264,8 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
 	return (u >> pin) & 1;
 	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);
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	unsigned long flags;
 	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);
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
 	u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
 	if (value)
 	if (value)
-		u |= 1 << pin;
+		u |= BIT(pin);
 	else
 	else
-		u &= ~(1 << pin);
+		u &= ~BIT(pin);
 	writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
 	writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 	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);
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	unsigned long flags;
 	unsigned long flags;
 	int ret;
 	int ret;
 	u32 u;
 	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);
 	ret = pinctrl_gpio_direction_input(chip->base + pin);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
 	spin_lock_irqsave(&mvchip->lock, flags);
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
 	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
-	u |= 1 << pin;
+	u |= BIT(pin);
 	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
 	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 
 
 	return 0;
 	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)
 				       int value)
 {
 {
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
 	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;
 	int ret;
 	u32 u;
 	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);
 	ret = pinctrl_gpio_direction_output(chip->base + pin);
 	if (ret)
 	if (ret)
 		return 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);
 	spin_lock_irqsave(&mvchip->lock, flags);
 	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
 	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
-	u &= ~(1 << pin);
+	u &= ~BIT(pin);
 	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
 	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 	spin_unlock_irqrestore(&mvchip->lock, flags);
 
 
 	return 0;
 	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);
 	struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
+
 	return irq_create_mapping(mvchip->domain, pin);
 	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;
 	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)
 	if (!u)
 		return -EINVAL;
 		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_EDGE_RISING:
 	case IRQ_TYPE_LEVEL_HIGH:
 	case IRQ_TYPE_LEVEL_HIGH:
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
-		u &= ~(1 << pin);
+		u &= ~BIT(pin);
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		break;
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
 	case IRQ_TYPE_EDGE_FALLING:
 	case IRQ_TYPE_LEVEL_LOW:
 	case IRQ_TYPE_LEVEL_LOW:
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
-		u |= 1 << pin;
+		u |= BIT(pin);
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		break;
 		break;
 	case IRQ_TYPE_EDGE_BOTH: {
 	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
 		 * set initial polarity based on current input level
 		 */
 		 */
 		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
 		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
 		else
-			u &= ~(1 << pin);	/* rising */
+			u &= ~BIT(pin);		/* rising */
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
 		break;
 		break;
 	}
 	}
@@ -461,7 +515,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
 
 
 		irq = irq_find_mapping(mvchip->domain, i);
 		irq = irq_find_mapping(mvchip->domain, i);
 
 
-		if (!(cause & (1 << i)))
+		if (!(cause & BIT(i)))
 			continue;
 			continue;
 
 
 		type = irq_get_trigger_type(irq);
 		type = irq_get_trigger_type(irq);
@@ -470,7 +524,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
 			u32 polarity;
 			u32 polarity;
 
 
 			polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
 			polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
-			polarity ^= 1 << i;
+			polarity ^= BIT(i);
 			writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
 			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);
 	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
 #ifdef CONFIG_DEBUG_FS
 #include <linux/seq_file.h>
 #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)
 		if (!label)
 			continue;
 			continue;
 
 
-		msk = 1 << i;
+		msk = BIT(i);
 		is_out = !(io_conf & msk);
 		is_out = !(io_conf & msk);
 
 
 		seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label);
 		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",
 		.compatible = "marvell,armadaxp-gpio",
 		.data	    = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
 		.data	    = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
 	},
 	},
+	{
+		.compatible = "marvell,armada-370-xp-gpio",
+		.data	    = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
+	},
 	{
 	{
 		/* sentinel */
 		/* sentinel */
 	},
 	},
@@ -596,6 +894,9 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
 		BUG();
 		BUG();
 	}
 	}
 
 
+	if (IS_ENABLED(CONFIG_PWM))
+		mvebu_pwm_suspend(mvchip);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -639,6 +940,9 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
 		BUG();
 		BUG();
 	}
 	}
 
 
+	if (IS_ENABLED(CONFIG_PWM))
+		mvebu_pwm_resume(mvchip);
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -650,7 +954,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct resource *res;
 	struct irq_chip_generic *gc;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 	struct irq_chip_type *ct;
-	struct clk *clk;
 	unsigned int ngpios;
 	unsigned int ngpios;
 	bool have_irqs;
 	bool have_irqs;
 	int soc_variant;
 	int soc_variant;
@@ -684,10 +987,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 		return id;
 		return id;
 	}
 	}
 
 
-	clk = devm_clk_get(&pdev->dev, NULL);
+	mvchip->clk = devm_clk_get(&pdev->dev, NULL);
 	/* Not all SoCs require a clock.*/
 	/* 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->soc_variant = soc_variant;
 	mvchip->chip.label = dev_name(&pdev->dev);
 	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))
 	if (IS_ERR(mvchip->membase))
 		return PTR_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) {
 	if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
 		mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev,
@@ -780,7 +1085,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 		goto err_domain;
 		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
 	 * access to the mask registers
 	 */
 	 */
 	gc = irq_get_domain_generic_chip(mvchip->domain, 0);
 	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->handler = handle_edge_irq;
 	ct->chip.name = mvchip->chip.label;
 	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
 	 * interrupt handlers, with each handler dealing with 8 GPIO
 	 * pins.
 	 * pins.
 	 */
 	 */
@@ -814,6 +1121,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 						 mvchip);
 						 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;
 	return 0;
 
 
 err_domain:
 err_domain:

+ 2 - 4
drivers/gpio/gpio-mxc.c

@@ -471,7 +471,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 	if (err)
 	if (err)
 		goto out_bgio;
 		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) {
 	if (irq_base < 0) {
 		err = irq_base;
 		err = irq_base;
 		goto out_bgio;
 		goto out_bgio;
@@ -481,7 +481,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 					     &irq_domain_simple_ops, NULL);
 					     &irq_domain_simple_ops, NULL);
 	if (!port->domain) {
 	if (!port->domain) {
 		err = -ENODEV;
 		err = -ENODEV;
-		goto out_irqdesc_free;
+		goto out_bgio;
 	}
 	}
 
 
 	/* gpio-mxc can be a generic irq chip */
 	/* gpio-mxc can be a generic irq chip */
@@ -495,8 +495,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 
 
 out_irqdomain_remove:
 out_irqdomain_remove:
 	irq_domain_remove(port->domain);
 	irq_domain_remove(port->domain);
-out_irqdesc_free:
-	irq_free_descs(irq_base, 32);
 out_bgio:
 out_bgio:
 	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
 	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
 	return err;
 	return err;

+ 2 - 4
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 */
 	/* clear address has to be used to clear IRQSTAT bits */
 	writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
 	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) {
 	if (irq_base < 0) {
 		err = irq_base;
 		err = irq_base;
 		goto out_iounmap;
 		goto out_iounmap;
@@ -338,7 +338,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 					     &irq_domain_simple_ops, NULL);
 					     &irq_domain_simple_ops, NULL);
 	if (!port->domain) {
 	if (!port->domain) {
 		err = -ENODEV;
 		err = -ENODEV;
-		goto out_irqdesc_free;
+		goto out_iounmap;
 	}
 	}
 
 
 	/* gpio-mxs can be a generic irq chip */
 	/* gpio-mxs can be a generic irq chip */
@@ -370,8 +370,6 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 
 
 out_irqdomain_remove:
 out_irqdomain_remove:
 	irq_domain_remove(port->domain);
 	irq_domain_remove(port->domain);
-out_irqdesc_free:
-	irq_free_descs(irq_base, 32);
 out_iounmap:
 out_iounmap:
 	iounmap(port->base);
 	iounmap(port->base);
 	return err;
 	return err;

+ 19 - 7
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
  * OMAP's debounce time is in 31us steps
  *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
  *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
  * so we need to convert and round up to the closest unit.
  * 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;
 	void __iomem		*reg;
 	u32			val;
 	u32			val;
@@ -218,11 +220,12 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
 	bool			enable = !!debounce;
 	bool			enable = !!debounce;
 
 
 	if (!bank->dbck_flag)
 	if (!bank->dbck_flag)
-		return;
+		return -ENOTSUPP;
 
 
 	if (enable) {
 	if (enable) {
 		debounce = DIV_ROUND_UP(debounce, 31) - 1;
 		debounce = DIV_ROUND_UP(debounce, 31) - 1;
-		debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
+		if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce)
+			return -EINVAL;
 	}
 	}
 
 
 	l = BIT(offset);
 	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 = debounce;
 		bank->context.debounce_en = val;
 		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;
 	struct gpio_bank *bank;
 	unsigned long flags;
 	unsigned long flags;
+	int ret;
 
 
 	bank = gpiochip_get_data(chip);
 	bank = gpiochip_get_data(chip);
 
 
 	raw_spin_lock_irqsave(&bank->lock, flags);
 	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);
 	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,
 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
 	 * 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_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) {
 	if (irq_base < 0) {
 		dev_err(bank->chip.parent, "Couldn't allocate IRQ numbers\n");
 		dev_err(bank->chip.parent, "Couldn't allocate IRQ numbers\n");
 		return -ENODEV;
 		return -ENODEV;

+ 31 - 7
drivers/gpio/gpio-pca953x.c

@@ -11,18 +11,19 @@
  *  the Free Software Foundation; version 2 of the License.
  *  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.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/consumer.h>
-#include <linux/interrupt.h>
 #include <linux/i2c.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/platform_data/pca953x.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+
 #include <asm/unaligned.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_INPUT		0
 #define PCA953X_OUTPUT		1
 #define PCA953X_OUTPUT		1
@@ -81,6 +82,7 @@ static const struct i2c_device_id pca953x_id[] = {
 	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
 	{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
 	{ "tca9539", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "tca9539", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "tca9554", 8  | PCA953X_TYPE | PCA_INT, },
 	{ "xra1202", 8  | PCA953X_TYPE },
 	{ "xra1202", 8  | PCA953X_TYPE },
 	{ }
 	{ }
 };
 };
@@ -363,6 +365,21 @@ exit:
 	mutex_unlock(&chip->i2c_lock);
 	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,
 static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
 				      unsigned long *mask, unsigned long *bits)
 				      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->direction_output = pca953x_gpio_direction_output;
 	gc->get = pca953x_gpio_get_value;
 	gc->get = pca953x_gpio_get_value;
 	gc->set = pca953x_gpio_set_value;
 	gc->set = pca953x_gpio_set_value;
+	gc->get_direction = pca953x_gpio_get_direction;
 	gc->set_multiple = pca953x_gpio_set_multiple;
 	gc->set_multiple = pca953x_gpio_set_multiple;
 	gc->can_sleep = true;
 	gc->can_sleep = true;
 
 
@@ -760,7 +778,13 @@ static int pca953x_probe(struct i2c_client *client,
 		chip->gpio_start = -1;
 		chip->gpio_start = -1;
 		irq_base = 0;
 		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",
 		reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
 						     GPIOD_OUT_LOW);
 						     GPIOD_OUT_LOW);
 		if (IS_ERR(reset_gpio))
 		if (IS_ERR(reset_gpio))

+ 0 - 2
drivers/gpio/gpio-pcf857x.c

@@ -46,7 +46,6 @@ static const struct i2c_device_id pcf857x_id[] = {
 	{ "pca9675", 16 },
 	{ "pca9675", 16 },
 	{ "max7328", 8 },
 	{ "max7328", 8 },
 	{ "max7329", 8 },
 	{ "max7329", 8 },
-	{ "tca9554", 8 },
 	{ }
 	{ }
 };
 };
 MODULE_DEVICE_TABLE(i2c, pcf857x_id);
 MODULE_DEVICE_TABLE(i2c, pcf857x_id);
@@ -66,7 +65,6 @@ static const struct of_device_id pcf857x_of_table[] = {
 	{ .compatible = "nxp,pca9675" },
 	{ .compatible = "nxp,pca9675" },
 	{ .compatible = "maxim,max7328" },
 	{ .compatible = "maxim,max7328" },
 	{ .compatible = "maxim,max7329" },
 	{ .compatible = "maxim,max7329" },
-	{ .compatible = "ti,tca9554" },
 	{ }
 	{ }
 };
 };
 MODULE_DEVICE_TABLE(of, pcf857x_of_table);
 MODULE_DEVICE_TABLE(of, pcf857x_of_table);

+ 4 - 10
drivers/gpio/gpio-pch.c

@@ -403,7 +403,8 @@ static int pch_gpio_probe(struct pci_dev *pdev,
 		goto err_gpiochip_add;
 		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) {
 	if (irq_base < 0) {
 		dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
 		dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
 		chip->irq_base = -1;
 		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->imask);
 	iowrite32(msk, &chip->reg->ien);
 	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) {
 	if (ret != 0) {
 		dev_err(&pdev->dev,
 		dev_err(&pdev->dev,
 			"%s request_irq failed\n", __func__);
 			"%s request_irq failed\n", __func__);
@@ -430,7 +431,6 @@ end:
 	return 0;
 	return 0;
 
 
 err_request_irq:
 err_request_irq:
-	irq_free_descs(irq_base, gpio_pins[chip->ioh]);
 	gpiochip_remove(&chip->gpio);
 	gpiochip_remove(&chip->gpio);
 
 
 err_gpiochip_add:
 err_gpiochip_add:
@@ -452,12 +452,6 @@ static void pch_gpio_remove(struct pci_dev *pdev)
 {
 {
 	struct pch_gpio *chip = pci_get_drvdata(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);
 	gpiochip_remove(&chip->gpio);
 	pci_iounmap(pdev, chip->base);
 	pci_iounmap(pdev, chip->base);
 	pci_release_regions(pdev);
 	pci_release_regions(pdev);

+ 14 - 14
drivers/gpio/gpio-pci-idio-16.c

@@ -59,7 +59,7 @@ struct idio_16_gpio_reg {
  */
  */
 struct idio_16_gpio {
 struct idio_16_gpio {
 	struct gpio_chip chip;
 	struct gpio_chip chip;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	struct idio_16_gpio_reg __iomem *reg;
 	struct idio_16_gpio_reg __iomem *reg;
 	unsigned long irq_mask;
 	unsigned long irq_mask;
 };
 };
@@ -121,7 +121,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	} else
 	} else
 		base = &idio16gpio->reg->out0_7;
 		base = &idio16gpio->reg->out0_7;
 
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 	if (value)
 	if (value)
 		out_state = ioread8(base) | mask;
 		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);
 	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,
 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 long flags;
 	unsigned int out_state;
 	unsigned int out_state;
 
 
-	spin_lock_irqsave(&idio16gpio->lock, flags);
+	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 	/* process output lines 0-7 */
 	/* process output lines 0-7 */
 	if (*mask & 0xFF) {
 	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);
 		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)
 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;
 	idio16gpio->irq_mask &= ~mask;
 
 
 	if (!idio16gpio->irq_mask) {
 	if (!idio16gpio->irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 		iowrite8(0, &idio16gpio->reg->irq_ctl);
 		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;
 	idio16gpio->irq_mask |= mask;
 
 
 	if (!prev_irq_mask) {
 	if (!prev_irq_mask) {
-		spin_lock_irqsave(&idio16gpio->lock, flags);
+		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
 
 
 		ioread8(&idio16gpio->reg->irq_ctl);
 		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;
 	struct gpio_chip *const chip = &idio16gpio->chip;
 	int gpio;
 	int gpio;
 
 
-	spin_lock(&idio16gpio->lock);
+	raw_spin_lock(&idio16gpio->lock);
 
 
 	irq_status = ioread8(&idio16gpio->reg->irq_status);
 	irq_status = ioread8(&idio16gpio->reg->irq_status);
 
 
-	spin_unlock(&idio16gpio->lock);
+	raw_spin_unlock(&idio16gpio->lock);
 
 
 	/* Make sure our device generated IRQ */
 	/* Make sure our device generated IRQ */
 	if (!(irq_status & 0x3) || !(irq_status & 0x4))
 	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)
 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
 		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
 		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
 
 
-	spin_lock(&idio16gpio->lock);
+	raw_spin_lock(&idio16gpio->lock);
 
 
 	/* Clear interrupt */
 	/* Clear interrupt */
 	iowrite8(0, &idio16gpio->reg->in0_7);
 	iowrite8(0, &idio16gpio->reg->in0_7);
 
 
-	spin_unlock(&idio16gpio->lock);
+	raw_spin_unlock(&idio16gpio->lock);
 
 
 	return IRQ_HANDLED;
 	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 = idio_16_gpio_set;
 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
 	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);
 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
 	if (err) {
 	if (err) {

+ 14 - 14
drivers/gpio/gpio-pl061.c

@@ -50,7 +50,7 @@ struct pl061_context_save_regs {
 #endif
 #endif
 
 
 struct pl061 {
 struct pl061 {
-	spinlock_t		lock;
+	raw_spinlock_t		lock;
 
 
 	void __iomem		*base;
 	void __iomem		*base;
 	struct gpio_chip	gc;
 	struct gpio_chip	gc;
@@ -74,11 +74,11 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
 	unsigned long flags;
 	unsigned long flags;
 	unsigned char gpiodir;
 	unsigned char gpiodir;
 
 
-	spin_lock_irqsave(&pl061->lock, flags);
+	raw_spin_lock_irqsave(&pl061->lock, flags);
 	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir &= ~(BIT(offset));
 	gpiodir &= ~(BIT(offset));
 	writeb(gpiodir, pl061->base + GPIODIR);
 	writeb(gpiodir, pl061->base + GPIODIR);
-	spin_unlock_irqrestore(&pl061->lock, flags);
+	raw_spin_unlock_irqrestore(&pl061->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -90,7 +90,7 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
 	unsigned long flags;
 	unsigned long flags;
 	unsigned char gpiodir;
 	unsigned char gpiodir;
 
 
-	spin_lock_irqsave(&pl061->lock, flags);
+	raw_spin_lock_irqsave(&pl061->lock, flags);
 	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
 	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
 	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir |= BIT(offset);
 	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.
 	 * a gpio pin before configuring it in OUT mode.
 	 */
 	 */
 	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
 	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
-	spin_unlock_irqrestore(&pl061->lock, flags);
+	raw_spin_unlock_irqrestore(&pl061->lock, flags);
 
 
 	return 0;
 	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);
 	gpioiev = readb(pl061->base + GPIOIEV);
 	gpiois = readb(pl061->base + GPIOIS);
 	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(gpioibe, pl061->base + GPIOIBE);
 	writeb(gpioiev, pl061->base + GPIOIEV);
 	writeb(gpioiev, pl061->base + GPIOIEV);
 
 
-	spin_unlock_irqrestore(&pl061->lock, flags);
+	raw_spin_unlock_irqrestore(&pl061->lock, flags);
 
 
 	return 0;
 	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 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 	u8 gpioie;
 	u8 gpioie;
 
 
-	spin_lock(&pl061->lock);
+	raw_spin_lock(&pl061->lock);
 	gpioie = readb(pl061->base + GPIOIE) & ~mask;
 	gpioie = readb(pl061->base + GPIOIE) & ~mask;
 	writeb(gpioie, pl061->base + GPIOIE);
 	writeb(gpioie, pl061->base + GPIOIE);
-	spin_unlock(&pl061->lock);
+	raw_spin_unlock(&pl061->lock);
 }
 }
 
 
 static void pl061_irq_unmask(struct irq_data *d)
 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 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 	u8 gpioie;
 	u8 gpioie;
 
 
-	spin_lock(&pl061->lock);
+	raw_spin_lock(&pl061->lock);
 	gpioie = readb(pl061->base + GPIOIE) | mask;
 	gpioie = readb(pl061->base + GPIOIE) | mask;
 	writeb(gpioie, pl061->base + GPIOIE);
 	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);
 	struct pl061 *pl061 = gpiochip_get_data(gc);
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 
 
-	spin_lock(&pl061->lock);
+	raw_spin_lock(&pl061->lock);
 	writeb(mask, pl061->base + GPIOIC);
 	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)
 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))
 	if (IS_ERR(pl061->base))
 		return PTR_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")) {
 	if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
 		pl061->gc.request = gpiochip_generic_request;
 		pl061->gc.request = gpiochip_generic_request;
 		pl061->gc.free = gpiochip_generic_free;
 		pl061->gc.free = gpiochip_generic_free;

+ 1 - 1
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;
 	nr_gpios = gpio_id->gpio_nums;
 	pxa_last_gpio = nr_gpios - 1;
 	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) {
 	if (irq_base < 0) {
 		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
 		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
 		return irq_base;
 		return irq_base;

+ 185 - 0
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;
+}

+ 139 - 77
drivers/gpio/gpio-sa1100.c

@@ -12,57 +12,97 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/syscore_ops.h>
 #include <linux/syscore_ops.h>
+#include <soc/sa1100/pwer.h>
 #include <mach/hardware.h>
 #include <mach/hardware.h>
 #include <mach/irqs.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)
 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)
 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)
 static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset)
 {
 {
+	void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR;
 	unsigned long flags;
 	unsigned long flags;
 
 
 	local_irq_save(flags);
 	local_irq_save(flags);
-	GPDR &= ~GPIO_GPIO(offset);
+	writel_relaxed(readl_relaxed(gpdr) & ~BIT(offset), gpdr);
 	local_irq_restore(flags);
 	local_irq_restore(flags);
+
 	return 0;
 	return 0;
 }
 }
 
 
 static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 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;
 	unsigned long flags;
 
 
 	local_irq_save(flags);
 	local_irq_save(flags);
 	sa1100_gpio_set(chip, offset, value);
 	sa1100_gpio_set(chip, offset, value);
-	GPDR |= GPIO_GPIO(offset);
+	writel_relaxed(readl_relaxed(gpdr) | BIT(offset), gpdr);
 	local_irq_restore(flags);
 	local_irq_restore(flags);
+
 	return 0;
 	return 0;
 }
 }
 
 
 static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset)
 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.
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
  * Use this instead of directly setting GRER/GFER.
  * 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)
 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 (type == IRQ_TYPE_PROBE) {
-		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
+		if ((sgc->irqrising | sgc->irqfalling) & mask)
 			return 0;
 			return 0;
 		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
 		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
 	}
 	}
 
 
 	if (type & IRQ_TYPE_EDGE_RISING)
 	if (type & IRQ_TYPE_EDGE_RISING)
-		GPIO_IRQ_rising_edge |= mask;
+		sgc->irqrising |= mask;
 	else
 	else
-		GPIO_IRQ_rising_edge &= ~mask;
+		sgc->irqrising &= ~mask;
 	if (type & IRQ_TYPE_EDGE_FALLING)
 	if (type & IRQ_TYPE_EDGE_FALLING)
-		GPIO_IRQ_falling_edge |= mask;
+		sgc->irqfalling |= mask;
 	else
 	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;
 	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)
 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)
 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);
 	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)
 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);
 	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)
 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,
 static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
 		unsigned int irq, irq_hw_number_t hwirq)
 		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);
 	irq_set_probe(irq);
 
 
 	return 0;
 	return 0;
@@ -174,17 +228,19 @@ static struct irq_domain *sa1100_gpio_irqdomain;
  */
  */
 static void sa1100_gpio_handler(struct irq_desc *desc)
 static void sa1100_gpio_handler(struct irq_desc *desc)
 {
 {
+	struct sa1100_gpio_chip *sgc = irq_desc_get_handler_data(desc);
 	unsigned int irq, mask;
 	unsigned int irq, mask;
+	void __iomem *gedr = sgc->membase + R_GEDR;
 
 
-	mask = GEDR;
+	mask = readl_relaxed(gedr);
 	do {
 	do {
 		/*
 		/*
 		 * clear down all currently active IRQ sources.
 		 * clear down all currently active IRQ sources.
 		 * We will be processing them all.
 		 * We will be processing them all.
 		 */
 		 */
-		GEDR = mask;
+		writel_relaxed(mask, gedr);
 
 
-		irq = IRQ_GPIO0;
+		irq = sgc->irqbase;
 		do {
 		do {
 			if (mask & 1)
 			if (mask & 1)
 				generic_handle_irq(irq);
 				generic_handle_irq(irq);
@@ -192,30 +248,32 @@ static void sa1100_gpio_handler(struct irq_desc *desc)
 			irq++;
 			irq++;
 		} while (mask);
 		} while (mask);
 
 
-		mask = GEDR;
+		mask = readl_relaxed(gedr);
 	} while (mask);
 	} while (mask);
 }
 }
 
 
 static int sa1100_gpio_suspend(void)
 static int sa1100_gpio_suspend(void)
 {
 {
+	struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip;
+
 	/*
 	/*
 	 * Set the appropriate edges for wakeup.
 	 * 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.
 	 * Clear any pending GPIO interrupts.
 	 */
 	 */
-	GEDR = GEDR;
+	writel_relaxed(readl_relaxed(sgc->membase + R_GEDR),
+		       sgc->membase + R_GEDR);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
 static void sa1100_gpio_resume(void)
 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 = {
 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);
 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)
 void __init sa1100_init_gpio(void)
 {
 {
+	struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip;
+	int i;
+
 	/* clear all GPIO edge detects */
 	/* 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,
 	sa1100_gpio_irqdomain = irq_domain_add_simple(NULL,
 			28, IRQ_GPIO0,
 			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);
 }
 }

+ 11 - 17
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;
 	struct irq_chip_type *ct;
 	int ret;
 	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)
 	if (sd->irq_base < 0)
 		return sd->irq_base;
 		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(0, sd->gpio_pub_base + GPIO_INT);
 	writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR);
 	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)
 	if (ret)
-		goto out_free_desc;
+		return ret;
 
 
 	/*
 	/*
 	 * This gpio irq controller latches level irqs. Testing shows that if
 	 * 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->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base,
 			sd->gpio_pub_base, handle_fasteoi_irq);
 			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;
 	sd->gc->private = sd;
 	ct = sd->gc->chip_types;
 	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->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS,
 				sd->irq_base, 0, &irq_domain_sdv_ops, sd);
 				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;
 	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,
 static int sdv_gpio_probe(struct pci_dev *pdev,

+ 6 - 11
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]);
 			gsta_set_config(chip, i, gpio_pdata->pinconfig[i]);
 
 
 	/* 384 was used in previous code: be compatible for other drivers */
 	/* 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) {
 	if (err < 0) {
 		dev_warn(&dev->dev, "sta2x11 gpio: Can't get irq base (%i)\n",
 		dev_warn(&dev->dev, "sta2x11 gpio: Can't get irq base (%i)\n",
 			 -err);
 			 -err);
@@ -401,29 +402,23 @@ static int gsta_probe(struct platform_device *dev)
 	chip->irq_base = err;
 	chip->irq_base = err;
 	gsta_alloc_irq_chip(chip);
 	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) {
 	if (err < 0) {
 		dev_err(&dev->dev, "sta2x11 gpio: Can't request irq (%i)\n",
 		dev_err(&dev->dev, "sta2x11 gpio: Can't request irq (%i)\n",
 			-err);
 			-err);
-		goto err_free_descs;
+		return err;
 	}
 	}
 
 
 	err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip);
 	err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip);
 	if (err < 0) {
 	if (err < 0) {
 		dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n",
 		dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n",
 			-err);
 			-err);
-		goto err_free_irq;
+		return err;
 	}
 	}
 
 
 	platform_set_drvdata(dev, chip);
 	platform_set_drvdata(dev, chip);
 	return 0;
 	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 = {
 static struct platform_driver sta2x11_gpio_platform_driver = {

+ 2 - 1
drivers/gpio/gpio-twl4030.c

@@ -485,7 +485,8 @@ static int gpio_twl4030_probe(struct platform_device *pdev)
 		goto no_irqs;
 		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) {
 	if (irq_base < 0) {
 		dev_err(&pdev->dev, "Failed to alloc irq_descs\n");
 		dev_err(&pdev->dev, "Failed to alloc irq_descs\n");
 		return irq_base;
 		return irq_base;

+ 5 - 3
drivers/gpio/gpio-wcove.c

@@ -51,6 +51,8 @@
 #define GROUP1_NR_IRQS		6
 #define GROUP1_NR_IRQS		6
 #define IRQ_MASK_BASE		0x4e19
 #define IRQ_MASK_BASE		0x4e19
 #define IRQ_STATUS_BASE		0x4e0b
 #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_TYPE		BIT(0)
 #define UPDATE_IRQ_MASK		BIT(1)
 #define UPDATE_IRQ_MASK		BIT(1)
 
 
@@ -309,7 +311,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
 		return IRQ_NONE;
 		return IRQ_NONE;
 	}
 	}
 
 
-	pending = p[0] | (p[1] << 8);
+	pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
 	if (!pending)
 	if (!pending)
 		return IRQ_NONE;
 		return IRQ_NONE;
 
 
@@ -317,7 +319,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
 	while (pending) {
 	while (pending) {
 		/* One iteration is for all pending bits */
 		/* One iteration is for all pending bits */
 		for_each_set_bit(gpio, (const unsigned long *)&pending,
 		for_each_set_bit(gpio, (const unsigned long *)&pending,
-						 GROUP0_NR_IRQS) {
+						 WCOVE_GPIO_NUM) {
 			offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0;
 			offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0;
 			mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) :
 			mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) :
 								BIT(gpio);
 								BIT(gpio);
@@ -333,7 +335,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
 			break;
 			break;
 		}
 		}
 
 
-		pending = p[0] | (p[1] << 8);
+		pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7);
 	}
 	}
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;

+ 23 - 23
drivers/gpio/gpio-ws16c48.c

@@ -51,7 +51,7 @@ struct ws16c48_gpio {
 	struct gpio_chip chip;
 	struct gpio_chip chip;
 	unsigned char io_state[6];
 	unsigned char io_state[6];
 	unsigned char out_state[6];
 	unsigned char out_state[6];
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned long irq_mask;
 	unsigned long irq_mask;
 	unsigned long flow_mask;
 	unsigned long flow_mask;
 	unsigned base;
 	unsigned base;
@@ -73,13 +73,13 @@ static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	const unsigned mask = BIT(offset % 8);
 	const unsigned mask = BIT(offset % 8);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	ws16c48gpio->io_state[port] |= mask;
 	ws16c48gpio->io_state[port] |= mask;
 	ws16c48gpio->out_state[port] &= ~mask;
 	ws16c48gpio->out_state[port] &= ~mask;
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -92,7 +92,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip,
 	const unsigned mask = BIT(offset % 8);
 	const unsigned mask = BIT(offset % 8);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	ws16c48gpio->io_state[port] &= ~mask;
 	ws16c48gpio->io_state[port] &= ~mask;
 	if (value)
 	if (value)
@@ -101,7 +101,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip,
 		ws16c48gpio->out_state[port] &= ~mask;
 		ws16c48gpio->out_state[port] &= ~mask;
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -114,17 +114,17 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset)
 	unsigned long flags;
 	unsigned long flags;
 	unsigned port_state;
 	unsigned port_state;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	/* ensure that GPIO is set for input */
 	/* ensure that GPIO is set for input */
 	if (!(ws16c48gpio->io_state[port] & mask)) {
 	if (!(ws16c48gpio->io_state[port] & mask)) {
-		spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
 	port_state = inb(ws16c48gpio->base + port);
 	port_state = inb(ws16c48gpio->base + port);
 
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 
 	return !!(port_state & mask);
 	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);
 	const unsigned mask = BIT(offset % 8);
 	unsigned long flags;
 	unsigned long flags;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	/* ensure that GPIO is set for output */
 	/* ensure that GPIO is set for output */
 	if (ws16c48gpio->io_state[port] & mask) {
 	if (ws16c48gpio->io_state[port] & mask) {
-		spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 		return;
 		return;
 	}
 	}
 
 
@@ -150,7 +150,7 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 		ws16c48gpio->out_state[port] &= ~mask;
 		ws16c48gpio->out_state[port] &= ~mask;
 	outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 	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,
 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];
 		iomask = mask[BIT_WORD(i)] & ~ws16c48gpio->io_state[port];
 		bitmask = iomask & bits[BIT_WORD(i)];
 		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 */
 		/* update output state data and set device gpio register */
 		ws16c48gpio->out_state[port] &= ~iomask;
 		ws16c48gpio->out_state[port] &= ~iomask;
 		ws16c48gpio->out_state[port] |= bitmask;
 		ws16c48gpio->out_state[port] |= bitmask;
 		outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
 		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 */
 		/* prepare for next gpio register set */
 		mask[BIT_WORD(i)] >>= gpio_reg_size;
 		mask[BIT_WORD(i)] >>= gpio_reg_size;
@@ -207,7 +207,7 @@ static void ws16c48_irq_ack(struct irq_data *data)
 	if (port > 2)
 	if (port > 2)
 		return;
 		return;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	port_state = ws16c48gpio->irq_mask >> (8*port);
 	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(port_state | mask, ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 	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)
 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)
 	if (port > 2)
 		return;
 		return;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	ws16c48gpio->irq_mask &= ~mask;
 	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(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 	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)
 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)
 	if (port > 2)
 		return;
 		return;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	ws16c48gpio->irq_mask |= mask;
 	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(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 	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)
 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)
 	if (port > 2)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	spin_lock_irqsave(&ws16c48gpio->lock, flags);
+	raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
 
 
 	switch (flow_type) {
 	switch (flow_type) {
 	case IRQ_TYPE_NONE:
 	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;
 		ws16c48gpio->flow_mask &= ~mask;
 		break;
 		break;
 	default:
 	default:
-		spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 		return -EINVAL;
 		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(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port);
 	outb(0xC0, ws16c48gpio->base + 7);
 	outb(0xC0, ws16c48gpio->base + 7);
 
 
-	spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
 
 
 	return 0;
 	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->chip.set_multiple = ws16c48_gpio_set_multiple;
 	ws16c48gpio->base = base[id];
 	ws16c48gpio->base = base[id];
 
 
-	spin_lock_init(&ws16c48gpio->lock);
+	raw_spin_lock_init(&ws16c48gpio->lock);
 
 
 	err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio);
 	err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio);
 	if (err) {
 	if (err) {

+ 5 - 4
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 */
 	/* XLP(MIPS) has fixed range for GPIO IRQs, Vulcan(ARM64) does not */
 	if (soc_type != GPIO_VARIANT_VULCAN) {
 	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) {
 		if (irq_base < 0) {
 			dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
 			dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
 			return irq_base;
 			return irq_base;
@@ -415,7 +417,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
 
 
 	err = gpiochip_add_data(gc, priv);
 	err = gpiochip_add_data(gc, priv);
 	if (err < 0)
 	if (err < 0)
-		goto out_free_desc;
+		return err;
 
 
 	err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base,
 	err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base,
 				handle_level_irq, IRQ_TYPE_NONE);
 				handle_level_irq, IRQ_TYPE_NONE);
@@ -433,14 +435,13 @@ static int xlp_gpio_probe(struct platform_device *pdev)
 
 
 out_gpio_remove:
 out_gpio_remove:
 	gpiochip_remove(gc);
 	gpiochip_remove(gc);
-out_free_desc:
-	irq_free_descs(irq_base, gc->ngpio);
 	return err;
 	return err;
 }
 }
 
 
 #ifdef CONFIG_ACPI
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xlp_gpio_acpi_match[] = {
 static const struct acpi_device_id xlp_gpio_acpi_match[] = {
 	{ "BRCM9006", GPIO_VARIANT_VULCAN },
 	{ "BRCM9006", GPIO_VARIANT_VULCAN },
+	{ "CAV9006",  GPIO_VARIANT_VULCAN },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match);
 MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match);

+ 12 - 12
drivers/gpio/gpio-zx.c

@@ -41,7 +41,7 @@
 #define ZX_GPIO_NR	16
 #define ZX_GPIO_NR	16
 
 
 struct zx_gpio {
 struct zx_gpio {
-	spinlock_t		lock;
+	raw_spinlock_t		lock;
 
 
 	void __iomem		*base;
 	void __iomem		*base;
 	struct gpio_chip	gc;
 	struct gpio_chip	gc;
@@ -56,11 +56,11 @@ static int zx_direction_input(struct gpio_chip *gc, unsigned offset)
 	if (offset >= gc->ngpio)
 	if (offset >= gc->ngpio)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	spin_lock_irqsave(&chip->lock, flags);
+	raw_spin_lock_irqsave(&chip->lock, flags);
 	gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
 	gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
 	gpiodir &= ~BIT(offset);
 	gpiodir &= ~BIT(offset);
 	writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
 	writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
-	spin_unlock_irqrestore(&chip->lock, flags);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -75,7 +75,7 @@ static int zx_direction_output(struct gpio_chip *gc, unsigned offset,
 	if (offset >= gc->ngpio)
 	if (offset >= gc->ngpio)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	spin_lock_irqsave(&chip->lock, flags);
+	raw_spin_lock_irqsave(&chip->lock, flags);
 	gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
 	gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
 	gpiodir |= BIT(offset);
 	gpiodir |= BIT(offset);
 	writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
 	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);
 		writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1);
 	else
 	else
 		writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0);
 		writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0);
-	spin_unlock_irqrestore(&chip->lock, flags);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -118,7 +118,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger)
 	if (offset < 0 || offset >= ZX_GPIO_NR)
 	if (offset < 0 || offset >= ZX_GPIO_NR)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	spin_lock_irqsave(&chip->lock, flags);
+	raw_spin_lock_irqsave(&chip->lock, flags);
 
 
 	gpioiev = readw_relaxed(chip->base + ZX_GPIO_IV);
 	gpioiev = readw_relaxed(chip->base + ZX_GPIO_IV);
 	gpiois = readw_relaxed(chip->base + ZX_GPIO_IVE);
 	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_epos, chip->base + ZX_GPIO_IEP);
 	writew_relaxed(gpioi_eneg, chip->base + ZX_GPIO_IEN);
 	writew_relaxed(gpioi_eneg, chip->base + ZX_GPIO_IEN);
 	writew_relaxed(gpioiev, chip->base + ZX_GPIO_IV);
 	writew_relaxed(gpioiev, chip->base + ZX_GPIO_IV);
-	spin_unlock_irqrestore(&chip->lock, flags);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
 
 
 	return 0;
 	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 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
 	u16 gpioie;
 	u16 gpioie;
 
 
-	spin_lock(&chip->lock);
+	raw_spin_lock(&chip->lock);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) | mask;
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) | mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) & ~mask;
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) & ~mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
 	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)
 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 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
 	u16 gpioie;
 	u16 gpioie;
 
 
-	spin_lock(&chip->lock);
+	raw_spin_lock(&chip->lock);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) & ~mask;
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) & ~mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) | mask;
 	gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) | mask;
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
 	writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
-	spin_unlock(&chip->lock);
+	raw_spin_unlock(&chip->lock);
 }
 }
 
 
 static struct irq_chip zx_irqchip = {
 static struct irq_chip zx_irqchip = {
@@ -230,7 +230,7 @@ static int zx_gpio_probe(struct platform_device *pdev)
 	if (IS_ERR(chip->base))
 	if (IS_ERR(chip->base))
 		return PTR_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")) {
 	if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
 		chip->gc.request = gpiochip_generic_request;
 		chip->gc.request = gpiochip_generic_request;
 		chip->gc.free = gpiochip_generic_free;
 		chip->gc.free = gpiochip_generic_free;

+ 44 - 9
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);
 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,
 static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
 				      const char *name, int index,
 				      const char *name, int index,
 				      struct acpi_reference_args *args)
 				      struct acpi_reference_args *args)
@@ -661,20 +692,24 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 {
 {
 	int idx, i;
 	int idx, i;
 	unsigned int irq_flags;
 	unsigned int irq_flags;
-	int ret = -ENOENT;
 
 
 	for (i = 0, idx = 0; idx <= index; i++) {
 	for (i = 0, idx = 0; idx <= index; i++) {
 		struct acpi_gpio_info info;
 		struct acpi_gpio_info info;
 		struct gpio_desc *desc;
 		struct gpio_desc *desc;
 
 
 		desc = acpi_get_gpiod_by_index(adev, NULL, i, &info);
 		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) {
 		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)
 			if (irq < 0)
 				return irq;
 				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);
 EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get);
 
 
@@ -1075,7 +1110,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
 					break;
 					break;
 				}
 				}
 		}
 		}
-		if (count >= 0)
+		if (count > 0)
 			break;
 			break;
 	}
 	}
 
 
@@ -1091,7 +1126,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
 		if (crs_count > 0)
 		if (crs_count > 0)
 			count = crs_count;
 			count = crs_count;
 	}
 	}
-	return count;
+	return count ? count : -ENOENT;
 }
 }
 
 
 struct acpi_crs_lookup {
 struct acpi_crs_lookup {

+ 1 - 1
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;
 		*flags |= GPIO_ACTIVE_LOW;
 
 
 	if (of_flags & OF_GPIO_SINGLE_ENDED) {
 	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;
 			*flags |= GPIO_OPEN_DRAIN;
 		else
 		else
 			*flags |= GPIO_OPEN_SOURCE;
 			*flags |= GPIO_OPEN_SOURCE;

+ 9 - 7
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,
 static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
 					  struct irq_chip *irqchip,
 					  struct irq_chip *irqchip,
-					  int parent_irq,
+					  unsigned int parent_irq,
 					  irq_flow_handler_t parent_handler)
 					  irq_flow_handler_t parent_handler)
 {
 {
 	unsigned int offset;
 	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,
 void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 				  struct irq_chip *irqchip,
 				  struct irq_chip *irqchip,
-				  int parent_irq,
+				  unsigned int parent_irq,
 				  irq_flow_handler_t parent_handler)
 				  irq_flow_handler_t parent_handler)
 {
 {
 	gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
 	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,
 void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
 				 struct irq_chip *irqchip,
 				 struct irq_chip *irqchip,
-				 int parent_irq)
+				 unsigned int parent_irq)
 {
 {
 	if (!gpiochip->irq_nested) {
 	if (!gpiochip->irq_nested) {
 		chip_err(gpiochip, "tried to nest a chained gpiochip\n");
 		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]);
 				 gpio_suffixes[i]);
 
 
 		ret = of_gpio_named_count(dev->of_node, propname);
 		ret = of_gpio_named_count(dev->of_node, propname);
-		if (ret >= 0)
+		if (ret > 0)
 			break;
 			break;
 	}
 	}
-	return ret;
+	return ret ? ret : -ENOENT;
 }
 }
 
 
 static int platform_gpio_count(struct device *dev, const char *con_id)
 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
  * underlying firmware interface and then makes sure that the GPIO
  * descriptor is requested before it is returned to the caller.
  * 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.
  * provided @dflags.
  *
  *
  * In case of error an ERR_PTR() is returned.
  * 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;
 	unsigned long lflags = 0;
 	bool active_low = false;
 	bool active_low = false;
 	bool single_ended = false;
 	bool single_ended = false;
+	bool open_drain = false;
 	int ret;
 	int ret;
 
 
 	if (!fwnode)
 	if (!fwnode)
@@ -3353,6 +3354,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
 		if (!IS_ERR(desc)) {
 		if (!IS_ERR(desc)) {
 			active_low = flags & OF_GPIO_ACTIVE_LOW;
 			active_low = flags & OF_GPIO_ACTIVE_LOW;
 			single_ended = flags & OF_GPIO_SINGLE_ENDED;
 			single_ended = flags & OF_GPIO_SINGLE_ENDED;
+			open_drain = flags & OF_GPIO_OPEN_DRAIN;
 		}
 		}
 	} else if (is_acpi_node(fwnode)) {
 	} else if (is_acpi_node(fwnode)) {
 		struct acpi_gpio_info info;
 		struct acpi_gpio_info info;
@@ -3373,7 +3375,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
 		lflags |= GPIO_ACTIVE_LOW;
 		lflags |= GPIO_ACTIVE_LOW;
 
 
 	if (single_ended) {
 	if (single_ended) {
-		if (active_low)
+		if (open_drain)
 			lflags |= GPIO_OPEN_DRAIN;
 			lflags |= GPIO_OPEN_DRAIN;
 		else
 		else
 			lflags |= GPIO_OPEN_SOURCE;
 			lflags |= GPIO_OPEN_SOURCE;

+ 3 - 2
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;
 		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");
 		dev_dbg(dev, "no GPIO attached, ignoring...\n");
-		return -ENODEV;
+		return error;
 	}
 	}
 
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);

+ 3 - 2
drivers/platform/x86/surface3_button.c

@@ -196,9 +196,10 @@ static int surface3_button_probe(struct i2c_client *client,
 		    strlen(SURFACE_BUTTON_OBJ_NAME)))
 		    strlen(SURFACE_BUTTON_OBJ_NAME)))
 		return -ENODEV;
 		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");
 		dev_dbg(dev, "no GPIO attached, ignoring...\n");
-		return -ENODEV;
+		return error;
 	}
 	}
 
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);

+ 3 - 2
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) {
 		if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
 			struct gpio_desc *gpio;
 			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);
 					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
 			 * 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);
 	device_init_wakeup(&pci->dev, false);
 	pm_runtime_get(&pci->dev);
 	pm_runtime_get(&pci->dev);
-	acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev));
 	platform_device_unregister(dwc->dwc3);
 	platform_device_unregister(dwc->dwc3);
 }
 }
 
 

+ 8 - 4
include/dt-bindings/gpio/gpio.h

@@ -17,11 +17,15 @@
 #define GPIO_PUSH_PULL 0
 #define GPIO_PUSH_PULL 0
 #define GPIO_SINGLE_ENDED 2
 #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
 #endif

+ 11 - 0
include/linux/acpi.h

@@ -957,6 +957,10 @@ static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
 		adev->driver_gpios = NULL;
 		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);
 int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index);
 #else
 #else
 static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
 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 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)
 static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 {
 {
 	return -ENXIO;
 	return -ENXIO;

+ 6 - 6
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,
 gpiod_get_optional(struct device *dev, const char *con_id,
 		   enum gpiod_flags flags)
 		   enum gpiod_flags flags)
 {
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 }
 
 
 static inline struct gpio_desc *__must_check
 static inline struct gpio_desc *__must_check
 gpiod_get_index_optional(struct device *dev, const char *con_id,
 gpiod_get_index_optional(struct device *dev, const char *con_id,
 			 unsigned int index, enum gpiod_flags flags)
 			 unsigned int index, enum gpiod_flags flags)
 {
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 }
 
 
 static inline struct gpio_descs *__must_check
 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,
 gpiod_get_array_optional(struct device *dev, const char *con_id,
 			 enum gpiod_flags flags)
 			 enum gpiod_flags flags)
 {
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 }
 
 
 static inline void gpiod_put(struct gpio_desc *desc)
 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,
 devm_gpiod_get_optional(struct device *dev, const char *con_id,
 			  enum gpiod_flags flags)
 			  enum gpiod_flags flags)
 {
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 }
 
 
 static inline struct gpio_desc *__must_check
 static inline struct gpio_desc *__must_check
 devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
 devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
 				unsigned int index, enum gpiod_flags flags)
 				unsigned int index, enum gpiod_flags flags)
 {
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 }
 
 
 static inline struct gpio_descs *__must_check
 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,
 devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
 			      enum gpiod_flags flags)
 			      enum gpiod_flags flags)
 {
 {
-	return ERR_PTR(-ENOSYS);
+	return NULL;
 }
 }
 
 
 static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
 static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)

+ 3 - 3
include/linux/gpio/driver.h

@@ -168,7 +168,7 @@ struct gpio_chip {
 	unsigned int		irq_base;
 	unsigned int		irq_base;
 	irq_flow_handler_t	irq_handler;
 	irq_flow_handler_t	irq_handler;
 	unsigned int		irq_default_type;
 	unsigned int		irq_default_type;
-	int			irq_chained_parent;
+	unsigned int		irq_chained_parent;
 	bool			irq_nested;
 	bool			irq_nested;
 	bool			irq_need_valid_mask;
 	bool			irq_need_valid_mask;
 	unsigned long		*irq_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,
 void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 		struct irq_chip *irqchip,
 		struct irq_chip *irqchip,
-		int parent_irq,
+		unsigned int parent_irq,
 		irq_flow_handler_t parent_handler);
 		irq_flow_handler_t parent_handler);
 
 
 void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
 void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
 		struct irq_chip *irqchip,
 		struct irq_chip *irqchip,
-		int parent_irq);
+		unsigned int parent_irq);
 
 
 int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
 			     struct irq_chip *irqchip,
 			     struct irq_chip *irqchip,

+ 13 - 0
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

+ 1 - 0
include/linux/of_gpio.h

@@ -30,6 +30,7 @@ struct device_node;
 enum of_gpio_flags {
 enum of_gpio_flags {
 	OF_GPIO_ACTIVE_LOW = 0x1,
 	OF_GPIO_ACTIVE_LOW = 0x1,
 	OF_GPIO_SINGLE_ENDED = 0x2,
 	OF_GPIO_SINGLE_ENDED = 0x2,
+	OF_GPIO_OPEN_DRAIN = 0x4,
 };
 };
 
 
 #ifdef CONFIG_OF_GPIO
 #ifdef CONFIG_OF_GPIO