gpio updates for v5.17

- new testing module: gpio-sim that is scheduled to replace gpio-mockup
 - initial changes aiming at converting all GPIO drivers to using the fwnode
   interface and limiting any references to OF symbols to gpiolib-of.c
 - add support for Tegra234 and Tegra241 to gpio-tegra186
 - add support for new models (SSD201 and SSD202D) to gpio-msc313
 - add basic support for interrupts to gpio-aggregator
 - add support for AMDIF031 HID device to gpio-amdpt
 - drop support for unused platforms in gpio-xlp
 - cleanup leftovers from the removal of the legacy Samsung Exynos GPIO driver
 - use raw spinlocks in gpio-aspeed and gpio-aspeed-sgpio to make PREEMPT_RT
   happy
 - generalize the common 'ngpios' device property by reading it in the core
   gpiolib code so that we can remove duplicate reads from drivers
 - allow line names from device properties to override names set by drivers
 - code shrink in gpiod_add_lookup_table()
 - add new model to the DT bindings for gpio-vf610
 - convert DT bindings for tegra devices to YAML
 - improvements to interrupt handling in gpio-rcar and gpio-rockchip
 - updates to intel drivers from Andy (details in the merge commit)
 - some minor tweaks, improvements and coding-style fixes all around the
   subsystem
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmHdpawACgkQEacuoBRx
 13KBTxAA1uB3zOqq5L9gn7cLR8Pi1/N4o7ltB0uwIFGJ8X5+jkHqkEi2TRa7Nyv1
 OODt/C2g8iguhynQJ1g//ZW12tzoThwI9fUzixZ9FRBMmX5oHeCcrS/YAYP4GDJY
 T9KOiXPDJ+vHV7SbM4k8gIlMHFk5Uq1jjvNnDIebzyBlyzAKxH9dIY3r1zt0Y4BR
 aKlAD5pxmLDAMAWVlTRo5e/W/Xd0ob0LCkDwlgozb3gwoPQbQQIPHuw+jPl5cMR2
 wBRNVFuJLi5dnpyrOoCXWWDQzeQzw8x+5vlwZfLkr2pF4FfDWoxefmbrDulzU+Au
 t6TULGcFKhLalyozY2D2mWNo8lMs4fDt/SXrDHwgS/cmGpq7RUGfvFuV6a9IOukP
 /uqoMYviIRswJuvPBs6dBNFaZxJkw4cWzd9tIzywb07mpkUCwX8wARwg+dZGvdQt
 4aAJwkJHuR29bEpDVfWwd2UV+fdAX5RiVQqLznNzGK51O+vS4UklYyWtO44R+fgm
 F81y2zOo0ly9xA6YkGjoSATnWDTmzTQSrnwcFv9J9UewY3PJpQc4xgqvZysur5cb
 0k/kuf9eWazmo46gW3ztv8GfXogDko8DEKrEgGs47tg97RDR5YbzOkOmnsqWvoUd
 nSVyx6vs2ijXsEi96FKhfTrU0AT2YcAIbEWjQoQvBR+3zkase7I=
 =OUhL
 -----END PGP SIGNATURE-----

Merge tag 'gpio-updates-for-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio updates from Bartosz Golaszewski:
 "The gpio-sim module is back, this time without any changes to
  configfs. This results in a less elegant user-space interface but I
  never got any follow-up on the committable items and didn't want to
  delay this module for several more months.

  Other than that we have support for several new models and some
  support going away. We started working on converting GPIO drivers to
  using fwnode exclusively in order to limit references to OF symbols to
  gpiolib-of.c exclusively. We also have regular tweaks and improvements
  all over the place.

  Summary:

   - new testing module: gpio-sim that is scheduled to replace
     gpio-mockup

   - initial changes aiming at converting all GPIO drivers to using the
     fwnode interface and limiting any references to OF symbols to
     gpiolib-of.c

   - add support for Tegra234 and Tegra241 to gpio-tegra186

   - add support for new models (SSD201 and SSD202D) to gpio-msc313

   - add basic support for interrupts to gpio-aggregator

   - add support for AMDIF031 HID device to gpio-amdpt

   - drop support for unused platforms in gpio-xlp

   - cleanup leftovers from the removal of the legacy Samsung Exynos
     GPIO driver

   - use raw spinlocks in gpio-aspeed and gpio-aspeed-sgpio to make
     PREEMPT_RT happy

   - generalize the common 'ngpios' device property by reading it in the
     core gpiolib code so that we can remove duplicate reads from
     drivers

   - allow line names from device properties to override names set by
     drivers

   - code shrink in gpiod_add_lookup_table()

   - add new model to the DT bindings for gpio-vf610

   - convert DT bindings for tegra devices to YAML

   - improvements to interrupt handling in gpio-rcar and gpio-rockchip

   - updates to intel drivers from Andy (details in the merge commit)

   - some minor tweaks, improvements and coding-style fixes all around
     the subsystem"

* tag 'gpio-updates-for-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (59 commits)
  gpio: rcar: Propagate errors from devm_request_irq()
  gpio: rcar: Use platform_get_irq() to get the interrupt
  gpio: ts5500: Use platform_get_irq() to get the interrupt
  gpio: dwapb: Switch to use fwnode instead of of_node
  gpiolib: acpi: make fwnode take precedence in struct gpio_chip
  dt-bindings: gpio: samsung: drop unused bindings
  gpio: max3191x: Use bitmap_free() to free bitmap
  gpio: regmap: Switch to use fwnode instead of of_node
  gpio: tegra186: Add support for Tegra241
  dt-bindings: gpio: Add Tegra241 support
  gpio: brcmstb: Use local variable to access OF node
  gpio: Remove unused local OF node pointers
  gpio: sim: add missing fwnode_handle_put() in gpio_sim_probe()
  gpio: msc313: Add support for SSD201 and SSD202D
  gpio: msc313: Code clean ups
  dt-bindings: gpio: msc313: Add offsets for ssd20xd
  dt-bindings: gpio: msc313: Add compatible for ssd20xd
  gpio: sim: fix uninitialized ret variable
  gpio: Propagate firmware node from a parent device
  gpio: Setup parent device and get rid of unnecessary of_node assignment
  ...
This commit is contained in:
Linus Torvalds 2022-01-11 12:31:35 -08:00
commit c288ea6798
75 changed files with 3415 additions and 634 deletions

View File

@ -0,0 +1,134 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Configfs GPIO Simulator
=======================
The configfs GPIO Simulator (gpio-sim) provides a way to create simulated GPIO
chips for testing purposes. The lines exposed by these chips can be accessed
using the standard GPIO character device interface as well as manipulated
using sysfs attributes.
Creating simulated chips
------------------------
The gpio-sim module registers a configfs subsystem called ``'gpio-sim'``. For
details of the configfs filesystem, please refer to the configfs documentation.
The user can create a hierarchy of configfs groups and items as well as modify
values of exposed attributes. Once the chip is instantiated, this hierarchy
will be translated to appropriate device properties. The general structure is:
**Group:** ``/config/gpio-sim``
This is the top directory of the gpio-sim configfs tree.
**Group:** ``/config/gpio-sim/gpio-device``
**Attribute:** ``/config/gpio-sim/gpio-device/dev_name``
**Attribute:** ``/config/gpio-sim/gpio-device/live``
This is a directory representing a GPIO platform device. The ``'dev_name'``
attribute is read-only and allows the user-space to read the platform device
name (e.g. ``'gpio-sim.0'``). The ``'live'`` attribute allows to trigger the
actual creation of the device once it's fully configured. The accepted values
are: ``'1'`` to enable the simulated device and ``'0'`` to disable and tear
it down.
**Group:** ``/config/gpio-sim/gpio-device/gpio-bankX``
**Attribute:** ``/config/gpio-sim/gpio-device/gpio-bankX/chip_name``
**Attribute:** ``/config/gpio-sim/gpio-device/gpio-bankX/num_lines``
This group represents a bank of GPIOs under the top platform device. The
``'chip_name'`` attribute is read-only and allows the user-space to read the
device name of the bank device. The ``'num_lines'`` attribute allows to specify
the number of lines exposed by this bank.
**Group:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY``
**Attribute:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY/name``
This group represents a single line at the offset Y. The 'name' attribute
allows to set the line name as represented by the 'gpio-line-names' property.
**Item:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY/hog``
**Attribute:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY/hog/name``
**Attribute:** ``/config/gpio-sim/gpio-device/gpio-bankX/lineY/hog/direction``
This item makes the gpio-sim module hog the associated line. The ``'name'``
attribute specifies the in-kernel consumer name to use. The ``'direction'``
attribute specifies the hog direction and must be one of: ``'input'``,
``'output-high'`` and ``'output-low'``.
Inside each bank directory, there's a set of attributes that can be used to
configure the new chip. Additionally the user can ``mkdir()`` subdirectories
inside the chip's directory that allow to pass additional configuration for
specific lines. The name of those subdirectories must take the form of:
``'line<offset>'`` (e.g. ``'line0'``, ``'line20'``, etc.) as the name will be
used by the module to assign the config to the specific line at given offset.
Once the confiuration is complete, the ``'live'`` attribute must be set to 1 in
order to instantiate the chip. It can be set back to 0 to destroy the simulated
chip. The module will synchronously wait for the new simulated device to be
successfully probed and if this doesn't happen, writing to ``'live'`` will
result in an error.
Simulated GPIO chips can also be defined in device-tree. The compatible string
must be: ``"gpio-simulator"``. Supported properties are:
``"gpio-sim,label"`` - chip label
Other standard GPIO properties (like ``"gpio-line-names"``, ``"ngpios"`` or
``"gpio-hog"``) are also supported. Please refer to the GPIO documentation for
details.
An example device-tree code defining a GPIO simulator:
.. code-block :: none
gpio-sim {
compatible = "gpio-simulator";
bank0 {
gpio-controller;
#gpio-cells = <2>;
ngpios = <16>;
gpio-sim,label = "dt-bank0";
gpio-line-names = "", "sim-foo", "", "sim-bar";
};
bank1 {
gpio-controller;
#gpio-cells = <2>;
ngpios = <8>;
gpio-sim,label = "dt-bank1";
line3 {
gpio-hog;
gpios = <3 0>;
output-high;
line-name = "sim-hog-from-dt";
};
};
};
Manipulating simulated lines
----------------------------
Each simulated GPIO chip creates a separate sysfs group under its device
directory for each exposed line
(e.g. ``/sys/devices/platform/gpio-sim.X/gpiochipY/``). The name of each group
is of the form: ``'sim_gpioX'`` where X is the offset of the line. Inside each
group there are two attibutes:
``pull`` - allows to read and set the current simulated pull setting for
every line, when writing the value must be one of: ``'pull-up'``,
``'pull-down'``
``value`` - allows to read the current value of the line which may be
different from the pull if the line is being driven from
user-space

View File

@ -1,41 +0,0 @@
Samsung Exynos4 GPIO Controller
Required properties:
- compatible: Compatible property value should be "samsung,exynos4-gpio>".
- reg: Physical base address of the controller and length of memory mapped
region.
- #gpio-cells: Should be 4. The syntax of the gpio specifier used by client nodes
should be the following with values derived from the SoC user manual.
<[phandle of the gpio controller node]
[pin number within the gpio controller]
[mux function]
[flags and pull up/down]
[drive strength]>
Values for gpio specifier:
- Pin number: is a value between 0 to 7.
- Flags and Pull Up/Down: 0 - Pull Up/Down Disabled.
1 - Pull Down Enabled.
3 - Pull Up Enabled.
Bit 16 (0x00010000) - Input is active low.
- Drive Strength: 0 - 1x,
1 - 3x,
2 - 2x,
3 - 4x
- gpio-controller: Specifies that the node is a gpio controller.
- #address-cells: should be 1.
- #size-cells: should be 1.
Example:
gpa0: gpio-controller@11400000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "samsung,exynos4-gpio";
reg = <0x11400000 0x20>;
#gpio-cells = <4>;
gpio-controller;
};

View File

@ -24,6 +24,9 @@ properties:
- items:
- const: fsl,imx7ulp-gpio
- const: fsl,vf610-gpio
- items:
- const: fsl,imx8ulp-gpio
- const: fsl,imx7ulp-gpio
reg:
description: The first reg tuple represents the PORT module, the second tuple

View File

@ -14,7 +14,9 @@ properties:
pattern: "^gpio@[0-9a-f]+$"
compatible:
const: mstar,msc313-gpio
enum:
- mstar,msc313-gpio
- sstar,ssd20xd-gpio
reg:
maxItems: 1

View File

