forked from Minki/linux
gpio: updates for v5.14
- 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmDiz88ACgkQEacuoBRx 13JIaxAAhM0kWMBCs14BT79ZteLQj+QvtA/EvNvC3yfAkrlzCc75yHP4ocV21O9E BIdbBqvA5RdOcL8akdL8V895wjM3CdUlFpjfkdVGeN7wZzagVEpb9z8j7Ba1YwSu dUzrvuPsiDigxDCMGDwHybrNxis54J61HV9mAw0LxXPERHQwbCUMdx4pbdBLUKcu qVX+mK2hzzgORkt9ntlnYQSKsnSiWan8g4q8zntdQOjJAVN473WySXmhfONlXkAV OH88/moDBk7Y3QdtUNAB7h/fu23F7Y++NoiStN2uilgrJ38/3PWi0eASK4XWx1jr LOx5PIRTRQNU+AHQ+EVP23XFH/1EKjPXGyZwcpprS5BkpJaBnUVCMnhoHdLX4LqV axxbszaMATxpTNt7lcLrklvzVb0D/zvvNtwuMyjWvPZ/GMLDyPfaVMFUqSGcFwQ+ ufdHAeIPAwU/AA9tF3OjiijsGWV+nnOWunfh2TdioHRzFM6LTM5lkcruoFmqjQxp 2IMTNGbhsr8xv6y64x3Cq/03k7hV5lwgn/J4CJL7LGa9VHI+VgGEKMluoINRxfc/ qIN9MT1iVu81ttCwTokSL08Le6ijqpP3LC8hMTRSCJpxZBna5KWbMm8gppYrXE1r EAGnEpnihM36Px9hPj4zJQYU/Ly8SIpYB4BHWs4F8eMOxgFKuWo= =IF0T -----END PGP SIGNATURE----- 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() ...
This commit is contained in:
commit
b805259942
@ -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";
|
||||
};
|
185
Documentation/devicetree/bindings/gpio/gpio-davinci.yaml
Normal file
185
Documentation/devicetree/bindings/gpio/gpio-davinci.yaml
Normal file
@ -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";
|
||||
};
|
@ -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>;
|
||||
};
|
@ -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>;
|
||||
};
|
@ -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; */
|
||||
};
|
99
Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml
Normal file
99
Documentation/devicetree/bindings/gpio/gpio-stp-xway.yaml
Normal file
@ -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>;
|
||||
};
|
||||
...
|
@ -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>;
|
||||
};
|
59
Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
Normal file
59
Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
Normal file
@ -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>;
|
||||
};
|
67
Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml
Normal file
67
Documentation/devicetree/bindings/gpio/idt,32434-gpio.yaml
Normal file
@ -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>;
|
||||
};
|
103
Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
Normal file
103
Documentation/devicetree/bindings/gpio/nxp,pcf8575.yaml
Normal file
@ -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>;
|
||||
};
|
||||
};
|
@ -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>.
|
@ -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>;
|
||||
};
|
108
Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml
Normal file
108
Documentation/devicetree/bindings/gpio/ti,omap-gpio.yaml
Normal file
@ -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";
|
||||
};
|
||||
};
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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 &&
|
||||
|
@ -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 = {
|
||||
|
@ -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[] = {
|
||||
|
@ -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 = {
|
||||
|
@ -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[] = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
206
drivers/gpio/gpio-idt3243x.c
Normal file
206
drivers/gpio/gpio-idt3243x.c
Normal file
@ -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");
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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), },
|
||||
{ }
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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[] = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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[] = {
|
||||
|
@ -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 = {
|
||||
|
@ -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[] = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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[] = {
|
||||
|
@ -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 0;
|
||||
return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64);
|
||||
}
|
||||
|
||||
static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio)
|
||||
static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio)
|
||||
{
|
||||
if (xgpio_index(chip, gpio))
|
||||
return XGPIO_CHANNEL_OFFSET;
|
||||
|
||||
return 0;
|
||||
return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64);
|
||||
}
|
||||
|
||||
static inline int xgpio_offset(struct xgpio_instance *chip, int gpio)
|
||||
static inline u32 xgpio_get_value32(const unsigned long *map, int bit)
|
||||
{
|
||||
if (xgpio_index(chip, gpio))
|
||||
return gpio - chip->gpio_width[0];
|
||||
const size_t index = BIT_WORD(bit);
|
||||
const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5);
|
||||
|
||||
return gpio;
|
||||
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 void xgpio_read_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a)
|
||||
{
|
||||
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);
|
||||
|
||||
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_writereg(chip->regs + XGPIO_DATA_OFFSET +
|
||||
index * XGPIO_CHANNEL_OFFSET, chip->gpio_state[index]);
|
||||
xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, state);
|
||||
|
||||
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);
|
||||
spin_lock(&chip->gpio_lock);
|
||||
|
||||
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];
|
||||
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;
|
||||
|
||||
if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1]))
|
||||
width[1] = 32;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user