diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-05 11:48:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-05 11:48:14 -0700 |
commit | b8052599420cd94505baec1f22b4e7c9e5ae5fce (patch) | |
tree | 80775d4b6c6d67948a1c5e9aa6bd70cb00838b7a | |
parent | 1f89a590b26e34ec7c32fbafaed446e52c3d0c3f (diff) | |
parent | c34c1228fc1cfe83aed909995f5b82e0ab7cb977 (diff) | |
download | linux-b8052599420cd94505baec1f22b4e7c9e5ae5fce.tar.bz2 |
Merge tag 'gpio-updates-for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio updates from Bartosz Golaszewski:
"One new driver, support for new models in existing ones, dt-bindings
conversions for several modules and improvements all over the place.
Summary:
- new driver for the IDT 79RC3243x GPIO controller
- device tree bindings coversion to YAML for the following drivers:
gpio-rk3328-grf, gpio-omap, gpio-davinci, gpio-zynq, gpio-stp,
gpio-pcf857x
- cleanup of probe functions in many drivers from Alexandru Ardelean,
mostly dropping unnecessary calls to platform_set_drvdata() and
removing error messages where none are needed (handled by the
subsystem already)
- several improvements to the core gpiolib and the sysfs interface
code from Andy Shevchenko
- conversion of the gpio-xilinx driver to using the bitmap API +
improvements of suspend/resume handling + minor tweaks
- convert the gpio-stmpe to using devres helpers exclusively in probe
for improved robustness
- updates for the generic gpio-regmap driver
- updates for the gpio-dwapb driver
- support for a new model in gpio-pca953x
- cleanups in gpio-tegra186, gpio-104-idio-16, gpio-mxs & gpio-xgene
- slight code refactoring of the gpio-zynq driver
- documentation fixes from Mauro Carvalho Chehab
- a bunch of minor tweaks and improvements all over the place"
* tag 'gpio-updates-for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (57 commits)
docs: driver-api: gpio: using-gpio.rst: avoid using ReST :doc:`foo` markup
dt-bindings: gpio: pcf857x: Convert to json-schema
gpio: mxs: Prefer unsigned int to bare use of unsigned
dt-bindings: gpio: stp: convert to json-schema
dt-bindings: gpio: zynq: convert bindings to YAML
dt-bindings: gpio: gpio-davinci: Convert to json-schema
gpio: pca953x: Add support for the On Semi pca9655
gpio: gpio-xilinx: update on suspend and resume calls
gpio: zynq: Check return value of irq_get_irq_data
gpio: zynq: Check return value of pm_runtime_get_sync
gpio: zynq: use module_platform_driver to simplify the code
gpio: idt3243x: Fix return value check in idt_gpio_probe()
MAINTAINERS: update ti,omap-gpio.yaml reference
dt-bindings: gpio: Add devicetree binding for IDT 79RC32434 GPIO controller
gpio: Add support for IDT 79RC3243x GPIO controller
gpio: regmap: move drvdata to config data
gpio-dwapb: Drop unused headers and sort the rest
gpio: gpio-regmap: Use devm_add_action_or_reset()
gpio: dwapb: Switch to use fwnode_irq_get()
gpio: dwapb: Drop redundant check in dwapb_irq_set_type()
...
52 files changed, 1243 insertions, 945 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt b/Documentation/devicetree/bindings/gpio/gpio-davinci.txt deleted file mode 100644 index 8ad4fd9aaffd..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt +++ /dev/null @@ -1,167 +0,0 @@ -Davinci/Keystone GPIO controller bindings - -Required Properties: -- compatible: should be "ti,dm6441-gpio": for Davinci da850 SoCs - "ti,keystone-gpio": for Keystone 2 66AK2H/K, 66AK2L, - 66AK2E SoCs - "ti,k2g-gpio", "ti,keystone-gpio": for 66AK2G - "ti,am654-gpio", "ti,keystone-gpio": for TI K3 AM654 - "ti,j721e-gpio", "ti,keystone-gpio": for J721E SoCs - "ti,am64-gpio", "ti,keystone-gpio": for AM64 SoCs - -- reg: Physical base address of the controller and the size of memory mapped - registers. - -- gpio-controller : Marks the device node as a gpio controller. - -- #gpio-cells : Should be two. - - first cell is the pin number - - second cell is used to specify optional parameters (unused) - -- interrupts: Array of GPIO interrupt number. Only banked or unbanked IRQs are - supported at a time. - -- ti,ngpio: The number of GPIO pins supported. - -- ti,davinci-gpio-unbanked: The number of GPIOs that have an individual interrupt - line to processor. - -- clocks: Should contain the device's input clock, and should be defined as per - the appropriate clock bindings consumer usage in, - - Documentation/devicetree/bindings/clock/keystone-gate.txt - for 66AK2HK/66AK2L/66AK2E SoCs or, - - Documentation/devicetree/bindings/clock/ti,sci-clk.yaml - for 66AK2G SoCs - -- clock-names: Name should be "gpio"; - -Currently clock-names and clocks are needed for all keystone 2 platforms -Davinci platforms do not have DT clocks as of now. - -The GPIO controller also acts as an interrupt controller. It uses the default -two cells specifier as described in Documentation/devicetree/bindings/ -interrupt-controller/interrupts.txt. - -Example: - -gpio: gpio@1e26000 { - compatible = "ti,dm6441-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x226000 0x1000>; - interrupt-parent = <&intc>; - interrupts = <42 IRQ_TYPE_EDGE_BOTH 43 IRQ_TYPE_EDGE_BOTH - 44 IRQ_TYPE_EDGE_BOTH 45 IRQ_TYPE_EDGE_BOTH - 46 IRQ_TYPE_EDGE_BOTH 47 IRQ_TYPE_EDGE_BOTH - 48 IRQ_TYPE_EDGE_BOTH 49 IRQ_TYPE_EDGE_BOTH - 50 IRQ_TYPE_EDGE_BOTH>; - ti,ngpio = <144>; - ti,davinci-gpio-unbanked = <0>; - interrupt-controller; - #interrupt-cells = <2>; -}; - -leds { - compatible = "gpio-leds"; - - led1 { - label = "davinci:green:usr1"; - gpios = <&gpio 10 GPIO_ACTIVE_HIGH>; - ... - }; - - led2 { - label = "davinci:red:debug1"; - gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; - ... - }; -}; - -Example for 66AK2G: - -gpio0: gpio@2603000 { - compatible = "ti,k2g-gpio", "ti,keystone-gpio"; - reg = <0x02603000 0x100>; - gpio-controller; - #gpio-cells = <2>; - interrupts = <GIC_SPI 432 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 433 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 434 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 435 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 436 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 437 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 438 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 439 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 440 IRQ_TYPE_EDGE_RISING>; - interrupt-controller; - #interrupt-cells = <2>; - ti,ngpio = <144>; - ti,davinci-gpio-unbanked = <0>; - clocks = <&k2g_clks 0x001b 0x0>; - clock-names = "gpio"; -}; - -Example for 66AK2HK/66AK2L/66AK2E: - -gpio0: gpio@260bf00 { - compatible = "ti,keystone-gpio"; - reg = <0x0260bf00 0x100>; - gpio-controller; - #gpio-cells = <2>; - /* HW Interrupts mapped to GPIO pins */ - interrupts = <GIC_SPI 120 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 121 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 122 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 123 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 124 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 125 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 126 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 127 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 128 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 131 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 132 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 133 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 134 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 135 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 136 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 137 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 138 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 139 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 140 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 141 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 144 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 145 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 146 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 147 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 148 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 150 IRQ_TYPE_EDGE_RISING>, - <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>; - clocks = <&clkgpio>; - clock-names = "gpio"; - ti,ngpio = <32>; - ti,davinci-gpio-unbanked = <32>; -}; - -Example for K3 AM654: - -wkup_gpio0: wkup_gpio0@42110000 { - compatible = "ti,am654-gpio", "ti,keystone-gpio"; - reg = <0x42110000 0x100>; - gpio-controller; - #gpio-cells = <2>; - interrupt-parent = <&intr_wkup_gpio>; - interrupts = <59 128>, <59 129>, <59 130>, <59 131>; - interrupt-controller; - #interrupt-cells = <2>; - ti,ngpio = <56>; - ti,davinci-gpio-unbanked = <0>; - clocks = <&k3_clks 59 0>; - clock-names = "gpio"; -}; diff --git a/Documentation/devicetree/bindings/gpio/gpio-davinci.yaml b/Documentation/devicetree/bindings/gpio/gpio-davinci.yaml new file mode 100644 index 000000000000..f32e09ef937c --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-davinci.yaml @@ -0,0 +1,185 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-davinci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO controller for Davinci and keystone devices + +maintainers: + - Keerthy <j-keerthy@ti.com> + +properties: + compatible: + oneOf: + - items: + - enum: + - ti,k2g-gpio + - ti,am654-gpio + - ti,j721e-gpio + - ti,am64-gpio + - const: ti,keystone-gpio + + - items: + - enum: + - ti,dm6441-gpio + - ti,keystone-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + gpio-ranges: true + + gpio-line-names: + description: strings describing the names of each gpio line. + minItems: 1 + maxItems: 100 + + "#gpio-cells": + const: 2 + description: + first cell is the pin number and second cell is used to specify optional parameters (unused). + + interrupts: + description: + The interrupts are specified as per the interrupt parent. Only banked + or unbanked IRQs are supported at a time. If the interrupts are + banked then provide list of interrupts corresponding to each bank, else + provide the list of interrupts for each gpio. + minItems: 1 + maxItems: 100 + + ti,ngpio: + $ref: /schemas/types.yaml#/definitions/uint32 + description: The number of GPIO pins supported consecutively. + minimum: 1 + + ti,davinci-gpio-unbanked: + $ref: /schemas/types.yaml#/definitions/uint32 + description: The number of GPIOs that have an individual interrupt line to processor. + minimum: 0 + + clocks: + maxItems: 1 + + clock-names: + const: gpio + + interrupt-controller: true + + power-domains: + maxItems: 1 + + "#interrupt-cells": + const: 2 + +patternProperties: + "^(.+-hog(-[0-9]+)?)$": + type: object + + required: + - gpio-hog + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + - interrupts + - ti,ngpio + - ti,davinci-gpio-unbanked + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include<dt-bindings/interrupt-controller/arm-gic.h> + + gpio0: gpio@2603000 { + compatible = "ti,k2g-gpio", "ti,keystone-gpio"; + reg = <0x02603000 0x100>; + gpio-controller; + #gpio-cells = <2>; + interrupts = <GIC_SPI 432 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 433 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 434 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 435 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 436 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 437 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 438 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 439 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 440 IRQ_TYPE_EDGE_RISING>; + interrupt-controller; + #interrupt-cells = <2>; + ti,ngpio = <144>; + ti,davinci-gpio-unbanked = <0>; + clocks = <&k2g_clks 0x001b 0x0>; + clock-names = "gpio"; + }; + + - | + #include<dt-bindings/interrupt-controller/arm-gic.h> + + gpio1: gpio@260bf00 { + compatible = "ti,keystone-gpio"; + reg = <0x0260bf00 0x100>; + gpio-controller; + #gpio-cells = <2>; + /* HW Interrupts mapped to GPIO pins */ + interrupts = <GIC_SPI 120 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 121 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 122 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 123 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 124 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 125 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 126 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 127 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 128 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 131 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 132 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 133 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 134 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 135 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 136 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 137 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 138 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 139 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 140 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 141 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 142 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 144 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 145 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 146 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 147 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 148 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 150 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 151 IRQ_TYPE_EDGE_RISING>; + clocks = <&clkgpio>; + clock-names = "gpio"; + ti,ngpio = <32>; + ti,davinci-gpio-unbanked = <32>; + }; + + - | + wkup_gpio0: gpio0@42110000 { + compatible = "ti,am654-gpio", "ti,keystone-gpio"; + reg = <0x42110000 0x100>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&intr_wkup_gpio>; + interrupts = <60>, <61>, <62>, <63>; + interrupt-controller; + #interrupt-cells = <2>; + ti,ngpio = <56>; + ti,davinci-gpio-unbanked = <0>; + clocks = <&k3_clks 59 0>; + clock-names = "gpio"; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-omap.txt b/Documentation/devicetree/bindings/gpio/gpio-omap.txt deleted file mode 100644 index e57b2cb28f6c..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-omap.txt +++ /dev/null @@ -1,45 +0,0 @@ -OMAP GPIO controller bindings - -Required properties: -- compatible: - - "ti,omap2-gpio" for OMAP2 controllers - - "ti,omap3-gpio" for OMAP3 controllers - - "ti,omap4-gpio" for OMAP4 controllers -- reg : Physical base address of the controller and length of memory mapped - region. -- gpio-controller : Marks the device node as a GPIO controller. -- #gpio-cells : Should be two. - - first cell is the pin number - - second cell is used to specify optional parameters (unused) -- interrupt-controller: Mark the device node as an interrupt controller. -- #interrupt-cells : Should be 2. - The first cell is the GPIO number. - The second cell is used to specify flags: - bits[3:0] trigger type and level flags: - 1 = low-to-high edge triggered. - 2 = high-to-low edge triggered. - 4 = active high level-sensitive. - 8 = active low level-sensitive. -- interrupts : The interrupt the controller is rising as output when an - interrupt occures - -OMAP specific properties: -- ti,hwmods: Name of the hwmod associated to the GPIO: - "gpio<X>", <X> being the 1-based instance number - from the HW spec. -- ti,gpio-always-on: Indicates if a GPIO bank is always powered and - so will never lose its logic state. - - -Example: - -gpio0: gpio@44e07000 { - compatible = "ti,omap4-gpio"; - reg = <0x44e07000 0x1000>; - ti,hwmods = "gpio1"; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - interrupts = <96>; -}; diff --git a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt deleted file mode 100644 index a482455a205b..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt +++ /dev/null @@ -1,69 +0,0 @@ -* PCF857x-compatible I/O expanders - -The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be -driven high by a pull-up current source or driven low to ground. This combines -the direction and output level into a single bit per line, which can't be read -back. We can't actually know at initialization time whether a line is configured -(a) as output and driving the signal low/high, or (b) as input and reporting a -low/high value, without knowing the last value written since the chip came out -of reset (if any). The only reliable solution for setting up line direction is -thus to do it explicitly. - -Required Properties: - - - compatible: should be one of the following. - - "maxim,max7328": For the Maxim MAX7378 - - "maxim,max7329": For the Maxim MAX7329 - - "nxp,pca8574": For the NXP PCA8574 - - "nxp,pca8575": For the NXP PCA8575 - - "nxp,pca9670": For the NXP PCA9670 - - "nxp,pca9671": For the NXP PCA9671 - - "nxp,pca9672": For the NXP PCA9672 - - "nxp,pca9673": For the NXP PCA9673 - - "nxp,pca9674": For the NXP PCA9674 - - "nxp,pca9675": For the NXP PCA9675 - - "nxp,pcf8574": For the NXP PCF8574 - - "nxp,pcf8574a": For the NXP PCF8574A - - "nxp,pcf8575": For the NXP PCF8575 - - - reg: I2C slave address. - - - gpio-controller: Marks the device node as a gpio controller. - - #gpio-cells: Should be 2. The first cell is the GPIO number and the second - cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the - GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported. - -Optional Properties: - - - lines-initial-states: Bitmask that specifies the initial state of each - line. When a bit is set to zero, the corresponding line will be initialized to - the input (pulled-up) state. When the bit is set to one, the line will be - initialized the low-level output state. If the property is not specified - all lines will be initialized to the input state. - - The I/O expander can detect input state changes, and thus optionally act as - an interrupt controller. When the expander interrupt line is connected all the - following properties must be set. For more information please see the - interrupt controller device tree bindings documentation available at - Documentation/devicetree/bindings/interrupt-controller/interrupts.txt. - - - interrupt-controller: Identifies the node as an interrupt controller. - - #interrupt-cells: Number of cells to encode an interrupt source, shall be 2. - - interrupts: Interrupt specifier for the controllers interrupt. - - -Please refer to gpio.txt in this directory for details of the common GPIO -bindings used by client devices. - -Example: PCF8575 I/O expander node - - pcf8575: gpio@20 { - compatible = "nxp,pcf8575"; - reg = <0x20>; - interrupt-parent = <&irqpin2>; - interrupts = <3 0>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupt-cells = <2>; - }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt deleted file mode 100644 index 78458adbf4b7..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-stp-xway.txt +++ /dev/null @@ -1,42 +0,0 @@ -Lantiq SoC Serial To Parallel (STP) GPIO controller - -The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a -peripheral controller used to drive external shift register cascades. At most -3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem -to drive the 2 LSBs of the cascade automatically. - - -Required properties: -- compatible : Should be "lantiq,gpio-stp-xway" -- reg : Address and length of the register set for the device -- #gpio-cells : Should be two. The first cell is the pin number and - the second cell is used to specify optional parameters (currently - unused). -- gpio-controller : Marks the device node as a gpio controller. - -Optional properties: -- lantiq,shadow : The default value that we shall assume as already set on the - shift register cascade. -- lantiq,groups : Set the 3 bit mask to select which of the 3 groups are enabled - in the shift register cascade. -- lantiq,dsl : The dsl core can control the 2 LSBs of the gpio cascade. This 2 bit - property can enable this feature. -- lantiq,phy1 : The gphy1 core can control 3 bits of the gpio cascade. -- lantiq,phy2 : The gphy2 core can control 3 bits of the gpio cascade. -- lantiq,rising : use rising instead of falling edge for the shift register - -Example: - -gpio1: stp@e100bb0 { - compatible = "lantiq,gpio-stp-xway"; - reg = <0xE100BB0 0x40>; - #gpio-cells = <2>; - gpio-controller; - - lantiq,shadow = <0xffff>; - lantiq,groups = <0x7>; - lantiq,dsl = <0x3>; - lantiq,phy1 = <0x7>; - lantiq,phy2 = <0x7>; - /* lantiq,rising; */ -}; diff --git a/Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml new file mode 100644 index 000000000000..d565c4b63dbf --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-stp-xway.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Lantiq SoC Serial To Parallel (STP) GPIO controller + +description: | + The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a + peripheral controller used to drive external shift register cascades. At most + 3 groups of 8 bits can be driven. The hardware is able to allow the DSL modem + and Ethernet PHYs to drive some bytes of the cascade automatically. + +maintainers: + - John Crispin <john@phrozen.org> + +properties: + $nodename: + pattern: "^gpio@[0-9a-f]+$" + + compatible: + const: lantiq,gpio-stp-xway + + reg: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + description: + The first cell is the pin number and the second cell is used to specify + consumer flags. + const: 2 + + lantiq,shadow: + description: + The default value that we shall assume as already set on the + shift register cascade. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x000000 + maximum: 0xffffff + + lantiq,groups: + description: + Set the 3 bit mask to select which of the 3 groups are enabled + in the shift register cascade. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x0 + maximum: 0x7 + + lantiq,dsl: + description: + The dsl core can control the 2 LSBs of the gpio cascade. This 2 bit + property can enable this feature. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x0 + maximum: 0x3 + + lantiq,rising: + description: + Use rising instead of falling edge for the shift register. + type: boolean + +patternProperties: + "^lantiq,phy[1-4]$": + description: + The gphy core can control 3 bits of the gpio cascade. In the xRX200 family + phy[1-2] are available, in xRX330 phy[1-3] and in XRX330 phy[1-4]. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0x0 + maximum: 0x7 + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + gpio@e100bb0 { + compatible = "lantiq,gpio-stp-xway"; + reg = <0xE100BB0 0x40>; + #gpio-cells = <2>; + gpio-controller; + + pinctrl-0 = <&stp_pins>; + pinctrl-names = "default"; + + lantiq,shadow = <0xffffff>; + lantiq,groups = <0x7>; + lantiq,dsl = <0x3>; + lantiq,phy1 = <0x7>; + lantiq,phy2 = <0x7>; + }; +... diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.txt b/Documentation/devicetree/bindings/gpio/gpio-zynq.txt deleted file mode 100644 index f693e82b4c0f..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-zynq.txt +++ /dev/null @@ -1,36 +0,0 @@ -Xilinx Zynq GPIO controller Device Tree Bindings -------------------------------------------- - -Required properties: -- #gpio-cells : Should be two - - First cell is the GPIO line number - - Second cell is used to specify optional - parameters (unused) -- compatible : Should be "xlnx,zynq-gpio-1.0" or - "xlnx,zynqmp-gpio-1.0" or "xlnx,versal-gpio-1.0 - or "xlnx,pmc-gpio-1.0 -- clocks : Clock specifier (see clock bindings for details) -- gpio-controller : Marks the device node as a GPIO controller. -- interrupts : Interrupt specifier (see interrupt bindings for - details) -- interrupt-controller : Marks the device node as an interrupt controller. -- #interrupt-cells : Should be 2. The first cell is the GPIO number. - The second cell bits[3:0] is used to specify trigger type and level flags: - 1 = low-to-high edge triggered. - 2 = high-to-low edge triggered. - 4 = active high level-sensitive. - 8 = active low level-sensitive. -- reg : Address and length of the register set for the device - -Example: - gpio@e000a000 { - #gpio-cells = <2>; - compatible = "xlnx,zynq-gpio-1.0"; - clocks = <&clkc 42>; - gpio-controller; - interrupt-parent = <&intc>; - interrupts = <0 20 4>; - interrupt-controller; - #interrupt-cells = <2>; - reg = <0xe000a000 0x1000>; - }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml new file mode 100644 index 000000000000..378da2649e66 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-zynq.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-zynq.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx Zynq GPIO controller Device Tree Bindings + +maintainers: + - Michal Simek <michal.simek@xilinx.com> + +properties: + compatible: + const: xlnx,zynq-gpio-1.0 + + reg: + maxItems: 1 + + "#gpio-cells": + const: 2 + + interrupts: + maxItems: 1 + + gpio-controller: true + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - "#gpio-cells" + - interrupts + - gpio-controller + - interrupt-controller + - "#interrupt-cells" + - clocks + +additionalProperties: false + +examples: + - | + gpio@e000a000 { + #gpio-cells = <2>; + compatible = "xlnx,zynq-gpio-1.0"; + clocks = <&clkc 42>; + gpio-controller; + interrupt-parent = <&intc>; + interrupts = <0 20 4>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xe000a000 0x1000>; + }; diff --git a/Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml b/Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml new file mode 100644 index 000000000000..d38de8144656 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/idt,32434-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IDT 79RC32434 GPIO controller + +maintainers: + - Thomas Bogendoerfer <tsbogend@alpha.franken.de> + +properties: + compatible: + const: idt,32434-gpio + + reg: + maxItems: 2 + + reg-names: + items: + - const: gpio + - const: pic + + gpio-controller: true + + "#gpio-cells": + const: 2 + + ngpios: + minimum: 1 + maximum: 32 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - reg-names + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + gpio0: gpio@50004 { + compatible = "idt,32434-gpio"; + reg = <0x50004 0x10>, <0x38030 0x0c>; + reg-names = "gpio", "pic"; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ngpios = <14>; + }; diff --git a/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml new file mode 100644 index 000000000000..f0ff66c4c74e --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/nxp,pcf8575.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PCF857x-compatible I/O expanders + +maintainers: + - Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> + +description: + The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be + driven high by a pull-up current source or driven low to ground. This + combines the direction and output level into a single bit per line, which + can't be read back. We can't actually know at initialization time whether a + line is configured (a) as output and driving the signal low/high, or (b) as + input and reporting a low/high value, without knowing the last value written + since the chip came out of reset (if any). The only reliable solution for + setting up line direction is thus to do it explicitly. + +properties: + compatible: + enum: + - maxim,max7328 + - maxim,max7329 + - nxp,pca8574 + - nxp,pca8575 + - nxp,pca9670 + - nxp,pca9671 + - nxp,pca9672 + - nxp,pca9673 + - nxp,pca9674 + - nxp,pca9675 + - nxp,pcf8574 + - nxp,pcf8574a + - nxp,pcf8575 + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + description: + The first cell is the GPIO number and the second cell specifies GPIO + flags, as defined in <dt-bindings/gpio/gpio.h>. Only the GPIO_ACTIVE_HIGH + and GPIO_ACTIVE_LOW flags are supported. + + lines-initial-states: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Bitmask that specifies the initial state of each line. + When a bit is set to zero, the corresponding line will be initialized to + the input (pulled-up) state. + When the bit is set to one, the line will be initialized to the + low-level output state. + If the property is not specified all lines will be initialized to the + input state. + + interrupts: + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + wakeup-source: true + +patternProperties: + "^(.+-hog(-[0-9]+)?)$": + type: object + + required: + - gpio-hog + +required: + - compatible + - reg + - gpio-controller + - '#gpio-cells' + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pcf8575: gpio@20 { + compatible = "nxp,pcf8575"; + reg = <0x20>; + interrupt-parent = <&irqpin2>; + interrupts = <3 0>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + }; diff --git a/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.txt b/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.txt deleted file mode 100644 index f9231df17c2b..000000000000 --- a/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.txt +++ /dev/null @@ -1,32 +0,0 @@ -Rockchip RK3328 GRF (General Register Files) GPIO controller. - -In Rockchip RK3328, the output only GPIO_MUTE pin, originally for codec mute -control, can also be used for general purpose. It is manipulated by the -GRF_SOC_CON10 register in GRF. Aside from the GPIO_MUTE pin, the HDMI pins can -also be set in the same way. - -Currently this GPIO controller only supports the mute pin. If needed in the -future, the HDMI pins support can also be added. - -Required properties: -- compatible: Should contain "rockchip,rk3328-grf-gpio". -- gpio-controller: Marks the device node as a gpio controller. -- #gpio-cells: Should be 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. - -Example: - - grf: syscon@ff100000 { - compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd"; - - grf_gpio: grf-gpio { - compatible = "rockchip,rk3328-grf-gpio"; - gpio-controller; - #gpio-cells = <2>; - }; - }; - -Note: The grf_gpio node should be declared as the child of the GRF (General -Register File) node. The GPIO_MUTE pin is referred to as <&grf_gpio 0>. diff --git a/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.yaml b/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.yaml new file mode 100644 index 000000000000..d8cce73ea0ae --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/rockchip,rk3328-grf-gpio.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/rockchip,rk3328-grf-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3328 General Register Files GPIO controller + +description: + The Rockchip RK3328 General Register File (GRF) outputs only the + GPIO_MUTE pin, originally for codec mute control, but it can also be used + for general purpose. It is manipulated by the GRF_SOC_CON10 register. + If needed in the future support for the HDMI pins can also be added. + The GPIO node should be declared as the child of the GRF node. + + The GPIO_MUTE pin is referred to in the format + + <&grf_gpio 0 GPIO_ACTIVE_LOW> + + The first cell is the pin number and + the second cell is used to specify the GPIO polarity + 0 = Active high + 1 = Active low + +maintainers: + - Heiko Stuebner <heiko@sntech.de> + +properties: + compatible: + const: rockchip,rk3328-grf-gpio + + gpio-controller: true + + "#gpio-cells": + const: 2 + +required: + - compatible + - gpio-controller + - "#gpio-cells" + +additionalProperties: false + +examples: + - | + grf_gpio: gpio { + compatible = "rockchip,rk3328-grf-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml b/Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml new file mode 100644 index 000000000000..7087e4a5013f --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/ti,omap-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: OMAP GPIO controller bindings + +maintainers: + - Grygorii Strashko <grygorii.strashko@ti.com> + +description: | + The general-purpose interface combines general-purpose input/output (GPIO) banks. + Each GPIO banks provides up to 32 dedicated general-purpose pins with input + and output capabilities; interrupt generation in active mode and wake-up + request generation in idle mode upon the detection of external events. + +properties: + compatible: + oneOf: + - enum: + - ti,omap2-gpio + - ti,omap3-gpio + - ti,omap4-gpio + - items: + - const: ti,am4372-gpio + - const: ti,omap4-gpio + + reg: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + interrupts: + maxItems: 1 + + gpio-ranges: true + + gpio-line-names: + minItems: 1 + maxItems: 32 + + ti,gpio-always-on: + $ref: /schemas/types.yaml#/definitions/flag + description: + Indicates if a GPIO bank is always powered and will never lose its logic state. + + ti,hwmods: + $ref: /schemas/types.yaml#/definitions/string + deprecated: true + description: + Name of the hwmod associated with the GPIO. Needed on some legacy OMAP + SoCs which have not been converted to the ti,sysc interconnect hierarachy. + + ti,no-reset-on-init: + $ref: /schemas/types.yaml#/definitions/flag + deprecated: true + description: + Do not reset on init. Used with ti,hwmods on some legacy OMAP SoCs which + have not been converted to the ti,sysc interconnect hierarachy. + +patternProperties: + "^(.+-hog(-[0-9]+)?)$": + type: object + + required: + - gpio-hog + +required: + - compatible + - reg + - gpio-controller + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + - interrupts + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + gpio0: gpio@0 { + compatible = "ti,omap4-gpio"; + reg = <0x0 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <96>; + ti,gpio-always-on; + + ls-buf-en-hog { + gpio-hog; + gpios = <10 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "LS_BUF_EN"; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 516b69d189b9..c06fcc41381c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13471,7 +13471,7 @@ M: Santosh Shilimkar <ssantosh@kernel.org> M: Kevin Hilman <khilman@kernel.org> L: linux-omap@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/gpio/gpio-omap.txt +F: Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml F: drivers/gpio/gpio-omap.c OMAP HARDWARE SPINLOCK SUPPORT @@ -18448,7 +18448,7 @@ TI DAVINCI SERIES GPIO DRIVER M: Keerthy <j-keerthy@ti.com> L: linux-gpio@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/gpio/gpio-davinci.txt +F: Documentation/devicetree/bindings/gpio/gpio-davinci.yaml F: drivers/gpio/gpio-davinci.c TI DAVINCI SERIES MEDIA DRIVER diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63b84ba161dc..fab571016adf 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -782,6 +782,18 @@ config GPIO_MSC313 Say Y here to support the main GPIO block on MStar/SigmaStar ARMv7 based SoCs. +config GPIO_IDT3243X + tristate "IDT 79RC3243X GPIO support" + depends on MIKROTIK_RB532 || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Select this option to enable GPIO driver for + IDT 79RC3243X based devices like Mikrotik RB532. + + To compile this driver as a module, choose M here: the module will + be called gpio-idt3243x. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d7c81e1611a4..32a32659866a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_HISI) += gpio-hisi.o obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o +obj-$(CONFIG_GPIO_IDT3243X) += gpio-idt3243x.o obj-$(CONFIG_GPIO_IOP) += gpio-iop.o obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 50ad0280fd78..55b40299ebfa 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -44,11 +44,12 @@ struct idio_16_gpio { struct gpio_chip chip; raw_spinlock_t lock; unsigned long irq_mask; - unsigned base; - unsigned out_state; + unsigned int base; + unsigned int out_state; }; -static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) { if (offset > 15) return GPIO_LINE_DIRECTION_IN; @@ -56,22 +57,23 @@ static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) return GPIO_LINE_DIRECTION_OUT; } -static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) { return 0; } static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { chip->set(chip, offset, value); return 0; } -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset-16); + const unsigned int mask = BIT(offset-16); if (offset < 16) return -EINVAL; @@ -96,10 +98,11 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip, return 0; } -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset); + const unsigned int mask = BIT(offset); unsigned long flags; if (offset > 15) @@ -180,7 +183,7 @@ static void idio_16_irq_unmask(struct irq_data *data) } } -static int idio_16_irq_set_type(struct irq_data *data, unsigned flow_type) +static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) { /* The only valid irq types are none and both-edges */ if (flow_type != IRQ_TYPE_NONE && diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 0386ede53f3a..c55e821c63b6 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c @@ -113,10 +113,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (pdata->gpio_en_mask & (1 << i)) dev->lut[gpios++] = 1 << i; - if (gpios < 1) { - ret = -EINVAL; - goto err; - } + if (gpios < 1) + return -EINVAL; gc = &dev->gpio_chip; gc->direction_input = adp5520_gpio_direction_input; @@ -148,18 +146,10 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to write\n"); - goto err; + return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); - if (ret) - goto err; - - platform_set_drvdata(pdev, dev); - return 0; - -err: - return ret; + return devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); } static struct platform_driver adp5520_gpio_driver = { diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index b5917c48e4dc..6af51feda06f 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -78,7 +78,6 @@ static const struct gpio_chip altr_a10sr_gc = { static int altr_a10sr_gpio_probe(struct platform_device *pdev) { struct altr_a10sr_gpio *gpio; - int ret; struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -91,15 +90,7 @@ static int altr_a10sr_gpio_probe(struct platform_device *pdev) gpio->gp.parent = pdev->dev.parent; gpio->gp.of_node = pdev->dev.of_node; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static const struct of_device_id altr_a10sr_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 678ddd375891..9b780dc5d390 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -234,7 +234,6 @@ static int ath79_gpio_probe(struct platform_device *pdev) ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; - platform_set_drvdata(pdev, ctrl); if (np) { err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); @@ -290,13 +289,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) girq->handler = handle_simple_irq; } - err = devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); - if (err) { - dev_err(dev, - "cannot add AR71xx GPIO chip, error=%d", err); - return err; - } - return 0; + return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); } static struct platform_driver ath79_gpio_driver = { diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c index df6102b57734..9a4d55f703bb 100644 --- a/drivers/gpio/gpio-bd9571mwv.c +++ b/drivers/gpio/gpio-bd9571mwv.c @@ -97,25 +97,16 @@ static const struct gpio_chip template_chip = { 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->regmap = dev_get_regmap(pdev->dev.parent, NULL); gpio->chip = template_chip; gpio->chip.parent = pdev->dev.parent; - 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; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct platform_device_id bd9571mwv_gpio_id_table[] = { diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 9aa59afdcbbf..559188d80c2b 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -196,7 +196,6 @@ static int da9052_gpio_probe(struct platform_device *pdev) { struct da9052_gpio *gpio; struct da9052_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -209,15 +208,7 @@ static int da9052_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9052_gpio_driver = { diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c index 6ad0c37b862e..49446a030f10 100644 --- a/drivers/gpio/gpio-da9055.c +++ b/drivers/gpio/gpio-da9055.c @@ -133,7 +133,6 @@ static int da9055_gpio_probe(struct platform_device *pdev) { struct da9055_gpio *gpio; struct da9055_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -146,15 +145,7 @@ static int da9055_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9055_gpio_driver = { diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index d3233cc4b76b..3eb13d6d31ef 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -13,17 +13,15 @@ #include <linux/io.h> #include <linux/ioport.h> #include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/platform_data/gpio-dwapb.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/reset.h> -#include <linux/spinlock.h> -#include <linux/platform_data/gpio-dwapb.h> #include <linux/slab.h> +#include <linux/spinlock.h> #include "gpiolib.h" #include "gpiolib-acpi.h" @@ -297,9 +295,6 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) irq_hw_number_t bit = irqd_to_hwirq(d); unsigned long level, polarity, flags; - if (type & ~IRQ_TYPE_SENSE_MASK) - return -EINVAL; - spin_lock_irqsave(&gc->bgpio_lock, flags); level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); polarity = dwapb_read(gpio, GPIO_INT_POLARITY); @@ -531,17 +526,13 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, struct dwapb_port_property *pp) { - struct device_node *np = NULL; - int irq = -ENXIO, j; - - if (fwnode_property_read_bool(fwnode, "interrupt-controller")) - np = to_of_node(fwnode); + int irq, j; for (j = 0; j < pp->ngpio; j++) { - if (np) - irq = of_irq_get(np, j); - else if (has_acpi_companion(dev)) + if (has_acpi_companion(dev)) irq = platform_get_irq_optional(to_platform_device(dev), j); + else + irq = fwnode_irq_get(fwnode, j); if (irq > 0) pp->irq[j] = irq; } diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c new file mode 100644 index 000000000000..50003ad2e589 --- /dev/null +++ b/drivers/gpio/gpio-idt3243x.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Driver for IDT/Renesas 79RC3243x Interrupt Controller */ + +#include <linux/bitops.h> +#include <linux/gpio/driver.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#define IDT_PIC_IRQ_PEND 0x00 +#define IDT_PIC_IRQ_MASK 0x08 + +#define IDT_GPIO_DIR 0x00 +#define IDT_GPIO_DATA 0x04 +#define IDT_GPIO_ILEVEL 0x08 +#define IDT_GPIO_ISTAT 0x0C + +struct idt_gpio_ctrl { + struct gpio_chip gc; + void __iomem *pic; + void __iomem *gpio; + u32 mask_cache; +}; + +static void idt_gpio_dispatch(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + unsigned int bit, virq; + unsigned long pending; + + chained_irq_enter(host_chip, desc); + + pending = readl(ctrl->pic + IDT_PIC_IRQ_PEND); + pending &= ~ctrl->mask_cache; + for_each_set_bit(bit, &pending, gc->ngpio) { + virq = irq_linear_revmap(gc->irq.domain, bit); + if (virq) + generic_handle_irq(virq); + } + + chained_irq_exit(host_chip, desc); +} + +static int idt_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned int sense = flow_type & IRQ_TYPE_SENSE_MASK; + unsigned long flags; + u32 ilevel; + + /* hardware only supports level triggered */ + if (sense == IRQ_TYPE_NONE || (sense & IRQ_TYPE_EDGE_BOTH)) + return -EINVAL; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ilevel = readl(ctrl->gpio + IDT_GPIO_ILEVEL); + if (sense & IRQ_TYPE_LEVEL_HIGH) + ilevel |= BIT(d->hwirq); + else if (sense & IRQ_TYPE_LEVEL_LOW) + ilevel &= ~BIT(d->hwirq); + + writel(ilevel, ctrl->gpio + IDT_GPIO_ILEVEL); + irq_set_handler_locked(d, handle_level_irq); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + return 0; +} + +static void idt_gpio_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + writel(~BIT(d->hwirq), ctrl->gpio + IDT_GPIO_ISTAT); +} + +static void idt_gpio_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache |= BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static void idt_gpio_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache &= ~BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static int idt_gpio_irq_init_hw(struct gpio_chip *gc) +{ + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + /* Mask interrupts. */ + ctrl->mask_cache = 0xffffffff; + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + return 0; +} + +static struct irq_chip idt_gpio_irqchip = { + .name = "IDTGPIO", + .irq_mask = idt_gpio_mask, + .irq_ack = idt_gpio_ack, + .irq_unmask = idt_gpio_unmask, + .irq_set_type = idt_gpio_irq_set_type +}; + +static int idt_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; + struct idt_gpio_ctrl *ctrl; + unsigned int parent_irq; + int ngpios; + int ret; + + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + ctrl->gpio = devm_platform_ioremap_resource_byname(pdev, "gpio"); + if (IS_ERR(ctrl->gpio)) + return PTR_ERR(ctrl->gpio); + + ctrl->gc.parent = dev; + + ret = bgpio_init(&ctrl->gc, &pdev->dev, 4, ctrl->gpio + IDT_GPIO_DATA, + NULL, NULL, ctrl->gpio + IDT_GPIO_DIR, NULL, 0); + if (ret) { + dev_err(dev, "bgpio_init failed\n"); + return ret; + } + + ret = device_property_read_u32(dev, "ngpios", &ngpios); + if (!ret) + ctrl->gc.ngpio = ngpios; + + if (device_property_read_bool(dev, "interrupt-controller")) { + ctrl->pic = devm_platform_ioremap_resource_byname(pdev, "pic"); + if (IS_ERR(ctrl->pic)) + return PTR_ERR(ctrl->pic); + + parent_irq = platform_get_irq(pdev, 0); + if (!parent_irq) + return -EINVAL; + + girq = &ctrl->gc.irq; + girq->chip = &idt_gpio_irqchip; + girq->init_hw = idt_gpio_irq_init_hw; + girq->parent_handler = idt_gpio_dispatch; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + + girq->parents[0] = parent_irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + } + + return devm_gpiochip_add_data(&pdev->dev, &ctrl->gc, ctrl); +} + +static const struct of_device_id idt_gpio_of_match[] = { + { .compatible = "idt,32434-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, idt_gpio_of_match); + +static struct platform_driver idt_gpio_driver = { + .probe = idt_gpio_probe, + .driver = { + .name = "idt3243x-gpio", + .of_match_table = idt_gpio_of_match, + }, +}; +module_platform_driver(idt_gpio_driver); + +MODULE_DESCRIPTION("IDT 79RC3243x GPIO/PIC Driver"); +MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-logicvc.c b/drivers/gpio/gpio-logicvc.c index 015632cf159f..992cc958a43f 100644 --- a/drivers/gpio/gpio-logicvc.c +++ b/drivers/gpio/gpio-logicvc.c @@ -114,10 +114,8 @@ static int logicvc_gpio_probe(struct platform_device *pdev) } base = devm_ioremap_resource(dev, &res); - if (IS_ERR(base)) { - dev_err(dev, "Failed to map I/O base\n"); + if (IS_ERR(base)) return PTR_ERR(base); - } logicvc_gpio_regmap_config.max_register = resource_size(&res) - logicvc_gpio_regmap_config.reg_stride; diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index d7e73876a3b9..0a9d746a0fe0 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -144,12 +144,9 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc, static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, unsigned int offset, int value) { + struct gpio_chip *gc = &chip->gc; + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); int curr, irq, irq_type, ret = 0; - struct gpio_desc *desc; - struct gpio_chip *gc; - - gc = &chip->gc; - desc = &gc->gpiodev->descs[offset]; mutex_lock(&chip->lock); @@ -369,7 +366,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, priv->chip = chip; priv->offset = i; - priv->desc = &gc->gpiodev->descs[i]; + priv->desc = gpiochip_get_desc(gc, i); debugfs_create_file(name, 0200, chip->dbg_dir, priv, &gpio_mockup_debugfs_ops); diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 524b668eb1ac..31a336b86ff2 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -229,14 +229,14 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) return rv; } -static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); return irq_find_mapping(port->domain, offset); } -static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); u32 mask = 1 << offset; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index c91d05651596..f5cfc0698799 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1241,6 +1241,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, + { .compatible = "onnn,pca9655", .data = OF_953X(16, PCA_INT), }, { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, { } diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 134cedf151a7..69c219742083 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -178,12 +178,6 @@ static int gpio_regmap_direction_output(struct gpio_chip *chip, return gpio_regmap_set_direction(chip, offset, true); } -void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data) -{ - gpio->driver_data = data; -} -EXPORT_SYMBOL_GPL(gpio_regmap_set_drvdata); - void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) { return gpio->driver_data; @@ -226,6 +220,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config return ERR_PTR(-ENOMEM); gpio->parent = config->parent; + gpio->driver_data = config->drvdata; gpio->regmap = config->regmap; gpio->ngpio_per_reg = config->ngpio_per_reg; gpio->reg_stride = config->reg_stride; @@ -311,9 +306,9 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio) } EXPORT_SYMBOL_GPL(gpio_regmap_unregister); -static void devm_gpio_regmap_unregister(struct device *dev, void *res) +static void devm_gpio_regmap_unregister(void *res) { - gpio_regmap_unregister(*(struct gpio_regmap **)res); + gpio_regmap_unregister(res); } /** @@ -330,20 +325,17 @@ static void devm_gpio_regmap_unregister(struct device *dev, void *res) struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, const struct gpio_regmap_config *config) { - struct gpio_regmap **ptr, *gpio; - - ptr = devres_alloc(devm_gpio_regmap_unregister, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct gpio_regmap *gpio; + int ret; gpio = gpio_regmap_register(config); - if (!IS_ERR(gpio)) { - *ptr = gpio; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + + if (IS_ERR(gpio)) + return gpio; + + ret = devm_add_action_or_reset(dev, devm_gpio_regmap_unregister, gpio); + if (ret) + return ERR_PTR(ret); return gpio; } diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index 6eca531b7d96..49aac2bb8d2c 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -122,7 +122,6 @@ static int spics_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spear_spics *spics; - int ret; spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL); if (!spics) @@ -148,8 +147,6 @@ static int spics_gpio_probe(struct platform_device *pdev) &spics->cs_enable_shift)) goto err_dt_data; - platform_set_drvdata(pdev, spics); - spics->chip.ngpio = NUM_OF_GPIO; spics->chip.base = -1; spics->chip.request = spics_request; @@ -163,14 +160,7 @@ static int spics_gpio_probe(struct platform_device *pdev) spics->chip.owner = THIS_MODULE; spics->last_off = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); - if (ret) { - dev_err(&pdev->dev, "unable to add gpio chip\n"); - return ret; - } - - dev_info(&pdev->dev, "spear spics registered\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); err_dt_data: dev_err(&pdev->dev, "DT probe failed\n"); diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index 36ea8a3bd451..25c37edcbc6c 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -222,7 +222,6 @@ static int sprd_gpio_probe(struct platform_device *pdev) { struct gpio_irq_chip *irq; struct sprd_gpio *sprd_gpio; - int ret; sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL); if (!sprd_gpio) @@ -259,14 +258,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) irq->num_parents = 1; irq->parents = &sprd_gpio->irq; - ret = devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, sprd_gpio); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); } static const struct of_device_id sprd_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index a74bb97a41e2..392fcab06ab8 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -398,15 +398,7 @@ static int gsta_probe(struct platform_device *dev) return err; } - err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); - if (err < 0) { - dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n", - -err); - return err; - } - - platform_set_drvdata(dev, chip); - return 0; + return devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); } static struct platform_driver sta2x11_gpio_platform_driver = { diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index b94ef8181428..dd4d58b4ae49 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -449,6 +449,11 @@ static void stmpe_init_irq_valid_mask(struct gpio_chip *gc, } } +static void stmpe_gpio_disable(void *stmpe) +{ + stmpe_disable(stmpe, STMPE_BLOCK_GPIO); +} + static int stmpe_gpio_probe(struct platform_device *pdev) { struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); @@ -461,7 +466,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) return -EINVAL; } - stmpe_gpio = kzalloc(sizeof(*stmpe_gpio), GFP_KERNEL); + stmpe_gpio = devm_kzalloc(&pdev->dev, sizeof(*stmpe_gpio), GFP_KERNEL); if (!stmpe_gpio) return -ENOMEM; @@ -489,7 +494,11 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); if (ret) - goto out_free; + return ret; + + ret = devm_add_action_or_reset(&pdev->dev, stmpe_gpio_disable, stmpe); + if (ret) + return ret; if (irq > 0) { struct gpio_irq_chip *girq; @@ -499,7 +508,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) "stmpe-gpio", stmpe_gpio); if (ret) { dev_err(&pdev->dev, "unable to get irq: %d\n", ret); - goto out_disable; + return ret; } girq = &stmpe_gpio->chip.irq; @@ -514,22 +523,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) girq->init_valid_mask = stmpe_init_irq_valid_mask; } - ret = gpiochip_add_data(&stmpe_gpio->chip, stmpe_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - goto out_disable; - } - - platform_set_drvdata(pdev, stmpe_gpio); - - return 0; - -out_disable: - stmpe_disable(stmpe, STMPE_BLOCK_GPIO); - gpiochip_remove(&stmpe_gpio->chip); -out_free: - kfree(stmpe_gpio); - return ret; + return devm_gpiochip_add_data(&pdev->dev, &stmpe_gpio->chip, stmpe_gpio); } static struct platform_driver stmpe_gpio_driver = { diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 55b8dbd13d11..8d158492488f 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -357,16 +357,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, - tc3589x_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tc3589x_gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, tc3589x_gpio); } static struct platform_driver tc3589x_gpio_driver = { diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 05974b760796..d38980b9923a 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -730,18 +730,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) offset += port->pins; } - platform_set_drvdata(pdev, gpio); - - err = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); - if (err < 0) - return err; - - return 0; -} - -static int tegra186_gpio_remove(struct platform_device *pdev) -{ - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); } #define TEGRA186_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -913,7 +902,6 @@ static struct platform_driver tegra186_gpio_driver = { .of_match_table = tegra186_gpio_of_match, }, .probe = tegra186_gpio_probe, - .remove = tegra186_gpio_remove, }; module_platform_driver(tegra186_gpio_driver); diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index 43a1150055ce..3517debe2b0b 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -187,7 +187,6 @@ static int tps65218_gpio_probe(struct platform_device *pdev) { struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent); struct tps65218_gpio *tps65218_gpio; - int ret; tps65218_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65218_gpio), GFP_KERNEL); @@ -201,16 +200,8 @@ static int tps65218_gpio_probe(struct platform_device *pdev) tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, - tps65218_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65218_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, + tps65218_gpio); } static const struct of_device_id tps65218_dt_match[] = { diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 9b6cc74f47c8..da0304b764a5 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -76,7 +76,6 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) { struct tps6586x_platform_data *pdata; struct tps6586x_gpio *tps6586x_gpio; - int ret; pdata = dev_get_platdata(pdev->dev.parent); tps6586x_gpio = devm_kzalloc(&pdev->dev, @@ -106,16 +105,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) else tps6586x_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, - tps6586x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps6586x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, + tps6586x_gpio); } static struct platform_driver tps6586x_gpio_driver = { diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 0c0b445c75c0..7fa8c841081f 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -165,16 +165,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev) } skip_init: - ret = devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, - tps65910_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65910_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, + tps65910_gpio); } static struct platform_driver tps65910_gpio_driver = { diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c index 510d9ed9fd2a..fab771cb6a87 100644 --- a/drivers/gpio/gpio-tps65912.c +++ b/drivers/gpio/gpio-tps65912.c @@ -99,7 +99,6 @@ static int tps65912_gpio_probe(struct platform_device *pdev) { struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); struct tps65912_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -109,16 +108,7 @@ static int tps65912_gpio_probe(struct platform_device *pdev) gpio->gpio_chip = template_chip; gpio->gpio_chip.parent = tps->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, - gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio); } static const struct platform_device_id tps65912_gpio_id_table[] = { diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c index f7f5f770e0fb..423b7bc30ae8 100644 --- a/drivers/gpio/gpio-tps68470.c +++ b/drivers/gpio/gpio-tps68470.c @@ -125,7 +125,6 @@ static const char *tps68470_names[TPS68470_N_GPIO] = { static int tps68470_gpio_probe(struct platform_device *pdev) { struct tps68470_gpio_data *tps68470_gpio; - int ret; tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), GFP_KERNEL); @@ -146,16 +145,7 @@ static int tps68470_gpio_probe(struct platform_device *pdev) tps68470_gpio->gc.base = -1; tps68470_gpio->gc.parent = &pdev->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, - tps68470_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps68470_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio); } static struct platform_driver tps68470_gpio_driver = { diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c index 0e3d19828eb1..47455810bdb9 100644 --- a/drivers/gpio/gpio-visconti.c +++ b/drivers/gpio/gpio-visconti.c @@ -187,15 +187,7 @@ static int visconti_gpio_probe(struct platform_device *pdev) girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_level_irq; - ret = devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); - if (ret) { - dev_err(dev, "failed to add GPIO chip\n"); - return ret; - } - - platform_set_drvdata(pdev, priv); - - return ret; + return devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); } static const struct of_device_id visconti_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index a3a32a77041f..9cf1e5ebb352 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -261,7 +261,6 @@ static int wm831x_gpio_probe(struct platform_device *pdev) struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = &wm831x->pdata; struct wm831x_gpio *wm831x_gpio; - int ret; wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio), GFP_KERNEL); @@ -280,16 +279,7 @@ static int wm831x_gpio_probe(struct platform_device *pdev) wm831x_gpio->gpio_chip.of_node = wm831x->dev->of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, - wm831x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm831x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, wm831x_gpio); } static struct platform_driver wm831x_gpio_driver = { diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index 460f0a4b04bd..b1b131fb9804 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c @@ -105,7 +105,6 @@ static int wm8350_gpio_probe(struct platform_device *pdev) struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent); struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev); struct wm8350_gpio_data *wm8350_gpio; - int ret; wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio), GFP_KERNEL); @@ -121,16 +120,7 @@ static int wm8350_gpio_probe(struct platform_device *pdev) else wm8350_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, - wm8350_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm8350_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, wm8350_gpio); } static struct platform_driver wm8350_gpio_driver = { diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 9af89cf7f6bc..f4a474cef32d 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -263,7 +263,6 @@ static int wm8994_gpio_probe(struct platform_device *pdev) struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev); struct wm8994_gpio *wm8994_gpio; - int ret; wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio), GFP_KERNEL); @@ -279,17 +278,7 @@ static int wm8994_gpio_probe(struct platform_device *pdev) else wm8994_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, - wm8994_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - return ret; - } - - platform_set_drvdata(pdev, wm8994_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, wm8994_gpio); } static struct platform_driver wm8994_gpio_driver = { diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index 532b0df8a1f2..fb4b0c67aeef 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -159,7 +159,6 @@ static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume); static int xgene_gpio_probe(struct platform_device *pdev) { struct xgene_gpio *gpio; - int err = 0; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -183,15 +182,7 @@ static int xgene_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio); - err = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (err) { - dev_err(&pdev->dev, - "failed to register gpiochip.\n"); - return err; - } - - dev_info(&pdev->dev, "X-Gene GPIO driver registered.\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct of_device_id xgene_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 136557e7dd3c..c329c3a606e8 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -5,6 +5,7 @@ * Copyright 2008 - 2013 Xilinx, Inc. */ +#include <linux/bitmap.h> #include <linux/bitops.h> #include <linux/clk.h> #include <linux/errno.h> @@ -23,7 +24,8 @@ #define XGPIO_DATA_OFFSET (0x0) /* Data register */ #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ -#define XGPIO_CHANNEL_OFFSET 0x8 +#define XGPIO_CHANNEL0_OFFSET 0x0 +#define XGPIO_CHANNEL1_OFFSET 0x8 #define XGPIO_GIER_OFFSET 0x11c /* Global Interrupt Enable */ #define XGPIO_GIER_IE BIT(31) @@ -43,56 +45,101 @@ * struct xgpio_instance - Stores information about GPIO device * @gc: GPIO chip * @regs: register block - * @gpio_width: GPIO width for every channel - * @gpio_state: GPIO write state shadow register - * @gpio_last_irq_read: GPIO read state register from last interrupt - * @gpio_dir: GPIO direction shadow register + * @hw_map: GPIO pin mapping on hardware side + * @sw_map: GPIO pin mapping on software side + * @state: GPIO write state shadow register + * @last_irq_read: GPIO read state register from last interrupt + * @dir: GPIO direction shadow register * @gpio_lock: Lock used for synchronization * @irq: IRQ used by GPIO device * @irqchip: IRQ chip - * @irq_enable: GPIO IRQ enable/disable bitfield - * @irq_rising_edge: GPIO IRQ rising edge enable/disable bitfield - * @irq_falling_edge: GPIO IRQ falling edge enable/disable bitfield + * @enable: GPIO IRQ enable/disable bitfield + * @rising_edge: GPIO IRQ rising edge enable/disable bitfield + * @falling_edge: GPIO IRQ falling edge enable/disable bitfield * @clk: clock resource for this driver */ struct xgpio_instance { struct gpio_chip gc; void __iomem *regs; - unsigned int gpio_width[2]; - u32 gpio_state[2]; - u32 gpio_last_irq_read[2]; - u32 gpio_dir[2]; + DECLARE_BITMAP(hw_map, 64); + DECLARE_BITMAP(sw_map, 64); + DECLARE_BITMAP(state, 64); + DECLARE_BITMAP(last_irq_read, 64); + DECLARE_BITMAP(dir, 64); spinlock_t gpio_lock; /* For serializing operations */ int irq; struct irq_chip irqchip; - u32 irq_enable[2]; - u32 irq_rising_edge[2]; - u32 irq_falling_edge[2]; + DECLARE_BITMAP(enable, 64); + DECLARE_BITMAP(rising_edge, 64); + DECLARE_BITMAP(falling_edge, 64); struct clk *clk; }; -static inline int xgpio_index(struct xgpio_instance *chip, int gpio) +static inline int xgpio_from_bit(struct xgpio_instance *chip, int bit) { - if (gpio >= chip->gpio_width[0]) - return 1; + return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64); +} - return 0; +static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio) +{ + return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64); } -static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio) +static inline u32 xgpio_get_value32(const unsigned long *map, int bit) { - if (xgpio_index(chip, gpio)) - return XGPIO_CHANNEL_OFFSET; + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); - return 0; + return (map[index] >> offset) & 0xFFFFFFFFul; +} + +static inline void xgpio_set_value32(unsigned long *map, int bit, u32 v) +{ + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); + + map[index] &= ~(0xFFFFFFFFul << offset); + map[index] |= v << offset; +} + +static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch) +{ + switch (ch) { + case 0: + return XGPIO_CHANNEL0_OFFSET; + case 1: + return XGPIO_CHANNEL1_OFFSET; + default: + return -EINVAL; + } } -static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) +static void xgpio_read_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) { - if (xgpio_index(chip, gpio)) - return gpio - chip->gpio_width[0]; + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_set_value32(a, bit, xgpio_readreg(addr)); +} + +static void xgpio_write_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) +{ + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_writereg(addr, xgpio_get_value32(a, bit)); +} + +static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) +{ + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); + + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_read_ch(chip, reg, bit, a); +} + +static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) +{ + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); - return gpio; + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_write_ch(chip, reg, bit, a); } /** @@ -109,12 +156,12 @@ static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { struct xgpio_instance *chip = gpiochip_get_data(gc); - u32 val; + int bit = xgpio_to_bit(chip, gpio); + DECLARE_BITMAP(state, 64); - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio)); + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, state); - return !!(val & BIT(xgpio_offset(chip, gpio))); + return test_bit(bit, state); } /** @@ -130,19 +177,14 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write to GPIO signal and set its direction to output */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); + __assign_bit(bit, chip->state, val); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -159,37 +201,22 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { + DECLARE_BITMAP(hw_mask, 64); + DECLARE_BITMAP(hw_bits, 64); + DECLARE_BITMAP(state, 64); unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, 0); - int offset, i; + + bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64); + bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64); spin_lock_irqsave(&chip->gpio_lock, flags); - /* Write to GPIO signals */ - for (i = 0; i < gc->ngpio; i++) { - if (*mask == 0) - break; - /* Once finished with an index write it out to the register */ - if (index != xgpio_index(chip, i)) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, - chip->gpio_state[index]); - spin_unlock_irqrestore(&chip->gpio_lock, flags); - index = xgpio_index(chip, i); - spin_lock_irqsave(&chip->gpio_lock, flags); - } - if (__test_and_clear_bit(i, mask)) { - offset = xgpio_offset(chip, i); - if (test_bit(i, bits)) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - } - } + bitmap_replace(state, chip->state, hw_bits, hw_mask, 64); + + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, state); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, chip->gpio_state[index]); + bitmap_copy(chip->state, state, 64); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -207,15 +234,13 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Set the GPIO bit in shadow register and set direction as input */ - chip->gpio_dir[index] |= BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + __set_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -238,23 +263,17 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write state of GPIO signal */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + __assign_bit(bit, chip->state, val); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); /* Clear the GPIO bit in shadow register and set direction as output */ - chip->gpio_dir[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + __clear_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -267,16 +286,8 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) */ static void xgpio_save_regs(struct xgpio_instance *chip) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); - - if (!chip->gpio_width[1]) - return; - - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_state[1]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_dir[1]); + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, chip->state); + xgpio_write_ch_all(chip, XGPIO_TRI_OFFSET, chip->dir); } static int xgpio_request(struct gpio_chip *chip, unsigned int offset) @@ -302,8 +313,8 @@ static int __maybe_unused xgpio_suspend(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_suspend(dev); } if (!irqd_is_wakeup_set(data)) @@ -348,8 +359,8 @@ static int __maybe_unused xgpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_resume(dev); } if (!irqd_is_wakeup_set(data)) @@ -391,18 +402,17 @@ static void xgpio_irq_mask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); + u32 mask = BIT(bit / 32), temp; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] &= ~BIT(offset); + __clear_bit(bit, chip->enable); - if (!chip->irq_enable[index]) { + if (xgpio_get_value32(chip->enable, bit) == 0) { /* Disable per channel interrupt */ - u32 temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - - temp &= ~BIT(index); + temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); + temp &= ~mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); } spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -417,30 +427,26 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); - u32 old_enable = chip->irq_enable[index]; + int bit = xgpio_to_bit(chip, irq_offset); + u32 old_enable = xgpio_get_value32(chip->enable, bit); + u32 mask = BIT(bit / 32), val; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] |= BIT(offset); + __set_bit(bit, chip->enable); - if (!old_enable) { + if (old_enable == 0) { /* Clear any existing per-channel interrupts */ - u32 val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET) & - BIT(index); - - if (val) - xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); + val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); + val &= mask; + xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); /* Update GPIO IRQ read data before enabling interrupt*/ - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); - chip->gpio_last_irq_read[index] = val; + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, chip->last_irq_read); /* Enable per channel interrupt */ val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - val |= BIT(index); + val |= mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val); } @@ -459,8 +465,7 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) { struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); /* * The Xilinx GPIO hardware provides a single interrupt status @@ -470,16 +475,16 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) */ switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_BOTH: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __set_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_RISING: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] &= ~BIT(offset); + __set_bit(bit, chip->rising_edge); + __clear_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_FALLING: - chip->irq_rising_edge[index] &= ~BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __clear_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; default: return -EINVAL; @@ -496,46 +501,44 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) static void xgpio_irqhandler(struct irq_desc *desc) { struct xgpio_instance *chip = irq_desc_get_handler_data(desc); + struct gpio_chip *gc = &chip->gc; struct irq_chip *irqchip = irq_desc_get_chip(desc); - u32 num_channels = chip->gpio_width[1] ? 2 : 1; - u32 offset = 0, index; - u32 status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); - + DECLARE_BITMAP(rising, 64); + DECLARE_BITMAP(falling, 64); + DECLARE_BITMAP(all, 64); + int irq_offset; + u32 status; + u32 bit; + + status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status); chained_irq_enter(irqchip, desc); - for (index = 0; index < num_channels; index++) { - if ((status & BIT(index))) { - unsigned long rising_events, falling_events, all_events; - unsigned long flags; - u32 data, bit; - unsigned int irq; - - spin_lock_irqsave(&chip->gpio_lock, flags); - data = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); - rising_events = data & - ~chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_rising_edge[index]; - falling_events = ~data & - chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_falling_edge[index]; - dev_dbg(chip->gc.parent, - "IRQ chan %u rising 0x%lx falling 0x%lx\n", - index, rising_events, falling_events); - all_events = rising_events | falling_events; - chip->gpio_last_irq_read[index] = data; - spin_unlock_irqrestore(&chip->gpio_lock, flags); - - for_each_set_bit(bit, &all_events, 32) { - irq = irq_find_mapping(chip->gc.irq.domain, - offset + bit); - generic_handle_irq(irq); - } - } - offset += chip->gpio_width[index]; + + spin_lock(&chip->gpio_lock); + + xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all); + + bitmap_complement(rising, chip->last_irq_read, 64); + bitmap_and(rising, rising, all, 64); + bitmap_and(rising, rising, chip->enable, 64); + bitmap_and(rising, rising, chip->rising_edge, 64); + + bitmap_complement(falling, all, 64); + bitmap_and(falling, falling, chip->last_irq_read, 64); + bitmap_and(falling, falling, chip->enable, 64); + bitmap_and(falling, falling, chip->falling_edge, 64); + + bitmap_copy(chip->last_irq_read, all, 64); + bitmap_or(all, rising, falling, 64); + + spin_unlock(&chip->gpio_lock); + + dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling); + + for_each_set_bit(bit, all, 64) { + irq_offset = xgpio_from_bit(chip, bit); + generic_handle_irq(irq_find_mapping(gc->irq.domain, irq_offset)); } chained_irq_exit(irqchip, desc); @@ -556,6 +559,9 @@ static int xgpio_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; u32 is_dual = 0; u32 cells = 2; + u32 width[2]; + u32 state[2]; + u32 dir[2]; struct gpio_irq_chip *girq; u32 temp; @@ -565,13 +571,25 @@ static int xgpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); + /* First, check if the device is dual-channel */ + of_property_read_u32(np, "xlnx,is-dual", &is_dual); + + /* Setup defaults */ + memset32(width, 0, ARRAY_SIZE(width)); + memset32(state, 0, ARRAY_SIZE(state)); + memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir)); + /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0])) - chip->gpio_state[0] = 0x0; + of_property_read_u32(np, "xlnx,dout-default", &state[0]); + of_property_read_u32(np, "xlnx,dout-default-2", &state[1]); + + bitmap_from_arr32(chip->state, state, 64); /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0])) - chip->gpio_dir[0] = 0xFFFFFFFF; + of_property_read_u32(np, "xlnx,tri-default", &dir[0]); + of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]); + + bitmap_from_arr32(chip->dir, dir, 64); /* Update cells with gpio-cells value */ if (of_property_read_u32(np, "#gpio-cells", &cells)) @@ -586,42 +604,29 @@ static int xgpio_probe(struct platform_device *pdev) * Check device node and parent device node for device width * and assume default width of 32 */ - if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0])) - chip->gpio_width[0] = 32; + if (of_property_read_u32(np, "xlnx,gpio-width", &width[0])) + width[0] = 32; - if (chip->gpio_width[0] > 32) + if (width[0] > 32) return -EINVAL; - spin_lock_init(&chip->gpio_lock); + if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1])) + width[1] = 32; - if (of_property_read_u32(np, "xlnx,is-dual", &is_dual)) - is_dual = 0; - - if (is_dual) { - /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default-2", - &chip->gpio_state[1])) - chip->gpio_state[1] = 0x0; - - /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default-2", - &chip->gpio_dir[1])) - chip->gpio_dir[1] = 0xFFFFFFFF; - - /* - * Check device node and parent device node for device width - * and assume default width of 32 - */ - if (of_property_read_u32(np, "xlnx,gpio2-width", - &chip->gpio_width[1])) - chip->gpio_width[1] = 32; - - if (chip->gpio_width[1] > 32) - return -EINVAL; - } + if (width[1] > 32) + return -EINVAL; + + /* Setup software pin mapping */ + bitmap_set(chip->sw_map, 0, width[0] + width[1]); + + /* Setup hardware pin mapping */ + bitmap_set(chip->hw_map, 0, width[0]); + bitmap_set(chip->hw_map, 32, width[1]); + + spin_lock_init(&chip->gpio_lock); chip->gc.base = -1; - chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; + chip->gc.ngpio = bitmap_weight(chip->hw_map, 64); chip->gc.parent = &pdev->dev; chip->gc.direction_input = xgpio_dir_in; chip->gc.direction_output = xgpio_dir_out; diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 3521c1dc3ac0..f0cb8ccd03ed 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -736,6 +736,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) disable_irq(gpio->irq); @@ -753,6 +758,11 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); int ret; + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) enable_irq(gpio->irq); @@ -1001,8 +1011,11 @@ err_pm_dis: static int zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); + int ret; - pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); @@ -1020,22 +1033,7 @@ static struct platform_driver zynq_gpio_driver = { .remove = zynq_gpio_remove, }; -/** - * zynq_gpio_init - Initial driver registration call - * - * Return: value from platform_driver_register - */ -static int __init zynq_gpio_init(void) -{ - return platform_driver_register(&zynq_gpio_driver); -} -postcore_initcall(zynq_gpio_init); - -static void __exit zynq_gpio_exit(void) -{ - platform_driver_unregister(&zynq_gpio_driver); -} -module_exit(zynq_gpio_exit); +module_platform_driver(zynq_gpio_driver); MODULE_AUTHOR("Xilinx Inc."); MODULE_DESCRIPTION("Zynq GPIO driver"); diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index ae49bb23c6ed..4098bc7f88b7 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -66,9 +66,8 @@ static ssize_t direction_show(struct device *dev, mutex_lock(&data->mutex); gpiod_get_direction(desc); - status = sprintf(buf, "%s\n", - test_bit(FLAG_IS_OUT, &desc->flags) - ? "out" : "in"); + status = sysfs_emit(buf, "%s\n", + test_bit(FLAG_IS_OUT, &desc->flags) ? "out" : "in"); mutex_unlock(&data->mutex); @@ -109,13 +108,9 @@ static ssize_t value_show(struct device *dev, mutex_lock(&data->mutex); status = gpiod_get_value_cansleep(desc); - if (status < 0) - goto err; + if (status >= 0) + status = sysfs_emit(buf, "%zd\n", status); - buf[0] = '0' + status; - buf[1] = '\n'; - status = 2; -err: mutex_unlock(&data->mutex); return status; @@ -249,11 +244,11 @@ static ssize_t edge_show(struct device *dev, mutex_lock(&data->mutex); for (i = 0; i < ARRAY_SIZE(trigger_types); i++) { - if (data->irq_flags == trigger_types[i].flags) { - status = sprintf(buf, "%s\n", trigger_types[i].name); + if (data->irq_flags == trigger_types[i].flags) break; - } } + if (i < ARRAY_SIZE(trigger_types)) + status = sysfs_emit(buf, "%s\n", trigger_types[i].name); mutex_unlock(&data->mutex); @@ -312,10 +307,7 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value) if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) return 0; - if (value) - set_bit(FLAG_ACTIVE_LOW, &desc->flags); - else - clear_bit(FLAG_ACTIVE_LOW, &desc->flags); + assign_bit(FLAG_ACTIVE_LOW, &desc->flags, value); /* reconfigure poll(2) support if enabled on one edge only */ if (flags == GPIO_IRQF_TRIGGER_FALLING || @@ -336,8 +328,8 @@ static ssize_t active_low_show(struct device *dev, mutex_lock(&data->mutex); - status = sprintf(buf, "%d\n", - !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); + status = sysfs_emit(buf, "%d\n", + !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); mutex_unlock(&data->mutex); @@ -415,7 +407,7 @@ static ssize_t base_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", chip->base); + return sysfs_emit(buf, "%d\n", chip->base); } static DEVICE_ATTR_RO(base); @@ -424,7 +416,7 @@ static ssize_t label_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", chip->label ? : ""); + return sysfs_emit(buf, "%s\n", chip->label ?: ""); } static DEVICE_ATTR_RO(label); @@ -433,7 +425,7 @@ static ssize_t ngpio_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", chip->ngpio); + return sysfs_emit(buf, "%u\n", chip->ngpio); } static DEVICE_ATTR_RO(ngpio); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1427c1be749b..27c07108496d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2004,9 +2004,6 @@ const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; - if (offset >= gc->ngpio) - return NULL; - desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return NULL; @@ -2543,21 +2540,28 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int first, j; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; + + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2580,8 +2584,10 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, ret = gpio_chip_get_multiple(gc, mask, bits); if (ret) { - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); return ret; } @@ -2601,8 +2607,10 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, j); } - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } @@ -2826,21 +2834,28 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int count = 0; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; + + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2885,8 +2900,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, if (count != 0) gpio_chip_set_multiple(gc, mask, bits); - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index 334dd928042b..a9f7b7faf57b 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -37,6 +37,9 @@ struct regmap; * offset to a register/bitmask pair. If not * given the default gpio_regmap_simple_xlate() * is used. + * @drvdata: (Optional) Pointer to driver specific data which is + * not used by gpio-remap but is provided "as is" to the + * driver callback(s). * * The ->reg_mask_xlate translates a given base address and GPIO offset to * register and mask pair. The base address is one of the given register @@ -78,13 +81,14 @@ struct gpio_regmap_config { int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, unsigned int offset, unsigned int *reg, unsigned int *mask); + + void *drvdata; }; struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config); void gpio_regmap_unregister(struct gpio_regmap *gpio); struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, const struct gpio_regmap_config *config); -void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data); void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio); #endif /* _LINUX_GPIO_REGMAP_H */ diff --git a/lib/bitmap.c b/lib/bitmap.c index 6e29b2aae6ba..9401d39e4722 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -793,8 +793,6 @@ int bitmap_parse(const char *start, unsigned int buflen, } EXPORT_SYMBOL(bitmap_parse); - -#ifdef CONFIG_NUMA /** * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap * @buf: pointer to a bitmap @@ -903,6 +901,7 @@ void bitmap_remap(unsigned long *dst, const unsigned long *src, set_bit(bitmap_ord_to_pos(new, n % w, nbits), dst); } } +EXPORT_SYMBOL(bitmap_remap); /** * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit @@ -940,7 +939,9 @@ int bitmap_bitremap(int oldbit, const unsigned long *old, else return bitmap_ord_to_pos(new, n % w, bits); } +EXPORT_SYMBOL(bitmap_bitremap); +#ifdef CONFIG_NUMA /** * bitmap_onto - translate one bitmap relative to another * @dst: resulting translated bitmap |