@ -1,165 +0,0 @@
NVIDIA Tegra186 GPIO controllers
Tegra186 contains two GPIO controllers; a main controller and an "AON"
controller. This binding document applies to both controllers. The register
layouts for the controllers share many similarities, but also some significant
differences. Hence, this document describes closely related but different
bindings and compatible values.
The Tegra186 GPIO controller allows software to set the IO direction of, and
read/write the value of, numerous GPIO signals. Routing of GPIO signals to
package balls is under the control of a separate pin controller HW block. Two
major sets of registers exist:
a) Security registers, which allow configuration of allowed access to the GPIO
register set. These registers exist in a single contiguous block of physical
address space. The size of this block, and the security features available,
varies between the different GPIO controllers.
Access to this set of registers is not necessary in all circumstances. Code
that wishes to configure access to the GPIO registers needs access to these
registers to do so. Code which simply wishes to read or write GPIO data does not
need access to these registers.
b) GPIO registers, which allow manipulation of the GPIO signals. In some GPIO
controllers, these registers are exposed via multiple "physical aliases" in
address space, each of which access the same underlying state. See the hardware
documentation for rationale. Any particular GPIO client is expected to access
just one of these physical aliases.
Tegra HW documentation describes a unified naming convention for all GPIOs
implemented by the SoC. Each GPIO is assigned to a port, and a port may control
a number of GPIOs. Thus, each GPIO is named according to an alphabetical port
name and an integer GPIO name within the port. For example, GPIO_PA0, GPIO_PN6,
or GPIO_PCC3.
The number of ports implemented by each GPIO controller varies. The number of
implemented GPIOs within each port varies. GPIO registers within a controller
are grouped and laid out according to the port they affect.
The mapping from port name to the GPIO controller that implements that port, and
the mapping from port name to register offset within a controller, are both
extremely non-linear. The header file <dt-bindings/gpio/tegra186-gpio.h>
describes the port-level mapping. In that file, the naming convention for ports
matches the HW documentation. The values chosen for the names are alphabetically
sorted within a particular controller. Drivers need to map between the DT GPIO
IDs and HW register offsets using a lookup table.
Each GPIO controller can generate a number of interrupt signals. Each signal
represents the aggregate status for all GPIOs within a set of ports. Thus, the
number of interrupt signals generated by a controller varies as a rough function
of the number of ports it implements. Note that the HW documentation refers to
both the overall controller HW module and the sets-of-ports as "controllers".
Each GPIO controller in fact generates multiple interrupts signals for each set
of ports. Each GPIO may be configured to feed into a specific one of the
interrupt signals generated by a set-of-ports. The intent is for each generated
signal to be routed to a different CPU, thus allowing different CPUs to each
handle subsets of the interrupts within a port. The status of each of these
per-port-set signals is reported via a separate register. Thus, a driver needs
to know which status register to observe. This binding currently defines no
configuration mechanism for this. By default, drivers should use register
GPIO_${port}_INTERRUPT_STATUS_G1_0. Future revisions to the binding could
define a property to configure this.
Required properties:
- compatible
Array of strings.
One of:
- "nvidia,tegra186-gpio".
- "nvidia,tegra186-gpio-aon".
- "nvidia,tegra194-gpio".
- "nvidia,tegra194-gpio-aon".
- reg-names
Array of strings.
Contains a list of names for the register spaces described by the reg
property. May contain the following entries, in any order:
- "gpio": Mandatory. GPIO control registers. This may cover either:
a) The single physical alias that this OS should use.
b) All physical aliases that exist in the controller. This is
appropriate when the OS is responsible for managing assignment of
the physical aliases.
- "security": Optional. Security configuration registers.
Users of this binding MUST look up entries in the reg property by name,
using this reg-names property to do so.
- reg
Array of (physical base address, length) tuples.
Must contain one entry per entry in the reg-names property, in a matching
order.
- interrupts
Array of interrupt specifiers.
The interrupt outputs from the HW block, one per set of ports, in the
order the HW manual describes them. The number of entries required varies
depending on compatible value:
- "nvidia,tegra186-gpio": 6 entries.
- "nvidia,tegra186-gpio-aon": 1 entry.
- "nvidia,tegra194-gpio": 6 entries.
- "nvidia,tegra194-gpio-aon": 1 entry.
- gpio-controller
Boolean.
Marks the device node as a GPIO controller/provider.
- #gpio-cells
Single-cell integer.
Must be <2>.
Indicates how many cells are used in a consumer's GPIO specifier.
In the specifier:
- The first cell is the pin number.
See <dt-bindings/gpio/tegra186-gpio.h>.
- The second cell contains flags:
- Bit 0 specifies polarity
- 0: Active-high (normal).
- 1: Active-low (inverted).
- interrupt-controller
Boolean.
Marks the device node as an interrupt controller/provider.
- #interrupt-cells
Single-cell integer.
Must be <2>.
Indicates how many cells are used in a consumer's interrupt specifier.
In the specifier:
- The first cell is the GPIO number.
See <dt-bindings/gpio/tegra186-gpio.h>.
- The second cell is contains flags:
- Bits [3:0] indicate trigger type and level:
- 1: Low-to-high edge triggered.
- 2: High-to-low edge triggered.
- 4: Active high level-sensitive.
- 8: Active low level-sensitive.
Valid combinations are 1, 2, 3, 4, 8.
Example:
#include <dt-bindings/interrupt-controller/irq.h>
gpio@2200000 {
compatible = "nvidia,tegra186-gpio";
reg-names = "security", "gpio";
reg =
<0x0 0x2200000 0x0 0x10000>,
<0x0 0x2210000 0x0 0x10000>;
interrupts =
<0 47 IRQ_TYPE_LEVEL_HIGH>,
<0 50 IRQ_TYPE_LEVEL_HIGH>,
<0 53 IRQ_TYPE_LEVEL_HIGH>,
<0 56 IRQ_TYPE_LEVEL_HIGH>,
<0 59 IRQ_TYPE_LEVEL_HIGH>,
<0 180 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio@c2f0000 {
compatible = "nvidia,tegra186-gpio-aon";
reg-names = "security", "gpio";
reg =
<0x0 0xc2f0000 0x0 0x1000>,
<0x0 0xc2f1000 0x0 0x1000>;
interrupts =
<0 60 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};

View File

@ -0,0 +1,214 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/nvidia,tegra186-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra GPIO Controller (Tegra186 and later)
maintainers:
- Thierry Reding <thierry.reding@gmail.com>
- Jon Hunter <jonathanh@nvidia.com>
description: |
Tegra186 contains two GPIO controllers; a main controller and an "AON"
controller. This binding document applies to both controllers. The register
layouts for the controllers share many similarities, but also some
significant differences. Hence, this document describes closely related but
different bindings and compatible values.
The Tegra186 GPIO controller allows software to set the IO direction of,
and read/write the value of, numerous GPIO signals. Routing of GPIO signals
to package balls is under the control of a separate pin controller hardware
block. Two major sets of registers exist:
a) Security registers, which allow configuration of allowed access to the
GPIO register set. These registers exist in a single contiguous block
of physical address space. The size of this block, and the security
features available, varies between the different GPIO controllers.
Access to this set of registers is not necessary in all circumstances.
Code that wishes to configure access to the GPIO registers needs access
to these registers to do so. Code which simply wishes to read or write
GPIO data does not need access to these registers.
b) GPIO registers, which allow manipulation of the GPIO signals. In some
GPIO controllers, these registers are exposed via multiple "physical
aliases" in address space, each of which access the same underlying
state. See the hardware documentation for rationale. Any particular
GPIO client is expected to access just one of these physical aliases.
Tegra HW documentation describes a unified naming convention for all GPIOs
implemented by the SoC. Each GPIO is assigned to a port, and a port may
control a number of GPIOs. Thus, each GPIO is named according to an
alphabetical port name and an integer GPIO name within the port. For
example, GPIO_PA0, GPIO_PN6, or GPIO_PCC3.
The number of ports implemented by each GPIO controller varies. The number
of implemented GPIOs within each port varies. GPIO registers within a
controller are grouped and laid out according to the port they affect.
The mapping from port name to the GPIO controller that implements that
port, and the mapping from port name to register offset within a
controller, are both extremely non-linear. The header file
<dt-bindings/gpio/tegra186-gpio.h> describes the port-level mapping. In
that file, the naming convention for ports matches the HW documentation.
The values chosen for the names are alphabetically sorted within a
particular controller. Drivers need to map between the DT GPIO IDs and HW
register offsets using a lookup table.
Each GPIO controller can generate a number of interrupt signals. Each
signal represents the aggregate status for all GPIOs within a set of
ports. Thus, the number of interrupt signals generated by a controller
varies as a rough function of the number of ports it implements. Note
that the HW documentation refers to both the overall controller HW
module and the sets-of-ports as "controllers".
Each GPIO controller in fact generates multiple interrupts signals for
each set of ports. Each GPIO may be configured to feed into a specific
one of the interrupt signals generated by a set-of-ports. The intent is
for each generated signal to be routed to a different CPU, thus allowing
different CPUs to each handle subsets of the interrupts within a port.
The status of each of these per-port-set signals is reported via a
separate register. Thus, a driver needs to know which status register to
observe. This binding currently defines no configuration mechanism for
this. By default, drivers should use register
GPIO_${port}_INTERRUPT_STATUS_G1_0. Future revisions to the binding could
define a property to configure this.
properties:
compatible:
enum:
- nvidia,tegra186-gpio
- nvidia,tegra186-gpio-aon
- nvidia,tegra194-gpio
- nvidia,tegra194-gpio-aon
- nvidia,tegra234-gpio
- nvidia,tegra234-gpio-aon
reg-names:
items:
- const: security
- const: gpio
minItems: 1
reg:
items:
- description: Security configuration registers.
- description: |
GPIO control registers. This may cover either:
a) The single physical alias that this OS should use.
b) All physical aliases that exist in the controller. This is
appropriate when the OS is responsible for managing assignment
of the physical aliases.
minItems: 1
interrupts:
description: The interrupt outputs from the HW block, one per set of
ports, in the order the HW manual describes them. The number of entries
required varies depending on compatible value.
gpio-controller: true
"#gpio-cells":
description: |
Indicates how many cells are used in a consumer's GPIO specifier. In the
specifier:
- The first cell is the pin number.
See <dt-bindings/gpio/tegra186-gpio.h>.
- The second cell contains flags:
- Bit 0 specifies polarity
- 0: Active-high (normal).
- 1: Active-low (inverted).
const: 2
interrupt-controller: true
"#interrupt-cells":
description: |
Indicates how many cells are used in a consumer's interrupt specifier.
In the specifier:
- The first cell is the GPIO number.
See <dt-bindings/gpio/tegra186-gpio.h>.
- The second cell is contains flags:
- Bits [3:0] indicate trigger type and level:
- 1: Low-to-high edge triggered.
- 2: High-to-low edge triggered.
- 4: Active high level-sensitive.
- 8: Active low level-sensitive.
Valid combinations are 1, 2, 3, 4, 8.
const: 2
allOf:
- if:
properties:
compatible:
contains:
enum:
- nvidia,tegra186-gpio
- nvidia,tegra194-gpio
- nvidia,tegra234-gpio
then:
properties:
interrupts:
minItems: 6
maxItems: 48
- if:
properties:
compatible:
contains:
enum:
- nvidia,tegra186-gpio-aon
- nvidia,tegra194-gpio-aon
- nvidia,tegra234-gpio-aon
then:
properties:
interrupts:
minItems: 1
maxItems: 4
required:
- compatible
- reg
- reg-names
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
gpio@2200000 {
compatible = "nvidia,tegra186-gpio";
reg-names = "security", "gpio";
reg = <0x2200000 0x10000>,
<0x2210000 0x10000>;
interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>,
<0 50 IRQ_TYPE_LEVEL_HIGH>,
<0 53 IRQ_TYPE_LEVEL_HIGH>,
<0 56 IRQ_TYPE_LEVEL_HIGH>,
<0 59 IRQ_TYPE_LEVEL_HIGH>,
<0 180 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
gpio@c2f0000 {
compatible = "nvidia,tegra186-gpio-aon";
reg-names = "security", "gpio";
reg = <0xc2f0000 0x1000>,
<0xc2f1000 0x1000>;
interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};

View File

@ -1,40 +0,0 @@
NVIDIA Tegra GPIO controller
Required properties:
- compatible : "nvidia,tegra<chip>-gpio"
- reg : Physical base address and length of the controller's registers.
- interrupts : The interrupt outputs from the controller. For Tegra20,
there should be 7 interrupts specified, and for Tegra30, there should
be 8 interrupts specified.
- #gpio-cells : Should be two. The first cell is the pin number and the
second cell is used to specify optional parameters:
- bit 0 specifies polarity (0 for normal, 1 for inverted)
- gpio-controller : Marks the device node as a GPIO 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.
Valid combinations are 1, 2, 3, 4, 8.
- interrupt-controller : Marks the device node as an interrupt controller.
Example:
gpio: gpio@6000d000 {
compatible = "nvidia,tegra20-gpio";
reg = < 0x6000d000 0x1000 >;
interrupts = < 0 32 0x04
0 33 0x04
0 34 0x04
0 35 0x04
0 55 0x04
0 87 0x04
0 89 0x04 >;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};

View File

@ -0,0 +1,110 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/nvidia,tegra20-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra GPIO Controller (Tegra20 - Tegra210)
maintainers:
- Thierry Reding <thierry.reding@gmail.com>
- Jon Hunter <jonathanh@nvidia.com>
properties:
compatible:
oneOf:
- enum:
- nvidia,tegra20-gpio
- nvidia,tegra30-gpio
- items:
- enum:
- nvidia,tegra114-gpio
- nvidia,tegra124-gpio
- nvidia,tegra210-gpio
- const: nvidia,tegra30-gpio
reg:
maxItems: 1
interrupts:
description: The interrupt outputs from the controller. For Tegra20,
there should be 7 interrupts specified, and for Tegra30, there should
be 8 interrupts specified.
"#gpio-cells":
description: The first cell is the pin number and the second cell is used
to specify the GPIO polarity (0 = active high, 1 = active low).
const: 2
gpio-controller: true
gpio-ranges:
maxItems: 1
"#interrupt-cells":
description: |
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.
Valid combinations are 1, 2, 3, 4, 8.
const: 2
interrupt-controller: true
allOf:
- if:
properties:
compatible:
contains:
const: nvidia,tegra30-gpio
then:
properties:
interrupts:
minItems: 8
maxItems: 8
else:
properties:
interrupts:
minItems: 7
maxItems: 7
required:
- compatible
- reg
- interrupts
- "#gpio-cells"
- gpio-controller
- "#interrupt-cells"
- interrupt-controller
additionalProperties:
type: object
required:
- gpio-hog
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
gpio: gpio@6000d000 {
compatible = "nvidia,tegra20-gpio";
reg = <0x6000d000 0x1000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};

View File

@ -77,7 +77,8 @@ examples:
gpio@10060000 {
compatible = "sifive,fu540-c000-gpio", "sifive,gpio0";
interrupt-parent = <&plic>;
interrupts = <7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22>;
interrupts = <7>, <8>, <9>, <10>, <11>, <12>, <13>, <14>, <15>, <16>,
<17>, <18>, <19>, <20>, <21>, <22>;
reg = <0x10060000 0x1000>;
clocks = <&tlclk PRCI_CLK_TLCLK>;
gpio-controller;

View File

@ -731,14 +731,12 @@ config GPIO_XILINX
Say yes here to support the Xilinx FPGA GPIO device.
config GPIO_XLP
tristate "Netlogic XLP GPIO support"
depends on OF_GPIO && (CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST)
tristate "Cavium ThunderX2 GPIO support"
depends on ARCH_THUNDER2 || COMPILE_TEST
select GPIOLIB_IRQCHIP
help
This driver provides support for GPIO interface on Netlogic XLP MIPS64
SoCs. Currently supported XLP variants are XLP8XX, XLP3XX, XLP2XX,
XLP9XX and XLP5XX. The same GPIO controller block is also present in
Cavium's ThunderX2 CN99XX SoCs.
This driver provides support for GPIO interface on Cavium's ThunderX2
CN99XX SoCs (Originally from Netlogic XLP).
If unsure, say N.
@ -1683,6 +1681,14 @@ config GPIO_VIRTIO
These virtual GPIOs can be routed to real GPIOs or attached to
simulators on the host (like QEMU).
config GPIO_SIM
tristate "GPIO Simulator Module"
select IRQ_SIM
select CONFIGFS_FS
help
This enables the GPIO simulator - a configfs-based GPIO testing
driver.
endmenu
endif

View File

@ -132,6 +132,7 @@ obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o
obj-$(CONFIG_GPIO_SIM) += gpio-sim.o
obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o

View File

@ -458,7 +458,6 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios,
chip->ngpio = num_gpios;
chip->label = adnp->client->name;
chip->parent = &adnp->client->dev;
chip->of_node = chip->parent->of_node;
chip->owner = THIS_MODULE;
if (is_irq_controller) {

View File

@ -371,6 +371,13 @@ static int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset,
return gpiod_set_config(fwd->descs[offset], config);
}
static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
return gpiod_to_irq(fwd->descs[offset]);
}
/**
* gpiochip_fwd_create() - Create a new GPIO forwarder
* @dev: Parent device pointer
@ -411,7 +418,8 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
for (i = 0; i < ngpios; i++) {
struct gpio_chip *parent = gpiod_to_chip(descs[i]);
dev_dbg(dev, "%u => gpio-%d\n", i, desc_to_gpio(descs[i]));
dev_dbg(dev, "%u => gpio %d irq %d\n", i,
desc_to_gpio(descs[i]), gpiod_to_irq(descs[i]));
if (gpiod_cansleep(descs[i]))
chip->can_sleep = true;
@ -429,6 +437,7 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
chip->get_multiple = gpio_fwd_get_multiple_locked;
chip->set = gpio_fwd_set;
chip->set_multiple = gpio_fwd_set_multiple_locked;
chip->to_irq = gpio_fwd_to_irq;
chip->base = -1;
chip->ngpio = ngpios;
fwd->descs = descs;

View File

@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#define PT_TOTAL_GPIO 8
#define PT_TOTAL_GPIO_EX 24
/* PCI-E MMIO register offsets */
#define PT_DIRECTION_REG 0x00
@ -103,10 +104,8 @@ static int pt_gpio_probe(struct platform_device *pdev)
pt_gpio->gc.owner = THIS_MODULE;
pt_gpio->gc.request = pt_gpio_request;
pt_gpio->gc.free = pt_gpio_free;
pt_gpio->gc.ngpio = PT_TOTAL_GPIO;
#if defined(CONFIG_OF_GPIO)
pt_gpio->gc.of_node = dev->of_node;
#endif
pt_gpio->gc.ngpio = (uintptr_t)device_get_match_data(dev);
ret = gpiochip_add_data(&pt_gpio->gc, pt_gpio);
if (ret) {
dev_err(dev, "Failed to register GPIO lib\n");
@ -133,8 +132,9 @@ static int pt_gpio_remove(struct platform_device *pdev)
}
static const struct acpi_device_id pt_gpio_acpi_match[] = {
{ "AMDF030", 0 },
{ "AMDIF030", 0 },
{ "AMDF030", PT_TOTAL_GPIO },
{ "AMDIF030", PT_TOTAL_GPIO },
{ "AMDIF031", PT_TOTAL_GPIO_EX },
{ },
};
MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match);

View File

@ -151,6 +151,8 @@ static int arizona_gpio_probe(struct platform_device *pdev)
struct arizona_gpio *arizona_gpio;
int ret;
device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
arizona_gpio = devm_kzalloc(&pdev->dev, sizeof(*arizona_gpio),
GFP_KERNEL);
if (!arizona_gpio)
@ -159,9 +161,6 @@ static int arizona_gpio_probe(struct platform_device *pdev)
arizona_gpio->arizona = arizona;
arizona_gpio->gpio_chip = template_chip;
arizona_gpio->gpio_chip.parent = &pdev->dev;
#ifdef CONFIG_OF_GPIO
arizona_gpio->gpio_chip.of_node = arizona->dev->of_node;
#endif
switch (arizona->type) {
case WM5102:

View File

@ -31,7 +31,7 @@ struct aspeed_sgpio {
struct gpio_chip chip;
struct irq_chip intc;
struct clk *pclk;
spinlock_t lock;
raw_spinlock_t lock;
void __iomem *base;
int irq;
};
@ -173,12 +173,12 @@ static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
enum aspeed_sgpio_reg reg;
int rc = 0;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
@ -215,11 +215,11 @@ static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
unsigned long flags;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
sgpio_set_value(gc, offset, val);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
@ -236,9 +236,9 @@ static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int v
/* No special action is required for setting the direction; we'll
* error-out in sgpio_set_value if this isn't an output GPIO */
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
rc = sgpio_set_value(gc, offset, val);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
@ -277,11 +277,11 @@ static void aspeed_sgpio_irq_ack(struct irq_data *d)
status_addr = bank_reg(gpio, bank, reg_irq_status);
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
iowrite32(bit, status_addr);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
@ -296,7 +296,7 @@ static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
addr = bank_reg(gpio, bank, reg_irq_enable);
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
reg = ioread32(addr);
if (set)
@ -306,7 +306,7 @@ static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
iowrite32(reg, addr);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
static void aspeed_sgpio_irq_mask(struct irq_data *d)
@ -355,7 +355,7 @@ static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
addr = bank_reg(gpio, bank, reg_irq_type0);
reg = ioread32(addr);
@ -372,7 +372,7 @@ static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type)
reg = (reg & ~bit) | type2;
iowrite32(reg, addr);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
irq_set_handler_locked(d, handler);
@ -467,7 +467,7 @@ static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
reg = bank_reg(gpio, to_bank(offset), reg_tolerance);
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
val = readl(reg);
@ -478,7 +478,7 @@ static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
writel(val, reg);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
@ -575,7 +575,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval |
ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL);
spin_lock_init(&gpio->lock);
raw_spin_lock_init(&gpio->lock);
gpio->chip.parent = &pdev->dev;
gpio->chip.ngpio = nr_gpios * 2;

View File

@ -53,7 +53,7 @@ struct aspeed_gpio_config {
struct aspeed_gpio {
struct gpio_chip chip;
struct irq_chip irqc;
spinlock_t lock;
raw_spinlock_t lock;
void __iomem *base;
int irq;
const struct aspeed_gpio_config *config;
@ -413,14 +413,14 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
unsigned long flags;
bool copro;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
__aspeed_gpio_set(gc, offset, val);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
@ -435,7 +435,7 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
if (!have_input(gpio, offset))
return -ENOTSUPP;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
reg = ioread32(addr);
reg &= ~GPIO_BIT(offset);
@ -445,7 +445,7 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
if (copro)
aspeed_gpio_copro_release(gpio, offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
@ -463,7 +463,7 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
if (!have_output(gpio, offset))
return -ENOTSUPP;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
reg = ioread32(addr);
reg |= GPIO_BIT(offset);
@ -474,7 +474,7 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
if (copro)
aspeed_gpio_copro_release(gpio, offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
@ -492,11 +492,11 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
if (!have_output(gpio, offset))
return GPIO_LINE_DIRECTION_IN;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
val = ioread32(bank_reg(gpio, bank, reg_dir)) & GPIO_BIT(offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return val ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
}
@ -539,14 +539,14 @@ static void aspeed_gpio_irq_ack(struct irq_data *d)
status_addr = bank_reg(gpio, bank, reg_irq_status);
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
iowrite32(bit, status_addr);
if (copro)
aspeed_gpio_copro_release(gpio, offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
@ -565,7 +565,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
addr = bank_reg(gpio, bank, reg_irq_enable);
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
reg = ioread32(addr);
@ -577,7 +577,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
if (copro)
aspeed_gpio_copro_release(gpio, offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
}
static void aspeed_gpio_irq_mask(struct irq_data *d)
@ -629,7 +629,7 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
addr = bank_reg(gpio, bank, reg_irq_type0);
@ -649,7 +649,7 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
if (copro)
aspeed_gpio_copro_release(gpio, offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
irq_set_handler_locked(d, handler);
@ -716,7 +716,7 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
treg = bank_reg(gpio, to_bank(offset), reg_tolerance);
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
copro = aspeed_gpio_copro_request(gpio, offset);
val = readl(treg);
@ -730,7 +730,7 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
if (copro)
aspeed_gpio_copro_release(gpio, offset);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
@ -856,7 +856,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
return rc;
}
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
if (timer_allocation_registered(gpio, offset)) {
rc = unregister_allocated_timer(gpio, offset);
@ -916,7 +916,7 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
configure_timer(gpio, offset, i);
out:
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
@ -927,13 +927,13 @@ static int disable_debounce(struct gpio_chip *chip, unsigned int offset)
unsigned long flags;
int rc;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
rc = unregister_allocated_timer(gpio, offset);
if (!rc)
configure_timer(gpio, offset, 0);
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
@ -1015,7 +1015,7 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
return -EINVAL;
bindex = offset >> 3;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
/* Sanity check, this shouldn't happen */
if (gpio->cf_copro_bankmap[bindex] == 0xff) {
@ -1036,7 +1036,7 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
if (bit)
*bit = GPIO_OFFSET(offset);
bail:
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
EXPORT_SYMBOL_GPL(aspeed_gpio_copro_grab_gpio);
@ -1060,7 +1060,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
return -EINVAL;
bindex = offset >> 3;
spin_lock_irqsave(&gpio->lock, flags);
raw_spin_lock_irqsave(&gpio->lock, flags);
/* Sanity check, this shouldn't happen */
if (gpio->cf_copro_bankmap[bindex] == 0) {
@ -1074,7 +1074,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
aspeed_gpio_change_cmd_source(gpio, bank, bindex,
GPIO_CMDSRC_ARM);
bail:
spin_unlock_irqrestore(&gpio->lock, flags);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return rc;
}
EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio);
@ -1148,7 +1148,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio->base))
return PTR_ERR(gpio->base);
spin_lock_init(&gpio->lock);
raw_spin_lock_init(&gpio->lock);
gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
if (!gpio_id)

View File

@ -606,7 +606,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
kona_gpio->pdev = pdev;
platform_set_drvdata(pdev, kona_gpio);
chip->of_node = dev->of_node;
chip->parent = dev;
chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK;
kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node,

View File

@ -121,7 +121,6 @@ static int bd71828_probe(struct platform_device *pdev)
* "gpio-reserved-ranges" and exclude them from control
*/
bdgpio->gpio.ngpio = 4;
bdgpio->gpio.of_node = dev->parent->of_node;
bdgpio->regmap = dev_get_regmap(dev->parent, NULL);
if (!bdgpio->regmap)
return -ENODEV;

View File

@ -703,9 +703,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
goto fail;
}
gc->of_node = np;
gc->owner = THIS_MODULE;
gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", dev->of_node);
gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
if (!gc->label) {
err = -ENOMEM;
goto fail;

View File

@ -163,12 +163,12 @@ static int creg_gpio_probe(struct platform_device *pdev)
spin_lock_init(&hcg->lock);
hcg->gc.parent = dev;
hcg->gc.label = dev_name(dev);
hcg->gc.base = -1;
hcg->gc.ngpio = ngpios;
hcg->gc.set = creg_gpio_set;
hcg->gc.direction_output = creg_gpio_dir_out;
hcg->gc.of_node = dev->of_node;
ret = devm_gpiochip_add_data(dev, &hcg->gc, hcg);
if (ret)

View File

@ -254,7 +254,6 @@ static int davinci_gpio_probe(struct platform_device *pdev)
#ifdef CONFIG_OF_GPIO
chips->chip.of_gpio_n_cells = 2;
chips->chip.parent = dev;
chips->chip.of_node = dev->of_node;
chips->chip.request = gpiochip_generic_request;
chips->chip.free = gpiochip_generic_free;
#endif

View File

@ -15,7 +15,6 @@
#include <linux/irq.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/reset.h>
@ -53,7 +52,9 @@
#define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */
#define GPIO_SWPORT_DDR_STRIDE 0x0c /* register stride 3*32 bits */
#define GPIO_REG_OFFSET_V1 0
#define GPIO_REG_OFFSET_V2 1
#define GPIO_REG_OFFSET_MASK BIT(0)
#define GPIO_INTMASK_V2 0x44
#define GPIO_INTTYPE_LEVEL_V2 0x34
@ -141,7 +142,7 @@ static inline u32 gpio_reg_v2_convert(unsigned int offset)
static inline u32 gpio_reg_convert(struct dwapb_gpio *gpio, unsigned int offset)
{
if (gpio->flags & GPIO_REG_OFFSET_V2)
if ((gpio->flags & GPIO_REG_OFFSET_MASK) == GPIO_REG_OFFSET_V2)
return gpio_reg_v2_convert(offset);
return offset;
@ -513,9 +514,7 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
return err;
}
#ifdef CONFIG_OF_GPIO
port->gc.of_node = to_of_node(pp->fwnode);
#endif
port->gc.fwnode = pp->fwnode;
port->gc.ngpio = pp->ngpio;
port->gc.base = pp->gpio_base;
@ -668,15 +667,15 @@ static int dwapb_get_clks(struct dwapb_gpio *gpio)
}
static const struct of_device_id dwapb_of_match[] = {
{ .compatible = "snps,dw-apb-gpio", .data = (void *)0},
{ .compatible = "snps,dw-apb-gpio", .data = (void *)GPIO_REG_OFFSET_V1},
{ .compatible = "apm,xgene-gpio-v2", .data = (void *)GPIO_REG_OFFSET_V2},
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dwapb_of_match);
static const struct acpi_device_id dwapb_acpi_match[] = {
{"HISI0181", 0},
{"APMC0D07", 0},
{"HISI0181", GPIO_REG_OFFSET_V1},
{"APMC0D07", GPIO_REG_OFFSET_V1},
{"APMC0D81", GPIO_REG_OFFSET_V2},
{ }
};

View File

@ -609,7 +609,6 @@ static int sprd_eic_probe(struct platform_device *pdev)
sprd_eic->chip.ngpio = pdata->num_eics;
sprd_eic->chip.base = -1;
sprd_eic->chip.parent = &pdev->dev;
sprd_eic->chip.of_node = pdev->dev.of_node;
sprd_eic->chip.direction_input = sprd_eic_direction_input;
switch (sprd_eic->type) {
case SPRD_EIC_DEBOUNCE:

View File

@ -306,7 +306,6 @@ static int em_gio_probe(struct platform_device *pdev)
}
gpio_chip = &p->gpio_chip;
gpio_chip->of_node = dev->of_node;
gpio_chip->direction_input = em_gio_direction_input;
gpio_chip->get = em_gio_get;
gpio_chip->direction_output = em_gio_direction_output;

View File

@ -82,7 +82,6 @@ static int __init gef_gpio_probe(struct platform_device *pdev)
gc->base = -1;
gc->ngpio = (u16)(uintptr_t)of_device_get_match_data(&pdev->dev);
gc->of_gpio_n_cells = 2;
gc->of_node = pdev->dev.of_node;
/* This function adds a memory mapped GPIO chip */
ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);

View File

@ -358,7 +358,6 @@ static int grgpio_probe(struct platform_device *ofdev)
priv->imask = gc->read_reg(regs + GRGPIO_IMASK);
priv->dev = &ofdev->dev;
gc->of_node = np;
gc->owner = THIS_MODULE;
gc->to_irq = grgpio_to_irq;
gc->label = devm_kasprintf(&ofdev->dev, GFP_KERNEL, "%pOF", np);

View File

@ -71,7 +71,6 @@ static int gw_pld_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct device_node *np = dev->of_node;
struct gw_pld *gw;
int ret;
@ -82,7 +81,6 @@ static int gw_pld_probe(struct i2c_client *client,
gw->chip.base = -1;
gw->chip.can_sleep = true;
gw->chip.parent = dev;
gw->chip.of_node = np;
gw->chip.owner = THIS_MODULE;
gw->chip.label = dev_name(dev);
gw->chip.ngpio = 8;

View File

@ -512,10 +512,10 @@ static int lpc32xx_gpio_probe(struct platform_device *pdev)
return PTR_ERR(reg_base);
for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
lpc32xx_gpiochip[i].chip.parent = &pdev->dev;
if (pdev->dev.of_node) {
lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
lpc32xx_gpiochip[i].reg_base = reg_base;
}
devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,

View File

@ -326,7 +326,7 @@ static void gpiod_set_array_single_value_cansleep(unsigned int ndescs,
bitmap_zero(values, ndescs);
gpiod_set_array_value_cansleep(ndescs, desc, info, values);
kfree(values);
bitmap_free(values);
}
static struct gpio_descs *devm_gpiod_get_array_optional_count(

View File

@ -98,9 +98,9 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
spin_lock_irqsave(&chip->spinlock, flags);
reg_val = ioread32(&chip->reg->regs[chip->ch].po);
if (val)
reg_val |= (1 << nr);
reg_val |= BIT(nr);
else
reg_val &= ~(1 << nr);
reg_val &= ~BIT(nr);
iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
spin_unlock_irqrestore(&chip->spinlock, flags);
@ -110,7 +110,7 @@ static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
{
struct ioh_gpio *chip = gpiochip_get_data(gpio);
return !!(ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr));
return !!(ioread32(&chip->reg->regs[chip->ch].pi) & BIT(nr));
}
static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
@ -122,16 +122,16 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
pm = ioread32(&chip->reg->regs[chip->ch].pm) &
((1 << num_ports[chip->ch]) - 1);
pm |= (1 << nr);
pm = ioread32(&chip->reg->regs[chip->ch].pm);
pm &= BIT(num_ports[chip->ch]) - 1;
pm |= BIT(nr);
iowrite32(pm, &chip->reg->regs[chip->ch].pm);
reg_val = ioread32(&chip->reg->regs[chip->ch].po);
if (val)
reg_val |= (1 << nr);
reg_val |= BIT(nr);
else
reg_val &= ~(1 << nr);
reg_val &= ~BIT(nr);
iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
spin_unlock_irqrestore(&chip->spinlock, flags);
@ -146,9 +146,9 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
pm = ioread32(&chip->reg->regs[chip->ch].pm) &
((1 << num_ports[chip->ch]) - 1);
pm &= ~(1 << nr);
pm = ioread32(&chip->reg->regs[chip->ch].pm);
pm &= BIT(num_ports[chip->ch]) - 1;
pm &= ~BIT(nr);
iowrite32(pm, &chip->reg->regs[chip->ch].pm);
spin_unlock_irqrestore(&chip->spinlock, flags);
@ -304,7 +304,7 @@ static void ioh_irq_unmask(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct ioh_gpio *chip = gc->private;
iowrite32(1 << (d->irq - chip->irq_base),
iowrite32(BIT(d->irq - chip->irq_base),
&chip->reg->regs[chip->ch].imaskclr);
}
@ -313,7 +313,7 @@ static void ioh_irq_mask(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct ioh_gpio *chip = gc->private;
iowrite32(1 << (d->irq - chip->irq_base),
iowrite32(BIT(d->irq - chip->irq_base),
&chip->reg->regs[chip->ch].imask);
}
@ -326,7 +326,7 @@ static void ioh_irq_disable(struct irq_data *d)
spin_lock_irqsave(&chip->spinlock, flags);
ien = ioread32(&chip->reg->regs[chip->ch].ien);
ien &= ~(1 << (d->irq - chip->irq_base));
ien &= ~BIT(d->irq - chip->irq_base);
iowrite32(ien, &chip->reg->regs[chip->ch].ien);
spin_unlock_irqrestore(&chip->spinlock, flags);
}
@ -340,7 +340,7 @@ static void ioh_irq_enable(struct irq_data *d)
spin_lock_irqsave(&chip->spinlock, flags);
ien = ioread32(&chip->reg->regs[chip->ch].ien);
ien |= 1 << (d->irq - chip->irq_base);
ien |= BIT(d->irq - chip->irq_base);
iowrite32(ien, &chip->reg->regs[chip->ch].ien);
spin_unlock_irqrestore(&chip->spinlock, flags);
}
@ -401,6 +401,7 @@ static int ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
static int ioh_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
int ret;
int i, j;
struct ioh_gpio *chip;
@ -410,19 +411,19 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__);
dev_err(dev, "%s : pci_enable_device failed", __func__);
goto err_pci_enable;
}
ret = pci_request_regions(pdev, KBUILD_MODNAME);
if (ret) {
dev_err(&pdev->dev, "pci_request_regions failed-%d", ret);
dev_err(dev, "pci_request_regions failed-%d", ret);
goto err_request_regions;
}
base = pci_iomap(pdev, 1, 0);
if (!base) {
dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
dev_err(dev, "%s : pci_iomap failed", __func__);
ret = -ENOMEM;
goto err_iomap;
}
@ -435,7 +436,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
chip = chip_save;
for (i = 0; i < 8; i++, chip++) {
chip->dev = &pdev->dev;
chip->dev = dev;
chip->base = base;
chip->reg = chip->base;
chip->ch = i;
@ -443,17 +444,17 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
ioh_gpio_setup(chip, num_ports[i]);
ret = gpiochip_add_data(&chip->gpio, chip);
if (ret) {
dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n");
dev_err(dev, "IOH gpio: Failed to register GPIO\n");
goto err_gpiochip_add;
}
}
chip = chip_save;
for (j = 0; j < 8; j++, chip++) {
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, IOH_IRQ_BASE,
irq_base = devm_irq_alloc_descs(dev, -1, IOH_IRQ_BASE,
num_ports[j], NUMA_NO_NODE);
if (irq_base < 0) {
dev_warn(&pdev->dev,
dev_warn(dev,
"ml_ioh_gpio: Failed to get IRQ base num\n");
ret = irq_base;
goto err_gpiochip_add;
@ -467,11 +468,10 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
}
chip = chip_save;
ret = devm_request_irq(&pdev->dev, pdev->irq, ioh_gpio_handler,
ret = devm_request_irq(dev, pdev->irq, ioh_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret != 0) {
dev_err(&pdev->dev,
"%s request_irq failed\n", __func__);
dev_err(dev, "%s request_irq failed\n", __func__);
goto err_gpiochip_add;
}
@ -498,7 +498,7 @@ err_request_regions:
err_pci_enable:
dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
dev_err(dev, "%s Failed returns %d\n", __func__, ret);
return ret;
}

View File

@ -221,6 +221,263 @@ static const unsigned int msc313_offsets[] = {
};
MSC313_GPIO_CHIPDATA(msc313);
/*
* Unlike the msc313(e) the ssd20xd have a bunch of pins
* that are actually called gpio probably because they
* have no dedicated function.
*/
#define SSD20XD_PINNAME_GPIO0 "gpio0"
#define SSD20XD_PINNAME_GPIO1 "gpio1"
#define SSD20XD_PINNAME_GPIO2 "gpio2"
#define SSD20XD_PINNAME_GPIO3 "gpio3"
#define SSD20XD_PINNAME_GPIO4 "gpio4"
#define SSD20XD_PINNAME_GPIO5 "gpio5"
#define SSD20XD_PINNAME_GPIO6 "gpio6"
#define SSD20XD_PINNAME_GPIO7 "gpio7"
#define SSD20XD_PINNAME_GPIO10 "gpio10"
#define SSD20XD_PINNAME_GPIO11 "gpio11"
#define SSD20XD_PINNAME_GPIO12 "gpio12"
#define SSD20XD_PINNAME_GPIO13 "gpio13"
#define SSD20XD_PINNAME_GPIO14 "gpio14"
#define SSD20XD_PINNAME_GPIO85 "gpio85"
#define SSD20XD_PINNAME_GPIO86 "gpio86"
#define SSD20XD_PINNAME_GPIO90 "gpio90"
#define SSD20XD_GPIO_NAMES SSD20XD_PINNAME_GPIO0, \
SSD20XD_PINNAME_GPIO1, \
SSD20XD_PINNAME_GPIO2, \
SSD20XD_PINNAME_GPIO3, \
SSD20XD_PINNAME_GPIO4, \
SSD20XD_PINNAME_GPIO5, \
SSD20XD_PINNAME_GPIO6, \
SSD20XD_PINNAME_GPIO7, \
SSD20XD_PINNAME_GPIO10, \
SSD20XD_PINNAME_GPIO11, \
SSD20XD_PINNAME_GPIO12, \
SSD20XD_PINNAME_GPIO13, \
SSD20XD_PINNAME_GPIO14, \
SSD20XD_PINNAME_GPIO85, \
SSD20XD_PINNAME_GPIO86, \
SSD20XD_PINNAME_GPIO90
#define SSD20XD_GPIO_OFF_GPIO0 0x0
#define SSD20XD_GPIO_OFF_GPIO1 0x4
#define SSD20XD_GPIO_OFF_GPIO2 0x8
#define SSD20XD_GPIO_OFF_GPIO3 0xc
#define SSD20XD_GPIO_OFF_GPIO4 0x10
#define SSD20XD_GPIO_OFF_GPIO5 0x14
#define SSD20XD_GPIO_OFF_GPIO6 0x18
#define SSD20XD_GPIO_OFF_GPIO7 0x1c
#define SSD20XD_GPIO_OFF_GPIO10 0x28
#define SSD20XD_GPIO_OFF_GPIO11 0x2c
#define SSD20XD_GPIO_OFF_GPIO12 0x30
#define SSD20XD_GPIO_OFF_GPIO13 0x34
#define SSD20XD_GPIO_OFF_GPIO14 0x38
#define SSD20XD_GPIO_OFF_GPIO85 0x100
#define SSD20XD_GPIO_OFF_GPIO86 0x104
#define SSD20XD_GPIO_OFF_GPIO90 0x114
#define SSD20XD_GPIO_OFFSETS SSD20XD_GPIO_OFF_GPIO0, \
SSD20XD_GPIO_OFF_GPIO1, \
SSD20XD_GPIO_OFF_GPIO2, \
SSD20XD_GPIO_OFF_GPIO3, \
SSD20XD_GPIO_OFF_GPIO4, \
SSD20XD_GPIO_OFF_GPIO5, \
SSD20XD_GPIO_OFF_GPIO6, \
SSD20XD_GPIO_OFF_GPIO7, \
SSD20XD_GPIO_OFF_GPIO10, \
SSD20XD_GPIO_OFF_GPIO11, \
SSD20XD_GPIO_OFF_GPIO12, \
SSD20XD_GPIO_OFF_GPIO13, \
SSD20XD_GPIO_OFF_GPIO14, \
SSD20XD_GPIO_OFF_GPIO85, \
SSD20XD_GPIO_OFF_GPIO86, \
SSD20XD_GPIO_OFF_GPIO90
/* "ttl" pins lcd interface pins */
#define SSD20XD_PINNAME_TTL0 "ttl0"
#define SSD20XD_PINNAME_TTL1 "ttl1"
#define SSD20XD_PINNAME_TTL2 "ttl2"
#define SSD20XD_PINNAME_TTL3 "ttl3"
#define SSD20XD_PINNAME_TTL4 "ttl4"
#define SSD20XD_PINNAME_TTL5 "ttl5"
#define SSD20XD_PINNAME_TTL6 "ttl6"
#define SSD20XD_PINNAME_TTL7 "ttl7"
#define SSD20XD_PINNAME_TTL8 "ttl8"
#define SSD20XD_PINNAME_TTL9 "ttl9"
#define SSD20XD_PINNAME_TTL10 "ttl10"
#define SSD20XD_PINNAME_TTL11 "ttl11"
#define SSD20XD_PINNAME_TTL12 "ttl12"
#define SSD20XD_PINNAME_TTL13 "ttl13"
#define SSD20XD_PINNAME_TTL14 "ttl14"
#define SSD20XD_PINNAME_TTL15 "ttl15"
#define SSD20XD_PINNAME_TTL16 "ttl16"
#define SSD20XD_PINNAME_TTL17 "ttl17"
#define SSD20XD_PINNAME_TTL18 "ttl18"
#define SSD20XD_PINNAME_TTL19 "ttl19"
#define SSD20XD_PINNAME_TTL20 "ttl20"
#define SSD20XD_PINNAME_TTL21 "ttl21"
#define SSD20XD_PINNAME_TTL22 "ttl22"
#define SSD20XD_PINNAME_TTL23 "ttl23"
#define SSD20XD_PINNAME_TTL24 "ttl24"
#define SSD20XD_PINNAME_TTL25 "ttl25"
#define SSD20XD_PINNAME_TTL26 "ttl26"
#define SSD20XD_PINNAME_TTL27 "ttl27"
#define SSD20XD_TTL_PINNAMES SSD20XD_PINNAME_TTL0, \
SSD20XD_PINNAME_TTL1, \
SSD20XD_PINNAME_TTL2, \
SSD20XD_PINNAME_TTL3, \
SSD20XD_PINNAME_TTL4, \
SSD20XD_PINNAME_TTL5, \
SSD20XD_PINNAME_TTL6, \
SSD20XD_PINNAME_TTL7, \
SSD20XD_PINNAME_TTL8, \
SSD20XD_PINNAME_TTL9, \
SSD20XD_PINNAME_TTL10, \
SSD20XD_PINNAME_TTL11, \
SSD20XD_PINNAME_TTL12, \
SSD20XD_PINNAME_TTL13, \
SSD20XD_PINNAME_TTL14, \
SSD20XD_PINNAME_TTL15, \
SSD20XD_PINNAME_TTL16, \
SSD20XD_PINNAME_TTL17, \
SSD20XD_PINNAME_TTL18, \
SSD20XD_PINNAME_TTL19, \
SSD20XD_PINNAME_TTL20, \
SSD20XD_PINNAME_TTL21, \
SSD20XD_PINNAME_TTL22, \
SSD20XD_PINNAME_TTL23, \
SSD20XD_PINNAME_TTL24, \
SSD20XD_PINNAME_TTL25, \
SSD20XD_PINNAME_TTL26, \
SSD20XD_PINNAME_TTL27
#define SSD20XD_TTL_OFFSET_TTL0 0x80
#define SSD20XD_TTL_OFFSET_TTL1 0x84
#define SSD20XD_TTL_OFFSET_TTL2 0x88
#define SSD20XD_TTL_OFFSET_TTL3 0x8c
#define SSD20XD_TTL_OFFSET_TTL4 0x90
#define SSD20XD_TTL_OFFSET_TTL5 0x94
#define SSD20XD_TTL_OFFSET_TTL6 0x98
#define SSD20XD_TTL_OFFSET_TTL7 0x9c
#define SSD20XD_TTL_OFFSET_TTL8 0xa0
#define SSD20XD_TTL_OFFSET_TTL9 0xa4
#define SSD20XD_TTL_OFFSET_TTL10 0xa8
#define SSD20XD_TTL_OFFSET_TTL11 0xac
#define SSD20XD_TTL_OFFSET_TTL12 0xb0
#define SSD20XD_TTL_OFFSET_TTL13 0xb4
#define SSD20XD_TTL_OFFSET_TTL14 0xb8
#define SSD20XD_TTL_OFFSET_TTL15 0xbc
#define SSD20XD_TTL_OFFSET_TTL16 0xc0
#define SSD20XD_TTL_OFFSET_TTL17 0xc4
#define SSD20XD_TTL_OFFSET_TTL18 0xc8
#define SSD20XD_TTL_OFFSET_TTL19 0xcc
#define SSD20XD_TTL_OFFSET_TTL20 0xd0
#define SSD20XD_TTL_OFFSET_TTL21 0xd4
#define SSD20XD_TTL_OFFSET_TTL22 0xd8
#define SSD20XD_TTL_OFFSET_TTL23 0xdc
#define SSD20XD_TTL_OFFSET_TTL24 0xe0
#define SSD20XD_TTL_OFFSET_TTL25 0xe4
#define SSD20XD_TTL_OFFSET_TTL26 0xe8
#define SSD20XD_TTL_OFFSET_TTL27 0xec
#define SSD20XD_TTL_OFFSETS SSD20XD_TTL_OFFSET_TTL0, \
SSD20XD_TTL_OFFSET_TTL1, \
SSD20XD_TTL_OFFSET_TTL2, \
SSD20XD_TTL_OFFSET_TTL3, \
SSD20XD_TTL_OFFSET_TTL4, \
SSD20XD_TTL_OFFSET_TTL5, \
SSD20XD_TTL_OFFSET_TTL6, \
SSD20XD_TTL_OFFSET_TTL7, \
SSD20XD_TTL_OFFSET_TTL8, \
SSD20XD_TTL_OFFSET_TTL9, \
SSD20XD_TTL_OFFSET_TTL10, \
SSD20XD_TTL_OFFSET_TTL11, \
SSD20XD_TTL_OFFSET_TTL12, \
SSD20XD_TTL_OFFSET_TTL13, \
SSD20XD_TTL_OFFSET_TTL14, \
SSD20XD_TTL_OFFSET_TTL15, \
SSD20XD_TTL_OFFSET_TTL16, \
SSD20XD_TTL_OFFSET_TTL17, \
SSD20XD_TTL_OFFSET_TTL18, \
SSD20XD_TTL_OFFSET_TTL19, \
SSD20XD_TTL_OFFSET_TTL20, \
SSD20XD_TTL_OFFSET_TTL21, \
SSD20XD_TTL_OFFSET_TTL22, \
SSD20XD_TTL_OFFSET_TTL23, \
SSD20XD_TTL_OFFSET_TTL24, \
SSD20XD_TTL_OFFSET_TTL25, \
SSD20XD_TTL_OFFSET_TTL26, \
SSD20XD_TTL_OFFSET_TTL27
/* On the ssd20xd the two normal uarts have dedicated pins */
#define SSD20XD_PINNAME_UART0_RX "uart0_rx"
#define SSD20XD_PINNAME_UART0_TX "uart0_tx"
#define SSD20XD_UART0_NAMES \
SSD20XD_PINNAME_UART0_RX, \
SSD20XD_PINNAME_UART0_TX
#define SSD20XD_PINNAME_UART1_RX "uart1_rx"
#define SSD20XD_PINNAME_UART1_TX "uart1_tx"
#define SSD20XD_UART1_NAMES \
SSD20XD_PINNAME_UART1_RX, \
SSD20XD_PINNAME_UART1_TX
#define SSD20XD_OFF_UART0_RX 0x60
#define SSD20XD_OFF_UART0_TX 0x64
#define SSD20XD_UART0_OFFSETS \
SSD20XD_OFF_UART0_RX, \
SSD20XD_OFF_UART0_TX
#define SSD20XD_OFF_UART1_RX 0x68
#define SSD20XD_OFF_UART1_TX 0x6c
#define SSD20XD_UART1_OFFSETS \
SSD20XD_OFF_UART1_RX, \
SSD20XD_OFF_UART1_TX
/*
* ssd20x has the same pin names but different ordering
* of the registers that control the gpio.
*/
#define SSD20XD_OFF_SD_D0 0x140
#define SSD20XD_OFF_SD_D1 0x144
#define SSD20XD_OFF_SD_D2 0x148
#define SSD20XD_OFF_SD_D3 0x14c
#define SSD20XD_OFF_SD_CMD 0x150
#define SSD20XD_OFF_SD_CLK 0x154
#define SSD20XD_SD_OFFSETS SSD20XD_OFF_SD_CLK, \
SSD20XD_OFF_SD_CMD, \
SSD20XD_OFF_SD_D0, \
SSD20XD_OFF_SD_D1, \
SSD20XD_OFF_SD_D2, \
SSD20XD_OFF_SD_D3
static const char * const ssd20xd_names[] = {
FUART_NAMES,
SD_NAMES,
SSD20XD_UART0_NAMES,
SSD20XD_UART1_NAMES,
SSD20XD_TTL_PINNAMES,
SSD20XD_GPIO_NAMES,
};
static const unsigned int ssd20xd_offsets[] = {
FUART_OFFSETS,
SSD20XD_SD_OFFSETS,
SSD20XD_UART0_OFFSETS,
SSD20XD_UART1_OFFSETS,
SSD20XD_TTL_OFFSETS,
SSD20XD_GPIO_OFFSETS,
};
MSC313_GPIO_CHIPDATA(ssd20xd);
#endif
struct msc313_gpio {
@ -344,7 +601,6 @@ static int msc313_gpio_probe(struct platform_device *pdev)
struct irq_domain *parent_domain;
struct device_node *parent_node;
struct device *dev = &pdev->dev;
int ret;
match_data = of_device_get_match_data(dev);
if (!match_data)
@ -399,8 +655,7 @@ static int msc313_gpio_probe(struct platform_device *pdev)
gpioirqchip->handler = handle_bad_irq;
gpioirqchip->default_type = IRQ_TYPE_NONE;
ret = devm_gpiochip_add_data(dev, gpiochip, gpio);
return ret;
return devm_gpiochip_add_data(dev, gpiochip, gpio);
}
static int msc313_gpio_remove(struct platform_device *pdev)
@ -414,6 +669,10 @@ static const struct of_device_id msc313_gpio_of_match[] = {
.compatible = "mstar,msc313-gpio",
.data = &msc313_data,
},
{
.compatible = "sstar,ssd20xd-gpio",
.data = &ssd20xd_data,
},
#endif
{ }
};
@ -456,5 +715,4 @@ static struct platform_driver msc313_gpio_driver = {
.probe = msc313_gpio_probe,
.remove = msc313_gpio_remove,
};
builtin_platform_driver(msc313_gpio_driver);

View File

@ -205,8 +205,7 @@ mediatek_gpio_xlate(struct gpio_chip *chip,
}
static int
mediatek_gpio_bank_probe(struct device *dev,
struct device_node *node, int bank)
mediatek_gpio_bank_probe(struct device *dev, int bank)
{
struct mtk *mtk = dev_get_drvdata(dev);
struct mtk_gc *rg;
@ -217,7 +216,6 @@ mediatek_gpio_bank_probe(struct device *dev,
memset(rg, 0, sizeof(*rg));
spin_lock_init(&rg->lock);
rg->chip.of_node = node;
rg->bank = bank;
dat = mtk->base + GPIO_REG_DATA + (rg->bank * GPIO_BANK_STRIDE);
@ -311,7 +309,7 @@ mediatek_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mtk);
for (i = 0; i < MTK_BANK_CNT; i++) {
ret = mediatek_gpio_bank_probe(dev, np, i);
ret = mediatek_gpio_bank_probe(dev, i);
if (ret)
return ret;
}

View File

@ -1183,7 +1183,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
mvchip->chip.ngpio = ngpios;
mvchip->chip.can_sleep = false;
mvchip->chip.of_node = np;
mvchip->chip.dbg_show = mvebu_gpio_dbg_show;
if (soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K)

View File

@ -1419,9 +1419,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
bank->is_mpuio = pdata->is_mpuio;
bank->non_wakeup_gpios = pdata->non_wakeup_gpios;
bank->regs = pdata->regs;
#ifdef CONFIG_OF_GPIO
bank->chip.of_node = of_node_get(node);
#endif
if (node) {
if (!of_property_read_bool(node, "ti,gpio-always-on"))

View File

@ -170,9 +170,7 @@ static int palmas_gpio_probe(struct platform_device *pdev)
palmas_gpio->gpio_chip.set = palmas_gpio_set;
palmas_gpio->gpio_chip.get = palmas_gpio_get;
palmas_gpio->gpio_chip.parent = &pdev->dev;
#ifdef CONFIG_OF_GPIO
palmas_gpio->gpio_chip.of_node = pdev->dev.of_node;
#endif
palmas_pdata = dev_get_platdata(palmas->dev);
if (palmas_pdata && palmas_pdata->gpio_base)
palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base;

View File

@ -346,51 +346,45 @@ static int pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
static int pch_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
s32 ret;
struct pch_gpio *chip;
int irq_base;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->dev = &pdev->dev;
chip->dev = dev;
ret = pcim_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "pci_enable_device FAILED");
dev_err(dev, "pci_enable_device FAILED");
return ret;
}
ret = pcim_iomap_regions(pdev, BIT(1), KBUILD_MODNAME);
if (ret) {
dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
dev_err(dev, "pci_request_regions FAILED-%d", ret);
return ret;
}
chip->base = pcim_iomap_table(pdev)[1];
if (pdev->device == 0x8803)
chip->ioh = INTEL_EG20T_PCH;
else if (pdev->device == 0x8014)
chip->ioh = OKISEMI_ML7223m_IOH;
else if (pdev->device == 0x8043)
chip->ioh = OKISEMI_ML7223n_IOH;
chip->ioh = id->driver_data;
chip->reg = chip->base;
pci_set_drvdata(pdev, chip);
spin_lock_init(&chip->spinlock);
pch_gpio_setup(chip);
ret = devm_gpiochip_add_data(&pdev->dev, &chip->gpio, chip);
ret = devm_gpiochip_add_data(dev, &chip->gpio, chip);
if (ret) {
dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
dev_err(dev, "PCH gpio: Failed to register GPIO\n");
return ret;
}
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0,
irq_base = devm_irq_alloc_descs(dev, -1, 0,
gpio_pins[chip->ioh], NUMA_NO_NODE);
if (irq_base < 0) {
dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n");
dev_warn(dev, "PCH gpio: Failed to get IRQ base num\n");
chip->irq_base = -1;
return 0;
}
@ -400,10 +394,10 @@ static int pch_gpio_probe(struct pci_dev *pdev,
iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->imask);
iowrite32(BIT(gpio_pins[chip->ioh]) - 1, &chip->reg->ien);
ret = devm_request_irq(&pdev->dev, pdev->irq, pch_gpio_handler,
ret = devm_request_irq(dev, pdev->irq, pch_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret) {
dev_err(&pdev->dev, "request_irq failed\n");
dev_err(dev, "request_irq failed\n");
return ret;
}
@ -439,10 +433,14 @@ static int __maybe_unused pch_gpio_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(pch_gpio_pm_ops, pch_gpio_suspend, pch_gpio_resume);
static const struct pci_device_id pch_gpio_pcidev_id[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803),
.driver_data = INTEL_EG20T_PCH },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014),
.driver_data = OKISEMI_ML7223m_IOH },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043),
.driver_data = OKISEMI_ML7223n_IOH },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803),
.driver_data = INTEL_EG20T_PCH },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);

View File

@ -331,7 +331,6 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev)
pmic_eic->chip.ngpio = SPRD_PMIC_EIC_NR;
pmic_eic->chip.base = -1;
pmic_eic->chip.parent = &pdev->dev;
pmic_eic->chip.of_node = pdev->dev.of_node;
pmic_eic->chip.direction_input = sprd_pmic_eic_direction_input;
pmic_eic->chip.request = sprd_pmic_eic_request;
pmic_eic->chip.free = sprd_pmic_eic_free;

View File

@ -343,8 +343,7 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc,
}
#endif
static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,
struct device_node *np, void __iomem *regbase)
static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio, void __iomem *regbase)
{
int i, gpio, nbanks = DIV_ROUND_UP(ngpio, 32);
struct pxa_gpio_bank *bank;
@ -354,6 +353,7 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,
if (!pchip->banks)
return -ENOMEM;
pchip->chip.parent = pchip->dev;
pchip->chip.label = "gpio-pxa";
pchip->chip.direction_input = pxa_gpio_direction_input;
pchip->chip.direction_output = pxa_gpio_direction_output;
@ -365,7 +365,6 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,
pchip->chip.free = gpiochip_generic_free;
#ifdef CONFIG_OF_GPIO
pchip->chip.of_node = np;
pchip->chip.of_xlate = pxa_gpio_of_xlate;
pchip->chip.of_gpio_n_cells = 2;
#endif
@ -675,8 +674,7 @@ static int pxa_gpio_probe(struct platform_device *pdev)
}
/* Initialize GPIO chips */
ret = pxa_init_gpio_chip(pchip, pxa_last_gpio + 1, pdev->dev.of_node,
gpio_reg_base);
ret = pxa_init_gpio_chip(pchip, pxa_last_gpio + 1, gpio_reg_base);
if (ret) {
clk_put(clk);
return ret;

View File

@ -221,7 +221,6 @@ static int rpi_exp_gpio_probe(struct platform_device *pdev)
rpi_gpio->gc.parent = dev;
rpi_gpio->gc.label = MODULE_NAME;
rpi_gpio->gc.owner = THIS_MODULE;
rpi_gpio->gc.of_node = np;
rpi_gpio->gc.base = -1;
rpi_gpio->gc.ngpio = NUM_GPIO;

View File

@ -477,7 +477,6 @@ static void gpio_rcar_enable_inputs(struct gpio_rcar_priv *p)
static int gpio_rcar_probe(struct platform_device *pdev)
{
struct gpio_rcar_priv *p;
struct resource *irq;
struct gpio_chip *gpio_chip;
struct irq_chip *irq_chip;
struct gpio_irq_chip *girq;
@ -502,12 +501,10 @@ static int gpio_rcar_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(dev, "missing IRQ\n");
ret = -EINVAL;
ret = platform_get_irq(pdev, 0);
if (ret < 0)
goto err0;
}
p->irq_parent = ret;
p->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(p->base)) {
@ -555,11 +552,10 @@ static int gpio_rcar_probe(struct platform_device *pdev)
goto err0;
}
p->irq_parent = irq->start;
if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler,
IRQF_SHARED, name, p)) {
ret = devm_request_irq(dev, p->irq_parent, gpio_rcar_irq_handler,
IRQF_SHARED, name, p);
if (ret) {
dev_err(dev, "failed to request IRQ\n");
ret = -ENOENT;
goto err1;
}

View File

@ -197,7 +197,6 @@ static void rda_gpio_irq_handler(struct irq_desc *desc)
static int rda_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct gpio_irq_chip *girq;
struct rda_gpio *rda_gpio;
@ -240,8 +239,6 @@ static int rda_gpio_probe(struct platform_device *pdev)
rda_gpio->chip.label = dev_name(dev);
rda_gpio->chip.ngpio = ngpios;
rda_gpio->chip.base = -1;
rda_gpio->chip.parent = dev;
rda_gpio->chip.of_node = np;
if (rda_gpio->irq >= 0) {
rda_gpio->irq_chip.name = "rda-gpio",

View File

@ -244,16 +244,12 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
chip = &gpio->gpio_chip;
chip->parent = config->parent;
chip->fwnode = config->fwnode;
chip->base = -1;
chip->ngpio = config->ngpio;
chip->names = config->names;
chip->label = config->label ?: dev_name(config->parent);
#if defined(CONFIG_OF_GPIO)
/* gpiolib will use of_node of the parent if chip->of_node is NULL */
chip->of_node = to_of_node(config->fwnode);
#endif /* CONFIG_OF_GPIO */
/*
* If our regmap is fast_io we should probably set can_sleep to false.
* Right now, the regmap doesn't save this property, nor is there any

View File

@ -465,6 +465,22 @@ out:
return ret;
}
static int rockchip_irq_reqres(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
return gpiochip_reqres_irq(&bank->gpio_chip, d->hwirq);
}
static void rockchip_irq_relres(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct rockchip_pin_bank *bank = gc->private;
gpiochip_relres_irq(&bank->gpio_chip, d->hwirq);
}
static void rockchip_irq_suspend(struct irq_data *d)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
@ -536,6 +552,8 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank)
gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
gc->chip_types[0].chip.irq_request_resources = rockchip_irq_reqres;
gc->chip_types[0].chip.irq_release_resources = rockchip_irq_relres;
gc->wake_enabled = IRQ_MSK(bank->nr_pins);
/*
@ -566,9 +584,6 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
gc->ngpio = bank->nr_pins;
gc->label = bank->name;
gc->parent = bank->dev;
#ifdef CONFIG_OF_GPIO
gc->of_node = of_node_get(bank->of_node);
#endif
ret = gpiochip_add_data(gc, bank);
if (ret) {

View File

@ -192,7 +192,6 @@ static int sama5d2_piobu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, piobu);
piobu->chip.label = pdev->name;
piobu->chip.parent = &pdev->dev;
piobu->chip.of_node = pdev->dev.of_node;
piobu->chip.owner = THIS_MODULE,
piobu->chip.get_direction = sama5d2_piobu_get_direction,
piobu->chip.direction_input = sama5d2_piobu_direction_input,

View File

@ -139,7 +139,7 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num,
/*
* according to the datasheet, writing to the level register has no
* effect when GPIO is programmed as input.
* Actually the the level register is read-only when configured as input.
* Actually the level register is read-only when configured as input.
* Thus presetting the output level before switching to output is _NOT_ possible.
* Hence we set the level after configuring the GPIO as output.
* But we cannot prevent a short low pulse if direction is set to high

1592
drivers/gpio/gpio-sim.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -237,7 +237,6 @@ static int sprd_gpio_probe(struct platform_device *pdev)
sprd_gpio->chip.ngpio = SPRD_GPIO_NR;
sprd_gpio->chip.base = -1;
sprd_gpio->chip.parent = &pdev->dev;
sprd_gpio->chip.of_node = pdev->dev.of_node;
sprd_gpio->chip.request = sprd_gpio_request;
sprd_gpio->chip.free = sprd_gpio_free;
sprd_gpio->chip.get = sprd_gpio_get;

View File

@ -324,7 +324,7 @@ static int gsta_alloc_irq_chip(struct gsta_gpio *chip)
if (rv)
return rv;
/* Set up all all 128 interrupts: code from setup_generic_chip */
/* Set up all 128 interrupts: code from setup_generic_chip */
{
struct irq_chip_type *ct = gc->chip_types;
int i, j;

View File

@ -477,7 +477,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
stmpe_gpio->chip = template_chip;
stmpe_gpio->chip.ngpio = stmpe->num_gpios;
stmpe_gpio->chip.parent = &pdev->dev;
stmpe_gpio->chip.of_node = np;
stmpe_gpio->chip.base = -1;
if (IS_ENABLED(CONFIG_DEBUG_FS))

View File

@ -319,7 +319,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
tc3589x_gpio->chip.parent = &pdev->dev;
tc3589x_gpio->chip.base = -1;
tc3589x_gpio->chip.of_node = np;
girq = &tc3589x_gpio->chip.irq;
girq->chip = &tc3589x_gpio_irq_chip;

View File

@ -14,6 +14,8 @@
#include <dt-bindings/gpio/tegra186-gpio.h>
#include <dt-bindings/gpio/tegra194-gpio.h>
#include <dt-bindings/gpio/tegra234-gpio.h>
#include <dt-bindings/gpio/tegra241-gpio.h>
/* security registers */
#define TEGRA186_GPIO_CTL_SCR 0x0c
@ -748,7 +750,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
gpio->gpio.names = (const char * const *)names;
#if defined(CONFIG_OF_GPIO)
gpio->gpio.of_node = pdev->dev.of_node;
gpio->gpio.of_gpio_n_cells = 2;
gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
#endif /* CONFIG_OF_GPIO */
@ -972,6 +973,124 @@ static const struct tegra_gpio_soc tegra194_aon_soc = {
.num_irqs_per_bank = 8,
};
#define TEGRA234_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
[TEGRA234_MAIN_GPIO_PORT_##_name] = { \
.name = #_name, \
.bank = _bank, \
.port = _port, \
.pins = _pins, \
}
static const struct tegra_gpio_port tegra234_main_ports[] = {
TEGRA234_MAIN_GPIO_PORT( A, 0, 0, 8),
TEGRA234_MAIN_GPIO_PORT( B, 0, 3, 1),
TEGRA234_MAIN_GPIO_PORT( C, 5, 1, 8),
TEGRA234_MAIN_GPIO_PORT( D, 5, 2, 4),
TEGRA234_MAIN_GPIO_PORT( E, 5, 3, 8),
TEGRA234_MAIN_GPIO_PORT( F, 5, 4, 6),
TEGRA234_MAIN_GPIO_PORT( G, 4, 0, 8),
TEGRA234_MAIN_GPIO_PORT( H, 4, 1, 8),
TEGRA234_MAIN_GPIO_PORT( I, 4, 2, 7),
TEGRA234_MAIN_GPIO_PORT( J, 5, 0, 6),
TEGRA234_MAIN_GPIO_PORT( K, 3, 0, 8),
TEGRA234_MAIN_GPIO_PORT( L, 3, 1, 4),
TEGRA234_MAIN_GPIO_PORT( M, 2, 0, 8),
TEGRA234_MAIN_GPIO_PORT( N, 2, 1, 8),
TEGRA234_MAIN_GPIO_PORT( P, 2, 2, 8),
TEGRA234_MAIN_GPIO_PORT( Q, 2, 3, 8),
TEGRA234_MAIN_GPIO_PORT( R, 2, 4, 6),
TEGRA234_MAIN_GPIO_PORT( X, 1, 0, 8),
TEGRA234_MAIN_GPIO_PORT( Y, 1, 1, 8),
TEGRA234_MAIN_GPIO_PORT( Z, 1, 2, 8),
TEGRA234_MAIN_GPIO_PORT(AC, 0, 1, 8),
TEGRA234_MAIN_GPIO_PORT(AD, 0, 2, 4),
TEGRA234_MAIN_GPIO_PORT(AE, 3, 3, 2),
TEGRA234_MAIN_GPIO_PORT(AF, 3, 4, 4),
TEGRA234_MAIN_GPIO_PORT(AG, 3, 2, 8),
};
static const struct tegra_gpio_soc tegra234_main_soc = {
.num_ports = ARRAY_SIZE(tegra234_main_ports),
.ports = tegra234_main_ports,
.name = "tegra234-gpio",
.instance = 0,
.num_irqs_per_bank = 8,
};
#define TEGRA234_AON_GPIO_PORT(_name, _bank, _port, _pins) \
[TEGRA234_AON_GPIO_PORT_##_name] = { \
.name = #_name, \
.bank = _bank, \
.port = _port, \
.pins = _pins, \
}
static const struct tegra_gpio_port tegra234_aon_ports[] = {
TEGRA234_AON_GPIO_PORT(AA, 0, 4, 8),
TEGRA234_AON_GPIO_PORT(BB, 0, 5, 4),
TEGRA234_AON_GPIO_PORT(CC, 0, 2, 8),
TEGRA234_AON_GPIO_PORT(DD, 0, 3, 3),
TEGRA234_AON_GPIO_PORT(EE, 0, 0, 8),
TEGRA234_AON_GPIO_PORT(GG, 0, 1, 1),
};
static const struct tegra_gpio_soc tegra234_aon_soc = {
.num_ports = ARRAY_SIZE(tegra234_aon_ports),
.ports = tegra234_aon_ports,
.name = "tegra234-gpio-aon",
.instance = 1,
.num_irqs_per_bank = 8,
};
#define TEGRA241_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \
[TEGRA241_MAIN_GPIO_PORT_##_name] = { \
.name = #_name, \
.bank = _bank, \
.port = _port, \
.pins = _pins, \
}
static const struct tegra_gpio_port tegra241_main_ports[] = {
TEGRA241_MAIN_GPIO_PORT(A, 0, 0, 8),
TEGRA241_MAIN_GPIO_PORT(B, 0, 1, 8),
TEGRA241_MAIN_GPIO_PORT(C, 0, 2, 2),
TEGRA241_MAIN_GPIO_PORT(D, 0, 3, 6),
TEGRA241_MAIN_GPIO_PORT(E, 0, 4, 8),
TEGRA241_MAIN_GPIO_PORT(F, 1, 0, 8),
TEGRA241_MAIN_GPIO_PORT(G, 1, 1, 8),
TEGRA241_MAIN_GPIO_PORT(H, 1, 2, 8),
TEGRA241_MAIN_GPIO_PORT(J, 1, 3, 8),
TEGRA241_MAIN_GPIO_PORT(K, 1, 4, 4),
TEGRA241_MAIN_GPIO_PORT(L, 1, 5, 6),
};
static const struct tegra_gpio_soc tegra241_main_soc = {
.num_ports = ARRAY_SIZE(tegra241_main_ports),
.ports = tegra241_main_ports,
.name = "tegra241-gpio",
.instance = 0,
};
#define TEGRA241_AON_GPIO_PORT(_name, _bank, _port, _pins) \
[TEGRA241_AON_GPIO_PORT_##_name] = { \
.name = #_name, \
.bank = _bank, \
.port = _port, \
.pins = _pins, \
}
static const struct tegra_gpio_port tegra241_aon_ports[] = {
TEGRA241_AON_GPIO_PORT(AA, 0, 0, 8),
TEGRA241_AON_GPIO_PORT(BB, 0, 0, 4),
};
static const struct tegra_gpio_soc tegra241_aon_soc = {
.num_ports = ARRAY_SIZE(tegra241_aon_ports),
.ports = tegra241_aon_ports,
.name = "tegra241-gpio-aon",
.instance = 1,
};
static const struct of_device_id tegra186_gpio_of_match[] = {
{
.compatible = "nvidia,tegra186-gpio",
@ -985,6 +1104,12 @@ static const struct of_device_id tegra186_gpio_of_match[] = {
}, {
.compatible = "nvidia,tegra194-gpio-aon",
.data = &tegra194_aon_soc
}, {
.compatible = "nvidia,tegra234-gpio",
.data = &tegra234_main_soc
}, {
.compatible = "nvidia,tegra234-gpio-aon",
.data = &tegra234_aon_soc
}, {
/* sentinel */
}
@ -996,6 +1121,8 @@ static const struct acpi_device_id tegra186_gpio_acpi_match[] = {
{ .id = "NVDA0208", .driver_data = (kernel_ulong_t)&tegra186_aon_soc },
{ .id = "NVDA0308", .driver_data = (kernel_ulong_t)&tegra194_main_soc },
{ .id = "NVDA0408", .driver_data = (kernel_ulong_t)&tegra194_aon_soc },
{ .id = "NVDA0508", .driver_data = (kernel_ulong_t)&tegra241_main_soc },
{ .id = "NVDA0608", .driver_data = (kernel_ulong_t)&tegra241_aon_soc },
{}
};
MODULE_DEVICE_TABLE(acpi, tegra186_gpio_acpi_match);

View File

@ -196,9 +196,6 @@ static int tps65218_gpio_probe(struct platform_device *pdev)
tps65218_gpio->tps65218 = tps65218;
tps65218_gpio->gpio_chip = template_chip;
tps65218_gpio->gpio_chip.parent = &pdev->dev;
#ifdef CONFIG_OF_GPIO
tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node;
#endif
return devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip,
tps65218_gpio);

View File

@ -77,6 +77,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)
struct tps6586x_platform_data *pdata;
struct tps6586x_gpio *tps6586x_gpio;
device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
pdata = dev_get_platdata(pdev->dev.parent);
tps6586x_gpio = devm_kzalloc(&pdev->dev,
sizeof(*tps6586x_gpio), GFP_KERNEL);
@ -97,9 +99,6 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)
tps6586x_gpio->gpio_chip.get = tps6586x_gpio_get;
tps6586x_gpio->gpio_chip.to_irq = tps6586x_gpio_to_irq;
#ifdef CONFIG_OF_GPIO
tps6586x_gpio->gpio_chip.of_node = pdev->dev.parent->of_node;
#endif
if (pdata && pdata->gpio_base)
tps6586x_gpio->gpio_chip.base = pdata->gpio_base;
else

View File

@ -111,6 +111,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev)
int ret;
int i;
device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
tps65910_gpio = devm_kzalloc(&pdev->dev,
sizeof(*tps65910_gpio), GFP_KERNEL);
if (!tps65910_gpio)
@ -137,9 +139,7 @@ static int tps65910_gpio_probe(struct platform_device *pdev)
tps65910_gpio->gpio_chip.set = tps65910_gpio_set;
tps65910_gpio->gpio_chip.get = tps65910_gpio_get;
tps65910_gpio->gpio_chip.parent = &pdev->dev;
#ifdef CONFIG_OF_GPIO
tps65910_gpio->gpio_chip.of_node = tps65910->dev->of_node;
#endif
if (pdata && pdata->gpio_base)
tps65910_gpio->gpio_chip.base = pdata->gpio_base;
else

View File

@ -317,22 +317,19 @@ static int ts5500_dio_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
const char *name = dev_name(dev);
struct ts5500_priv *priv;
struct resource *res;
unsigned long flags;
int ret;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(dev, "missing IRQ resource\n");
return -EINVAL;
}
ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
priv = devm_kzalloc(dev, sizeof(struct ts5500_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
priv->hwirq = res->start;
priv->hwirq = ret;
spin_lock_init(&priv->lock);
priv->gpio_chip.owner = THIS_MODULE;

View File

@ -80,6 +80,8 @@ static int gpo_twl6040_probe(struct platform_device *pdev)
struct twl6040 *twl6040 = dev_get_drvdata(twl6040_core_dev);
int ret;
device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
twl6040gpo_chip.base = -1;
if (twl6040_get_revid(twl6040) < TWL6041_REV_ES2_0)
@ -88,9 +90,6 @@ static int gpo_twl6040_probe(struct platform_device *pdev)
twl6040gpo_chip.ngpio = 1; /* twl6041 have 1 GPO */
twl6040gpo_chip.parent = &pdev->dev;
#ifdef CONFIG_OF_GPIO
twl6040gpo_chip.of_node = twl6040_core_dev->of_node;
#endif
ret = devm_gpiochip_add_data(&pdev->dev, &twl6040gpo_chip, NULL);
if (ret < 0) {

View File

@ -298,7 +298,6 @@ static int vf610_gpio_probe(struct platform_device *pdev)
}
gc = &port->gc;
gc->of_node = np;
gc->parent = dev;
gc->label = "vf610-gpio";
gc->ngpio = VF610_GPIO_PER_PORT;

View File

@ -262,6 +262,8 @@ static int wm831x_gpio_probe(struct platform_device *pdev)
struct wm831x_pdata *pdata = &wm831x->pdata;
struct wm831x_gpio *wm831x_gpio;
device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio),
GFP_KERNEL);
if (wm831x_gpio == NULL)
@ -275,9 +277,6 @@ static int wm831x_gpio_probe(struct platform_device *pdev)
wm831x_gpio->gpio_chip.base = pdata->gpio_base;
else
wm831x_gpio->gpio_chip.base = -1;
#ifdef CONFIG_OF_GPIO
wm831x_gpio->gpio_chip.of_node = wm831x->dev->of_node;
#endif
return devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, wm831x_gpio);
}

View File

@ -6,7 +6,6 @@
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
@ -26,16 +25,6 @@
*
* where addr is base address of the that feature register and gpio is the pin.
*/
#define GPIO_OUTPUT_EN 0x00
#define GPIO_PADDRV 0x08
#define GPIO_INT_EN00 0x18
#define GPIO_INT_EN10 0x20
#define GPIO_INT_EN20 0x28
#define GPIO_INT_EN30 0x30
#define GPIO_INT_POL 0x38
#define GPIO_INT_TYPE 0x40
#define GPIO_INT_STAT 0x48
#define GPIO_9XX_BYTESWAP 0X00
#define GPIO_9XX_CTRL 0X04
#define GPIO_9XX_OUTPUT_EN 0x14
@ -52,14 +41,6 @@
#define GPIO_9XX_INT_TYPE 0x114
#define GPIO_9XX_INT_STAT 0x124
#define GPIO_3XX_INT_EN00 0x18
#define GPIO_3XX_INT_EN10 0x20
#define GPIO_3XX_INT_EN20 0x28
#define GPIO_3XX_INT_EN30 0x30
#define GPIO_3XX_INT_POL 0x78
#define GPIO_3XX_INT_TYPE 0x80
#define GPIO_3XX_INT_STAT 0x88
/* Interrupt type register mask */
#define XLP_GPIO_IRQ_TYPE_LVL 0x0
#define XLP_GPIO_IRQ_TYPE_EDGE 0x1
@ -72,16 +53,6 @@
#define XLP_GPIO_IRQ_BASE 768
#define XLP_MAX_NR_GPIO 96
/* XLP variants supported by this driver */
enum {
XLP_GPIO_VARIANT_XLP832 = 1,
XLP_GPIO_VARIANT_XLP316,
XLP_GPIO_VARIANT_XLP208,
XLP_GPIO_VARIANT_XLP980,
XLP_GPIO_VARIANT_XLP532,
GPIO_VARIANT_VULCAN
};
struct xlp_gpio_priv {
struct gpio_chip chip;
DECLARE_BITMAP(gpio_enabled_mask, XLP_MAX_NR_GPIO);
@ -257,44 +228,13 @@ static void xlp_gpio_set(struct gpio_chip *gc, unsigned gpio, int state)
xlp_gpio_set_reg(priv->gpio_paddrv, gpio, state);
}
static const struct of_device_id xlp_gpio_of_ids[] = {
{
.compatible = "netlogic,xlp832-gpio",
.data = (void *)XLP_GPIO_VARIANT_XLP832,
},
{
.compatible = "netlogic,xlp316-gpio",
.data = (void *)XLP_GPIO_VARIANT_XLP316,
},
{
.compatible = "netlogic,xlp208-gpio",
.data = (void *)XLP_GPIO_VARIANT_XLP208,
},
{
.compatible = "netlogic,xlp980-gpio",
.data = (void *)XLP_GPIO_VARIANT_XLP980,
},
{
.compatible = "netlogic,xlp532-gpio",
.data = (void *)XLP_GPIO_VARIANT_XLP532,
},
{
.compatible = "brcm,vulcan-gpio",
.data = (void *)GPIO_VARIANT_VULCAN,
},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids);
static int xlp_gpio_probe(struct platform_device *pdev)
{
struct gpio_chip *gc;
struct gpio_irq_chip *girq;
struct xlp_gpio_priv *priv;
void __iomem *gpio_base;
int irq_base, irq, err;
int ngpio;
u32 soc_type;
int irq, err;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@ -308,62 +248,12 @@ static int xlp_gpio_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
if (pdev->dev.of_node) {
soc_type = (uintptr_t)of_device_get_match_data(&pdev->dev);
} else {
const struct acpi_device_id *acpi_id;
acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
&pdev->dev);
if (!acpi_id || !acpi_id->driver_data) {
dev_err(&pdev->dev, "Unable to match ACPI ID\n");
return -ENODEV;
}
soc_type = (uintptr_t) acpi_id->driver_data;
}
switch (soc_type) {
case XLP_GPIO_VARIANT_XLP832:
priv->gpio_out_en = gpio_base + GPIO_OUTPUT_EN;
priv->gpio_paddrv = gpio_base + GPIO_PADDRV;
priv->gpio_intr_stat = gpio_base + GPIO_INT_STAT;
priv->gpio_intr_type = gpio_base + GPIO_INT_TYPE;
priv->gpio_intr_pol = gpio_base + GPIO_INT_POL;
priv->gpio_intr_en = gpio_base + GPIO_INT_EN00;
ngpio = 41;
break;
case XLP_GPIO_VARIANT_XLP208:
case XLP_GPIO_VARIANT_XLP316:
priv->gpio_out_en = gpio_base + GPIO_OUTPUT_EN;
priv->gpio_paddrv = gpio_base + GPIO_PADDRV;
priv->gpio_intr_stat = gpio_base + GPIO_3XX_INT_STAT;
priv->gpio_intr_type = gpio_base + GPIO_3XX_INT_TYPE;
priv->gpio_intr_pol = gpio_base + GPIO_3XX_INT_POL;
priv->gpio_intr_en = gpio_base + GPIO_3XX_INT_EN00;
ngpio = (soc_type == XLP_GPIO_VARIANT_XLP208) ? 42 : 57;
break;
case XLP_GPIO_VARIANT_XLP980:
case XLP_GPIO_VARIANT_XLP532:
case GPIO_VARIANT_VULCAN:
priv->gpio_out_en = gpio_base + GPIO_9XX_OUTPUT_EN;
priv->gpio_paddrv = gpio_base + GPIO_9XX_PADDRV;
priv->gpio_intr_stat = gpio_base + GPIO_9XX_INT_STAT;
priv->gpio_intr_type = gpio_base + GPIO_9XX_INT_TYPE;
priv->gpio_intr_pol = gpio_base + GPIO_9XX_INT_POL;
priv->gpio_intr_en = gpio_base + GPIO_9XX_INT_EN00;
if (soc_type == XLP_GPIO_VARIANT_XLP980)
ngpio = 66;
else if (soc_type == XLP_GPIO_VARIANT_XLP532)
ngpio = 67;
else
ngpio = 70;
break;
default:
dev_err(&pdev->dev, "Unknown Processor type!\n");
return -ENODEV;
}
priv->gpio_out_en = gpio_base + GPIO_9XX_OUTPUT_EN;
priv->gpio_paddrv = gpio_base + GPIO_9XX_PADDRV;
priv->gpio_intr_stat = gpio_base + GPIO_9XX_INT_STAT;
priv->gpio_intr_type = gpio_base + GPIO_9XX_INT_TYPE;
priv->gpio_intr_pol = gpio_base + GPIO_9XX_INT_POL;
priv->gpio_intr_en = gpio_base + GPIO_9XX_INT_EN00;
bitmap_zero(priv->gpio_enabled_mask, XLP_MAX_NR_GPIO);
@ -373,8 +263,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
gc->label = dev_name(&pdev->dev);
gc->base = 0;
gc->parent = &pdev->dev;
gc->ngpio = ngpio;
gc->of_node = pdev->dev.of_node;
gc->ngpio = 70;
gc->direction_output = xlp_gpio_dir_output;
gc->direction_input = xlp_gpio_dir_input;
gc->set = xlp_gpio_set;
@ -382,19 +271,6 @@ static int xlp_gpio_probe(struct platform_device *pdev)
spin_lock_init(&priv->lock);
/* XLP(MIPS) has fixed range for GPIO IRQs, Vulcan(ARM64) does not */
if (soc_type != GPIO_VARIANT_VULCAN) {
irq_base = devm_irq_alloc_descs(&pdev->dev, -1,
XLP_GPIO_IRQ_BASE,
gc->ngpio, 0);
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
return irq_base;
}
} else {
irq_base = 0;
}
girq = &gc->irq;
girq->chip = &xlp_gpio_irq_chip;
girq->parent_handler = xlp_gpio_generic_handler;
@ -405,7 +281,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = irq;
girq->first = irq_base;
girq->first = 0;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
@ -420,8 +296,8 @@ static int xlp_gpio_probe(struct platform_device *pdev)
#ifdef CONFIG_ACPI
static const struct acpi_device_id xlp_gpio_acpi_match[] = {
{ "BRCM9006", GPIO_VARIANT_VULCAN },
{ "CAV9006", GPIO_VARIANT_VULCAN },
{ "BRCM9006" },
{ "CAV9006" },
{},
};
MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match);
@ -430,7 +306,6 @@ MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match);
static struct platform_driver xlp_gpio_driver = {
.driver = {
.name = "xlp-gpio",
.of_match_table = xlp_gpio_of_ids,
.acpi_match_table = ACPI_PTR(xlp_gpio_acpi_match),
},
.probe = xlp_gpio_probe,

View File

@ -219,14 +219,13 @@ EXPORT_SYMBOL_GPL(acpi_gpio_get_io_resource);
static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
struct acpi_gpio_event *event)
{
struct device *parent = acpi_gpio->chip->parent;
int ret, value;
ret = request_threaded_irq(event->irq, NULL, event->handler,
event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);
if (ret) {
dev_err(acpi_gpio->chip->parent,
"Failed to setup interrupt handler for %d\n",
event->irq);
dev_err(parent, "Failed to setup interrupt handler for %d\n", event->irq);
return;
}
@ -347,8 +346,7 @@ static bool acpi_gpio_in_ignore_list(const char *controller_in, int pin_in)
return false;
err:
pr_err_once("Error invalid value for gpiolib_acpi.ignore_wake: %s\n",
ignore_wake);
pr_err_once("Error: Invalid value for gpiolib_acpi.ignore_wake: %s\n", ignore_wake);
return false;
}
@ -579,37 +577,25 @@ void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
}
EXPORT_SYMBOL_GPL(acpi_dev_remove_driver_gpios);
static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res)
static void acpi_dev_release_driver_gpios(void *adev)
{
acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev));
acpi_dev_remove_driver_gpios(adev);
}
int devm_acpi_dev_add_driver_gpios(struct device *dev,
const struct acpi_gpio_mapping *gpios)
{
void *res;
struct acpi_device *adev = ACPI_COMPANION(dev);
int ret;
res = devres_alloc(devm_acpi_dev_release_driver_gpios, 0, GFP_KERNEL);
if (!res)
return -ENOMEM;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), gpios);
if (ret) {
devres_free(res);
ret = acpi_dev_add_driver_gpios(adev, gpios);
if (ret)
return ret;
}
devres_add(dev, res);
return 0;
return devm_add_action_or_reset(dev, acpi_dev_release_driver_gpios, adev);
}
EXPORT_SYMBOL_GPL(devm_acpi_dev_add_driver_gpios);
void devm_acpi_dev_remove_driver_gpios(struct device *dev)
{
WARN_ON(devres_release(dev, devm_acpi_dev_release_driver_gpios, NULL, NULL));
}
EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios);
static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
const char *name, int index,
struct fwnode_reference_args *args,
@ -941,7 +927,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev,
if (info.gpioint &&
(*dflags == GPIOD_OUT_LOW || *dflags == GPIOD_OUT_HIGH)) {
dev_dbg(dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
dev_dbg(&adev->dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
return ERR_PTR(-ENOENT);
}
@ -1056,10 +1042,17 @@ int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int ind
irq_flags = acpi_dev_get_irq_type(info.triggering,
info.polarity);
/* Set type if specified and different than the current one */
if (irq_flags != IRQ_TYPE_NONE &&
irq_flags != irq_get_trigger_type(irq))
irq_set_irq_type(irq, irq_flags);
/*
* If the IRQ is not already in use then set type
* if specified and different than the current one.
*/
if (can_request_irq(irq, irq_flags)) {
if (irq_flags != IRQ_TYPE_NONE &&
irq_flags != irq_get_trigger_type(irq))
irq_set_irq_type(irq, irq_flags);
} else {
dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
}
return irq;
}
@ -1346,6 +1339,9 @@ void acpi_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev)
/* Set default fwnode to parent's one if present */
if (gc->parent)
ACPI_COMPANION_SET(&gdev->dev, ACPI_COMPANION(gc->parent));
if (gc->fwnode)
device_set_node(&gdev->dev, gc->fwnode);
}
static int acpi_gpio_package_count(const union acpi_object *obj)

View File

@ -1046,6 +1046,9 @@ void of_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev)
if (gc->parent)
gdev->dev.of_node = gc->parent->of_node;
if (gc->fwnode)
gc->of_node = to_of_node(gc->fwnode);
/* If the gpiochip has an assigned OF node this takes precedence */
if (gc->of_node)
gdev->dev.of_node = gc->of_node;

View File

@ -422,8 +422,16 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
if (count > chip->ngpio)
count = chip->ngpio;
for (i = 0; i < count; i++)
gdev->descs[i].name = names[chip->offset + i];
for (i = 0; i < count; i++) {
/*
* Allow overriding "fixed" names provided by the GPIO
* provider. The "fixed" names are more often than not
* generic and less informative than the names given in
* device properties.
*/
if (names[chip->offset + i] && names[chip->offset + i][0])
gdev->descs[i].name = names[chip->offset + i];
}
kfree(names);
@ -593,12 +601,18 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
struct fwnode_handle *fwnode = gc->parent ? dev_fwnode(gc->parent) : NULL;
unsigned long flags;
int ret = 0;
unsigned i;
int base = gc->base;
struct fwnode_handle *fwnode = NULL;
struct gpio_device *gdev;
unsigned long flags;
int base = gc->base;
unsigned int i;
int ret = 0;
u32 ngpios;
if (gc->fwnode)
fwnode = gc->fwnode;
else if (gc->parent)
fwnode = dev_fwnode(gc->parent);
/*
* First: allocate and populate the internal stat container, and
@ -646,6 +660,26 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
goto err_free_dev_name;
}
/*
* Try the device properties if the driver didn't supply the number
* of GPIO lines.
*/
if (gc->ngpio == 0) {
ret = device_property_read_u32(&gdev->dev, "ngpios", &ngpios);
if (ret == -ENODATA)
/*
* -ENODATA means that there is no property found and
* we want to issue the error message to the user.
* Besides that, we want to return different error code
* to state that supplied value is not valid.
*/
ngpios = 0;
else if (ret)
goto err_free_descs;
gc->ngpio = ngpios;
}
if (gc->ngpio == 0) {
chip_err(gc, "tried to insert a GPIO chip with zero lines\n");
ret = -EINVAL;
@ -708,10 +742,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
INIT_LIST_HEAD(&gdev->pin_ranges);
#endif
if (gc->names)
if (gc->names) {
ret = gpiochip_set_desc_names(gc);
else
ret = devprop_gpiochip_set_names(gc);
if (ret)
goto err_remove_from_list;
}
ret = devprop_gpiochip_set_names(gc);
if (ret)
goto err_remove_from_list;
@ -3487,11 +3523,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);
*/
void gpiod_add_lookup_table(struct gpiod_lookup_table *table)
{
mutex_lock(&gpio_lookup_lock);
list_add_tail(&table->list, &gpio_lookup_list);
mutex_unlock(&gpio_lookup_lock);
gpiod_add_lookup_tables(&table, 1);
}
EXPORT_SYMBOL_GPL(gpiod_add_lookup_table);
@ -3540,6 +3572,17 @@ void gpiod_add_hogs(struct gpiod_hog *hogs)
}
EXPORT_SYMBOL_GPL(gpiod_add_hogs);
void gpiod_remove_hogs(struct gpiod_hog *hogs)
{
struct gpiod_hog *hog;
mutex_lock(&gpio_machine_hogs_mutex);
for (hog = &hogs[0]; hog->chip_label; hog++)
list_del(&hog->list);
mutex_unlock(&gpio_machine_hogs_mutex);
}
EXPORT_SYMBOL_GPL(gpiod_remove_hogs);
static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
{
const char *dev_id = dev ? dev_name(dev) : NULL;

View File

@ -50,4 +50,75 @@
#define MSC313_GPIO_SPI0_DI (MSC313_GPIO_SPI0 + 2)
#define MSC313_GPIO_SPI0_DO (MSC313_GPIO_SPI0 + 3)
/* SSD20x */
#define SSD20XD_GPIO_FUART 0
#define SSD20XD_GPIO_FUART_RX (SSD20XD_GPIO_FUART + 0)
#define SSD20XD_GPIO_FUART_TX (SSD20XD_GPIO_FUART + 1)
#define SSD20XD_GPIO_FUART_CTS (SSD20XD_GPIO_FUART + 2)
#define SSD20XD_GPIO_FUART_RTS (SSD20XD_GPIO_FUART + 3)
#define SSD20XD_GPIO_SD (SSD20XD_GPIO_FUART_RTS + 1)
#define SSD20XD_GPIO_SD_CLK (SSD20XD_GPIO_SD + 0)
#define SSD20XD_GPIO_SD_CMD (SSD20XD_GPIO_SD + 1)
#define SSD20XD_GPIO_SD_D0 (SSD20XD_GPIO_SD + 2)
#define SSD20XD_GPIO_SD_D1 (SSD20XD_GPIO_SD + 3)
#define SSD20XD_GPIO_SD_D2 (SSD20XD_GPIO_SD + 4)
#define SSD20XD_GPIO_SD_D3 (SSD20XD_GPIO_SD + 5)
#define SSD20XD_GPIO_UART0 (SSD20XD_GPIO_SD_D3 + 1)
#define SSD20XD_GPIO_UART0_RX (SSD20XD_GPIO_UART0 + 0)
#define SSD20XD_GPIO_UART0_TX (SSD20XD_GPIO_UART0 + 1)
#define SSD20XD_GPIO_UART1 (SSD20XD_GPIO_UART0_TX + 1)
#define SSD20XD_GPIO_UART1_RX (SSD20XD_GPIO_UART1 + 0)
#define SSD20XD_GPIO_UART1_TX (SSD20XD_GPIO_UART1 + 1)
#define SSD20XD_GPIO_TTL (SSD20XD_GPIO_UART1_TX + 1)
#define SSD20XD_GPIO_TTL0 (SSD20XD_GPIO_TTL + 0)
#define SSD20XD_GPIO_TTL1 (SSD20XD_GPIO_TTL + 1)
#define SSD20XD_GPIO_TTL2 (SSD20XD_GPIO_TTL + 2)
#define SSD20XD_GPIO_TTL3 (SSD20XD_GPIO_TTL + 3)
#define SSD20XD_GPIO_TTL4 (SSD20XD_GPIO_TTL + 4)
#define SSD20XD_GPIO_TTL5 (SSD20XD_GPIO_TTL + 5)
#define SSD20XD_GPIO_TTL6 (SSD20XD_GPIO_TTL + 6)
#define SSD20XD_GPIO_TTL7 (SSD20XD_GPIO_TTL + 7)
#define SSD20XD_GPIO_TTL8 (SSD20XD_GPIO_TTL + 8)
#define SSD20XD_GPIO_TTL9 (SSD20XD_GPIO_TTL + 9)
#define SSD20XD_GPIO_TTL10 (SSD20XD_GPIO_TTL + 10)
#define SSD20XD_GPIO_TTL11 (SSD20XD_GPIO_TTL + 11)
#define SSD20XD_GPIO_TTL12 (SSD20XD_GPIO_TTL + 12)
#define SSD20XD_GPIO_TTL13 (SSD20XD_GPIO_TTL + 13)
#define SSD20XD_GPIO_TTL14 (SSD20XD_GPIO_TTL + 14)
#define SSD20XD_GPIO_TTL15 (SSD20XD_GPIO_TTL + 15)
#define SSD20XD_GPIO_TTL16 (SSD20XD_GPIO_TTL + 16)
#define SSD20XD_GPIO_TTL17 (SSD20XD_GPIO_TTL + 17)
#define SSD20XD_GPIO_TTL18 (SSD20XD_GPIO_TTL + 18)
#define SSD20XD_GPIO_TTL19 (SSD20XD_GPIO_TTL + 19)
#define SSD20XD_GPIO_TTL20 (SSD20XD_GPIO_TTL + 20)
#define SSD20XD_GPIO_TTL21 (SSD20XD_GPIO_TTL + 21)
#define SSD20XD_GPIO_TTL22 (SSD20XD_GPIO_TTL + 22)
#define SSD20XD_GPIO_TTL23 (SSD20XD_GPIO_TTL + 23)
#define SSD20XD_GPIO_TTL24 (SSD20XD_GPIO_TTL + 24)
#define SSD20XD_GPIO_TTL25 (SSD20XD_GPIO_TTL + 25)
#define SSD20XD_GPIO_TTL26 (SSD20XD_GPIO_TTL + 26)
#define SSD20XD_GPIO_TTL27 (SSD20XD_GPIO_TTL + 27)
#define SSD20XD_GPIO_GPIO (SSD20XD_GPIO_TTL27 + 1)
#define SSD20XD_GPIO_GPIO0 (SSD20XD_GPIO_GPIO + 0)
#define SSD20XD_GPIO_GPIO1 (SSD20XD_GPIO_GPIO + 1)
#define SSD20XD_GPIO_GPIO2 (SSD20XD_GPIO_GPIO + 2)
#define SSD20XD_GPIO_GPIO3 (SSD20XD_GPIO_GPIO + 3)
#define SSD20XD_GPIO_GPIO4 (SSD20XD_GPIO_GPIO + 4)
#define SSD20XD_GPIO_GPIO5 (SSD20XD_GPIO_GPIO + 5)
#define SSD20XD_GPIO_GPIO6 (SSD20XD_GPIO_GPIO + 6)
#define SSD20XD_GPIO_GPIO7 (SSD20XD_GPIO_GPIO + 7)
#define SSD20XD_GPIO_GPIO10 (SSD20XD_GPIO_GPIO + 8)
#define SSD20XD_GPIO_GPIO11 (SSD20XD_GPIO_GPIO + 9)
#define SSD20XD_GPIO_GPIO12 (SSD20XD_GPIO_GPIO + 10)
#define SSD20XD_GPIO_GPIO13 (SSD20XD_GPIO_GPIO + 11)
#define SSD20XD_GPIO_GPIO14 (SSD20XD_GPIO_GPIO + 12)
#define SSD20XD_GPIO_GPIO85 (SSD20XD_GPIO_GPIO + 13)
#define SSD20XD_GPIO_GPIO86 (SSD20XD_GPIO_GPIO + 14)
#define SSD20XD_GPIO_GPIO90 (SSD20XD_GPIO_GPIO + 15)
#endif /* _DT_BINDINGS_MSC313_GPIO_H */

View File

@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. */
/*
* This header provides constants for binding nvidia,tegra234-gpio*.
*
* The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
* provide names for this.
*
* The second cell contains standard flag values specified in gpio.h.
*/
#ifndef _DT_BINDINGS_GPIO_TEGRA234_GPIO_H
#define _DT_BINDINGS_GPIO_TEGRA234_GPIO_H
#include <dt-bindings/gpio/gpio.h>
/* GPIOs implemented by main GPIO controller */
#define TEGRA234_MAIN_GPIO_PORT_A 0
#define TEGRA234_MAIN_GPIO_PORT_B 1
#define TEGRA234_MAIN_GPIO_PORT_C 2
#define TEGRA234_MAIN_GPIO_PORT_D 3
#define TEGRA234_MAIN_GPIO_PORT_E 4
#define TEGRA234_MAIN_GPIO_PORT_F 5
#define TEGRA234_MAIN_GPIO_PORT_G 6
#define TEGRA234_MAIN_GPIO_PORT_H 7
#define TEGRA234_MAIN_GPIO_PORT_I 8
#define TEGRA234_MAIN_GPIO_PORT_J 9
#define TEGRA234_MAIN_GPIO_PORT_K 10
#define TEGRA234_MAIN_GPIO_PORT_L 11
#define TEGRA234_MAIN_GPIO_PORT_M 12
#define TEGRA234_MAIN_GPIO_PORT_N 13
#define TEGRA234_MAIN_GPIO_PORT_P 14
#define TEGRA234_MAIN_GPIO_PORT_Q 15
#define TEGRA234_MAIN_GPIO_PORT_R 16
#define TEGRA234_MAIN_GPIO_PORT_S 17
#define TEGRA234_MAIN_GPIO_PORT_T 18
#define TEGRA234_MAIN_GPIO_PORT_U 19
#define TEGRA234_MAIN_GPIO_PORT_V 20
#define TEGRA234_MAIN_GPIO_PORT_X 21
#define TEGRA234_MAIN_GPIO_PORT_Y 22
#define TEGRA234_MAIN_GPIO_PORT_Z 23
#define TEGRA234_MAIN_GPIO_PORT_AC 24
#define TEGRA234_MAIN_GPIO_PORT_AD 25
#define TEGRA234_MAIN_GPIO_PORT_AE 26
#define TEGRA234_MAIN_GPIO_PORT_AF 27
#define TEGRA234_MAIN_GPIO_PORT_AG 28
#define TEGRA234_MAIN_GPIO(port, offset) \
((TEGRA234_MAIN_GPIO_PORT_##port * 8) + offset)
/* GPIOs implemented by AON GPIO controller */
#define TEGRA234_AON_GPIO_PORT_AA 0
#define TEGRA234_AON_GPIO_PORT_BB 1
#define TEGRA234_AON_GPIO_PORT_CC 2
#define TEGRA234_AON_GPIO_PORT_DD 3
#define TEGRA234_AON_GPIO_PORT_EE 4
#define TEGRA234_AON_GPIO_PORT_GG 5
#define TEGRA234_AON_GPIO(port, offset) \
((TEGRA234_AON_GPIO_PORT_##port * 8) + offset)
#endif

View File

@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. */
/*
* This header provides constants for the nvidia,tegra241-gpio DT binding.
*
* The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
* provide names for this.
*
* The second cell contains standard flag values specified in gpio.h.
*/
#ifndef _DT_BINDINGS_GPIO_TEGRA241_GPIO_H
#define _DT_BINDINGS_GPIO_TEGRA241_GPIO_H
#include <dt-bindings/gpio/gpio.h>
/* GPIOs implemented by main GPIO controller */
#define TEGRA241_MAIN_GPIO_PORT_A 0
#define TEGRA241_MAIN_GPIO_PORT_B 1
#define TEGRA241_MAIN_GPIO_PORT_C 2
#define TEGRA241_MAIN_GPIO_PORT_D 3
#define TEGRA241_MAIN_GPIO_PORT_E 4
#define TEGRA241_MAIN_GPIO_PORT_F 5
#define TEGRA241_MAIN_GPIO_PORT_G 6
#define TEGRA241_MAIN_GPIO_PORT_H 7
#define TEGRA241_MAIN_GPIO_PORT_I 8
#define TEGRA241_MAIN_GPIO_PORT_J 9
#define TEGRA241_MAIN_GPIO_PORT_K 10
#define TEGRA241_MAIN_GPIO_PORT_L 11
#define TEGRA241_MAIN_GPIO(port, offset) \
((TEGRA241_MAIN_GPIO_PORT_##port * 8) + (offset))
/* GPIOs implemented by AON GPIO controller */
#define TEGRA241_AON_GPIO_PORT_AA 0
#define TEGRA241_AON_GPIO_PORT_BB 1
#define TEGRA241_AON_GPIO(port, offset) \
((TEGRA241_AON_GPIO_PORT_##port * 8) + (offset))
#endif

View File

@ -690,7 +690,6 @@ void acpi_dev_remove_driver_gpios(struct acpi_device *adev);
int devm_acpi_dev_add_driver_gpios(struct device *dev,
const struct acpi_gpio_mapping *gpios);
void devm_acpi_dev_remove_driver_gpios(struct device *dev);
struct gpio_desc *acpi_get_and_request_gpiod(char *path, int pin, char *label);
@ -708,7 +707,6 @@ static inline int devm_acpi_dev_add_driver_gpios(struct device *dev,
{
return -ENXIO;
}
static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {}
#endif /* CONFIG_GPIOLIB && CONFIG_ACPI */

View File

@ -289,6 +289,7 @@ struct gpio_irq_chip {
* number or the name of the SoC IP-block implementing it.
* @gpiodev: the internal state holder, opaque struct
* @parent: optional parent device providing the GPIOs
* @fwnode: optional fwnode providing this controller's properties
* @owner: helps prevent removal of modules exporting active GPIOs
* @request: optional hook for chip-specific activation, such as
* enabling module power and clock; may sleep
@ -377,6 +378,7 @@ struct gpio_chip {
const char *label;
struct gpio_device *gpiodev;
struct device *parent;
struct fwnode_handle *fwnode;
struct module *owner;
int (*request)(struct gpio_chip *gc,

View File

@ -100,6 +100,7 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n);
void gpiod_remove_lookup_table(struct gpiod_lookup_table *table);
void gpiod_add_hogs(struct gpiod_hog *hogs);
void gpiod_remove_hogs(struct gpiod_hog *hogs);
#else /* ! CONFIG_GPIOLIB */
static inline
void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {}
@ -108,6 +109,7 @@ void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {}
static inline
void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {}
static inline void gpiod_add_hogs(struct gpiod_hog *hogs) {}
static inline void gpiod_remove_hogs(struct gpiod_hog *hogs) {}
#endif /* CONFIG_GPIOLIB */
#endif /* __LINUX_GPIO_MACHINE_H */

View File

@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
gpio-mockup-cdev
gpio-chip-info
gpio-line-name

View File

@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
TEST_PROGS := gpio-mockup.sh
TEST_PROGS := gpio-mockup.sh gpio-sim.sh
TEST_FILES := gpio-mockup-sysfs.sh
TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev
TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev gpio-chip-info gpio-line-name
CFLAGS += -O2 -g -Wall -I../../../../usr/include/
include ../lib.mk

View File

@ -1,3 +1,4 @@
CONFIG_GPIOLIB=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_MOCKUP=m
CONFIG_GPIO_SIM=m

View File

@ -0,0 +1,57 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* GPIO character device helper for reading chip information.
*
* Copyright (C) 2021 Bartosz Golaszewski <brgl@bgdev.pl>
*/
#include <fcntl.h>
#include <linux/gpio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
static void print_usage(void)
{
printf("usage:\n");
printf(" gpio-chip-info <chip path> [name|label|num-lines]\n");
}
int main(int argc, char **argv)
{
struct gpiochip_info info;
int fd, ret;
if (argc != 3) {
print_usage();
return EXIT_FAILURE;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
perror("unable to open the GPIO chip");
return EXIT_FAILURE;
}
memset(&info, 0, sizeof(info));
ret = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &info);
if (ret) {
perror("chip info ioctl failed");
return EXIT_FAILURE;
}
if (strcmp(argv[2], "name") == 0) {
printf("%s\n", info.name);
} else if (strcmp(argv[2], "label") == 0) {
printf("%s\n", info.label);
} else if (strcmp(argv[2], "num-lines") == 0) {
printf("%u\n", info.lines);
} else {
fprintf(stderr, "unknown command: %s\n", argv[2]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* GPIO character device helper for reading line names.
*
* Copyright (C) 2021 Bartosz Golaszewski <brgl@bgdev.pl>
*/
#include <fcntl.h>
#include <linux/gpio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
static void print_usage(void)
{
printf("usage:\n");
printf(" gpio-line-name <chip path> <line offset>\n");
}
int main(int argc, char **argv)
{
struct gpio_v2_line_info info;
int fd, ret;
char *endp;
if (argc != 3) {
print_usage();
return EXIT_FAILURE;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
perror("unable to open the GPIO chip");
return EXIT_FAILURE;
}
memset(&info, 0, sizeof(info));
info.offset = strtoul(argv[2], &endp, 10);
if (*endp != '\0') {
print_usage();
return EXIT_FAILURE;
}
ret = ioctl(fd, GPIO_V2_GET_LINEINFO_IOCTL, &info);
if (ret) {
perror("line info ioctl failed");
return EXIT_FAILURE;
}
printf("%s\n", info.name);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,396 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2021 Bartosz Golaszewski <brgl@bgdev.pl>
BASE_DIR=`dirname $0`
CONFIGFS_DIR="/sys/kernel/config/gpio-sim"
MODULE="gpio-sim"
fail() {
echo "$*" >&2
echo "GPIO $MODULE test FAIL"
exit 1
}
skip() {
echo "$*" >&2
echo "GPIO $MODULE test SKIP"
exit 4
}
remove_chip() {
local CHIP=$1
for FILE in $CONFIGFS_DIR/$CHIP/*; do
BANK=`basename $FILE`
if [ "$BANK" = "live" -o "$BANK" = "dev_name" ]; then
continue
fi
LINES=`ls $CONFIGFS_DIR/$CHIP/$BANK/ | egrep ^line`
if [ "$?" = 0 ]; then
for LINE in $LINES; do
if [ -e $CONFIGFS_DIR/$CHIP/$BANK/$LINE/hog ]; then
rmdir $CONFIGFS_DIR/$CHIP/$BANK/$LINE/hog || \
fail "Unable to remove the hog"
fi
rmdir $CONFIGFS_DIR/$CHIP/$BANK/$LINE || \
fail "Unable to remove the line"
done
fi
rmdir $CONFIGFS_DIR/$CHIP/$BANK
done
rmdir $CONFIGFS_DIR/$CHIP || fail "Unable to remove the chip"
}
configfs_cleanup() {
for CHIP in `ls $CONFIGFS_DIR/`; do
remove_chip $CHIP
done
}
create_chip() {
local CHIP=$1
mkdir $CONFIGFS_DIR/$CHIP
}
create_bank() {
local CHIP=$1
local BANK=$2
mkdir $CONFIGFS_DIR/$CHIP/$BANK
}
set_label() {
local CHIP=$1
local BANK=$2
local LABEL=$3
echo $LABEL > $CONFIGFS_DIR/$CHIP/$BANK/label || fail "Unable to set the chip label"
}
set_num_lines() {
local CHIP=$1
local BANK=$2
local NUM_LINES=$3
echo $NUM_LINES > $CONFIGFS_DIR/$CHIP/$BANK/num_lines || \
fail "Unable to set the number of lines"
}
set_line_name() {
local CHIP=$1
local BANK=$2
local OFFSET=$3
local NAME=$4
local LINE_DIR=$CONFIGFS_DIR/$CHIP/$BANK/line$OFFSET
test -d $LINE_DIR || mkdir $LINE_DIR
echo $NAME > $LINE_DIR/name || fail "Unable to set the line name"
}
enable_chip() {
local CHIP=$1
echo 1 > $CONFIGFS_DIR/$CHIP/live || fail "Unable to enable the chip"
}
disable_chip() {
local CHIP=$1
echo 0 > $CONFIGFS_DIR/$CHIP/live || fail "Unable to disable the chip"
}
configfs_chip_name() {
local CHIP=$1
local BANK=$2
cat $CONFIGFS_DIR/$CHIP/$BANK/chip_name 2> /dev/null || \
fail "unable to read the chip name from configfs"
}
configfs_dev_name() {
local CHIP=$1
cat $CONFIGFS_DIR/$CHIP/dev_name 2> /dev/null || \
fail "unable to read the device name from configfs"
}
get_chip_num_lines() {
local CHIP=$1
local BANK=$2
$BASE_DIR/gpio-chip-info /dev/`configfs_chip_name $CHIP $BANK` num-lines || \
fail "unable to read the number of lines from the character device"
}
get_chip_label() {
local CHIP=$1
local BANK=$2
$BASE_DIR/gpio-chip-info /dev/`configfs_chip_name $CHIP $BANK` label || \
fail "unable to read the chip label from the character device"
}
get_line_name() {
local CHIP=$1
local BANK=$2
local OFFSET=$3
$BASE_DIR/gpio-line-name /dev/`configfs_chip_name $CHIP $BANK` $OFFSET || \
fail "unable to read the line name from the character device"
}
sysfs_set_pull() {
local DEV=$1
local BANK=$2
local OFFSET=$3
local PULL=$4
local DEVNAME=`configfs_dev_name $DEV`
local CHIPNAME=`configfs_chip_name $DEV $BANK`
local SYSFSPATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio$OFFSET/pull"
echo $PULL > $SYSFSPATH || fail "Unable to set line pull in sysfs"
}
# Load the gpio-sim module. This will pull in configfs if needed too.
modprobe gpio-sim || skip "unable to load the gpio-sim module"
# Make sure configfs is mounted at /sys/kernel/config. Wait a bit if needed.
for IDX in `seq 5`; do
if [ "$IDX" -eq "5" ]; then
skip "configfs not mounted at /sys/kernel/config"
fi
mountpoint -q /sys/kernel/config && break
sleep 0.1
done
# If the module was already loaded: remove all previous chips
configfs_cleanup
trap "exit 1" SIGTERM SIGINT
trap configfs_cleanup EXIT
echo "1. chip_name and dev_name attributes"
echo "1.1. Chip name is communicated to user"
create_chip chip
create_bank chip bank
enable_chip chip
test -n `cat $CONFIGFS_DIR/chip/bank/chip_name` || fail "chip_name doesn't work"
remove_chip chip
echo "1.2. chip_name returns 'none' if the chip is still pending"
create_chip chip
create_bank chip bank
test "`cat $CONFIGFS_DIR/chip/bank/chip_name`" = "none" || \
fail "chip_name doesn't return 'none' for a pending chip"
remove_chip chip
echo "1.3. Device name is communicated to user"
create_chip chip
create_bank chip bank
enable_chip chip
test -n `cat $CONFIGFS_DIR/chip/dev_name` || fail "dev_name doesn't work"
remove_chip chip
echo "2. Creating and configuring simulated chips"
echo "2.1. Default number of lines is 1"
create_chip chip
create_bank chip bank
enable_chip chip
test "`get_chip_num_lines chip bank`" = "1" || fail "default number of lines is not 1"
remove_chip chip
echo "2.2. Number of lines can be specified"
create_chip chip
create_bank chip bank
set_num_lines chip bank 16
enable_chip chip
test "`get_chip_num_lines chip bank`" = "16" || fail "number of lines is not 16"
remove_chip chip
echo "2.3. Label can be set"
create_chip chip
create_bank chip bank
set_label chip bank foobar
enable_chip chip
test "`get_chip_label chip bank`" = "foobar" || fail "label is incorrect"
remove_chip chip
echo "2.4. Label can be left empty"
create_chip chip
create_bank chip bank
enable_chip chip
test -z "`cat $CONFIGFS_DIR/chip/bank/label`" || fail "label is not empty"
remove_chip chip
echo "2.5. Line names can be configured"
create_chip chip
create_bank chip bank
set_num_lines chip bank 16
set_line_name chip bank 0 foo
set_line_name chip bank 2 bar
enable_chip chip
test "`get_line_name chip bank 0`" = "foo" || fail "line name is incorrect"
test "`get_line_name chip bank 2`" = "bar" || fail "line name is incorrect"
remove_chip chip
echo "2.6. Line config can remain unused if offset is greater than number of lines"
create_chip chip
create_bank chip bank
set_num_lines chip bank 2
set_line_name chip bank 5 foobar
enable_chip chip
test "`get_line_name chip bank 0`" = "" || fail "line name is incorrect"
test "`get_line_name chip bank 1`" = "" || fail "line name is incorrect"
remove_chip chip
echo "2.7. Line configfs directory names are sanitized"
create_chip chip
create_bank chip bank
mkdir $CONFIGFS_DIR/chip/bank/line12foobar 2> /dev/null && \
fail "invalid configfs line name accepted"
mkdir $CONFIGFS_DIR/chip/bank/line_no_offset 2> /dev/null && \
fail "invalid configfs line name accepted"
remove_chip chip
echo "2.8. Multiple chips can be created"
CHIPS="chip0 chip1 chip2"
for CHIP in $CHIPS; do
create_chip $CHIP
create_bank $CHIP bank
enable_chip $CHIP
done
for CHIP in $CHIPS; do
remove_chip $CHIP
done
echo "2.9. Can't modify settings when chip is live"
create_chip chip
create_bank chip bank
enable_chip chip
echo foobar > $CONFIGFS_DIR/chip/bank/label 2> /dev/null && \
fail "Setting label of a live chip should fail"
echo 8 > $CONFIGFS_DIR/chip/bank/num_lines 2> /dev/null && \
fail "Setting number of lines of a live chip should fail"
remove_chip chip
echo "2.10. Can't create line items when chip is live"
create_chip chip
create_bank chip bank
enable_chip chip
mkdir $CONFIGFS_DIR/chip/bank/line0 2> /dev/null && fail "Creating line item should fail"
remove_chip chip
echo "2.11. Probe errors are propagated to user-space"
create_chip chip
create_bank chip bank
set_num_lines chip bank 99999
echo 1 > $CONFIGFS_DIR/chip/live 2> /dev/null && fail "Probe error was not propagated"
remove_chip chip
echo "2.12. Cannot enable a chip without any GPIO banks"
create_chip chip
echo 1 > $CONFIGFS_DIR/chip/live 2> /dev/null && fail "Chip enabled without any GPIO banks"
remove_chip chip
echo "2.13. Duplicate chip labels are not allowed"
create_chip chip
create_bank chip bank0
set_label chip bank0 foobar
create_bank chip bank1
set_label chip bank1 foobar
echo 1 > $CONFIGFS_DIR/chip/live 2> /dev/null && fail "Duplicate chip labels were not rejected"
remove_chip chip
echo "2.14. Lines can be hogged"
create_chip chip
create_bank chip bank
set_num_lines chip bank 8
mkdir -p $CONFIGFS_DIR/chip/bank/line4/hog
enable_chip chip
$BASE_DIR/gpio-mockup-cdev -s 1 /dev/`configfs_chip_name chip bank` 4 2> /dev/null && \
fail "Setting the value of a hogged line shouldn't succeed"
remove_chip chip
echo "3. Controlling simulated chips"
echo "3.1. Pull can be set over sysfs"
create_chip chip
create_bank chip bank
set_num_lines chip bank 8
enable_chip chip
sysfs_set_pull chip bank 0 pull-up
$BASE_DIR/gpio-mockup-cdev /dev/`configfs_chip_name chip bank` 0
test "$?" = "1" || fail "pull set incorrectly"
sysfs_set_pull chip bank 0 pull-down
$BASE_DIR/gpio-mockup-cdev /dev/`configfs_chip_name chip bank` 1
test "$?" = "0" || fail "pull set incorrectly"
remove_chip chip
echo "3.2. Pull can be read from sysfs"
create_chip chip
create_bank chip bank
set_num_lines chip bank 8
enable_chip chip
DEVNAME=`configfs_dev_name chip`
CHIPNAME=`configfs_chip_name chip bank`
SYSFS_PATH=/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/pull
test `cat $SYSFS_PATH` = "pull-down" || fail "reading the pull failed"
sysfs_set_pull chip bank 0 pull-up
test `cat $SYSFS_PATH` = "pull-up" || fail "reading the pull failed"
remove_chip chip
echo "3.3. Incorrect input in sysfs is rejected"
create_chip chip
create_bank chip bank
set_num_lines chip bank 8
enable_chip chip
DEVNAME=`configfs_dev_name chip`
CHIPNAME=`configfs_chip_name chip bank`
SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/pull"
echo foobar > $SYSFS_PATH 2> /dev/null && fail "invalid input not detected"
remove_chip chip
echo "3.4. Can't write to value"
create_chip chip
create_bank chip bank
enable_chip chip
DEVNAME=`configfs_dev_name chip`
CHIPNAME=`configfs_chip_name chip bank`
SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
echo 1 > $SYSFS_PATH 2> /dev/null && fail "writing to 'value' succeeded unexpectedly"
remove_chip chip
echo "4. Simulated GPIO chips are functional"
echo "4.1. Values can be read from sysfs"
create_chip chip
create_bank chip bank
set_num_lines chip bank 8
enable_chip chip
DEVNAME=`configfs_dev_name chip`
CHIPNAME=`configfs_chip_name chip bank`
SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
test `cat $SYSFS_PATH` = "0" || fail "incorrect value read from sysfs"
$BASE_DIR/gpio-mockup-cdev -s 1 /dev/`configfs_chip_name chip bank` 0 &
sleep 0.1 # FIXME Any better way?
test `cat $SYSFS_PATH` = "1" || fail "incorrect value read from sysfs"
kill $!
remove_chip chip
echo "4.2. Bias settings work correctly"
create_chip chip
create_bank chip bank
set_num_lines chip bank 8
enable_chip chip
$BASE_DIR/gpio-mockup-cdev -b pull-up /dev/`configfs_chip_name chip bank` 0
test `cat $SYSFS_PATH` = "1" || fail "bias setting does not work"
remove_chip chip
echo "GPIO $MODULE test PASS"