This is the bulk of GPIO changes for v4.4:

GPIO core:
 - Define and handle flags for open drain/open collector
   and open source/open emitter, also know as "single-ended"
   configurations.
 - Generic request/free operations that handle calling out
   to the (optional) pin control backend.
 - Some refactoring related to an ABI change that did not
   happen, yet provide useful.
 - Added a real-time compliance checklist. Many GPIO chips
   have irqchips, and need to think this over with the RT
   patches going upstream.
 - Restructure, fix and clean up Kconfig menus a bit.
 
 New drivers:
 - New driver for AMD Promony.
 - New driver for ACCES 104-IDIO-16, a port-mapped I/O
   card, ISA-style. Very retro.
 
 Subdriver changes:
 - OMAP changes to handle real time requirements.
 - Handle trigger types for edge and level IRQs on PL061
   properly. As this hardware is very common it needs to
   set a proper example for others to follow.
 - Some container_of() cleanups.
 - Delete the unused MSM driver in favor of the driver that
   is embedded inside the pin control driver.
 - Cleanup of the ath79 GPIO driver used by many, many
   OpenWRT router targets.
 - A consolidated IT87xx driver replacing the earlier
   very specific IT8761e driver.
 - Handle the TI TCA9539 in the PCA953x driver. Also
   handle ACPI devices in this subdriver.
 - Drop xilinx arch dependencies as these FPGAs seem to
   profilate over a few different architectures. MIPS and
   ARM come to mind.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJWNz3qAAoJEEEQszewGV1zKlAP/R+mVoQHyfDFurChDzuWQjZK
 T4eDiFGTHr/MUDP9I0jINF400SfEm3ajm3aoPvKc6fA2d7oLNB7TzyUxjDsQV4h8
 NsCJ9IYD9xYgF6SDovPYPZ6SkRJYimDrwjD/DUSR8ijisVzJwYCyEGznelWKnQMo
 Fcw4kOTMrW0034ZT4nGH4kSgIzNAMcecazaaqLisniYZ/4Ozk1CQsrBK1gCO/kr8
 Hh3N/mN4TBvOyIuD7lmN5PnWuJo641rplcWErjxUZYvqEddSfAnpasfAcXMkZ4gM
 jOK+l7VIycxOAn+EJwqjyVPJ0gDPPaMwB836gogzNraO2SYd/R2JvyI2zyTogmdW
 MNwsKwP2b/ma/h0A/JBDFmcMiJwA2QHHgylLrB+vfWAP9o2nJv++Op1/q8ktVR+1
 EgEk9StVvnYqC86DJhYbUbMmX7TorRwPoUo/5Z6C/viyZzOagZge0vYKYTQS99Pq
 B+2aH7pMPLooAdU/cyYy8J20mxQ4RaHoy+TCe0RMRhxnRi9CnnnYNHbZDVdHISpr
 OSfZKSM40DbAAs7UNxIgPXM1qSzia23tgzZEdh5qwQtZBTC6fWr/1xOrTpFW2wY6
 VxqgP/OX23BzJQE4YDnOHLIj8GX0MLqXr7pl2+KBcHO9xvPS6Qj8fFsLEVatCwX0
 Caify6KIbbgMWcVmut/6
 =LDCr
 -----END PGP SIGNATURE-----

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

Pull GPIO updates from Linus Walleij:
 "Here is the bulk of GPIO changes for the v4.4 development cycle.

  The only changes hitting outside drivers/gpio are in the pin control
  subsystem and these seem to have settled nicely in linux-next.

  Development mistakes and catfights are nicely documented in the
  reverts as you can see.  The outcome of the ABI fight is that we're
  working on a chardev ABI for GPIO now, where hope to show results for
  the v4.5 kernel.

  Summary of changes:

  GPIO core:
   - Define and handle flags for open drain/open collector and open
     source/open emitter, also know as "single-ended" configurations.
   - Generic request/free operations that handle calling out to the
     (optional) pin control backend.
   - Some refactoring related to an ABI change that did not happen, yet
     provide useful.
   - Added a real-time compliance checklist.  Many GPIO chips have
     irqchips, and need to think this over with the RT patches going
     upstream.
   - Restructure, fix and clean up Kconfig menus a bit.

  New drivers:
   - New driver for AMD Promony.
   - New driver for ACCES 104-IDIO-16, a port-mapped I/O card,
     ISA-style.  Very retro.

  Subdriver changes:
   - OMAP changes to handle real time requirements.
   - Handle trigger types for edge and level IRQs on PL061 properly.  As
     this hardware is very common it needs to set a proper example for
     others to follow.
   - Some container_of() cleanups.
   - Delete the unused MSM driver in favor of the driver that is
     embedded inside the pin control driver.
   - Cleanup of the ath79 GPIO driver used by many, many OpenWRT router
     targets.
   - A consolidated IT87xx driver replacing the earlier very specific
     IT8761e driver.
   - Handle the TI TCA9539 in the PCA953x driver.  Also handle ACPI
     devices in this subdriver.
   - Drop xilinx arch dependencies as these FPGAs seem to profilate over
     a few different architectures.  MIPS and ARM come to mind"

* tag 'gpio-v4.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (57 commits)
  gpio: fix up SPI submenu
  gpio: drop surplus I2C dependencies
  gpio: drop surplus X86 dependencies
  gpio: dt-bindings: document the official use of "ngpios"
  gpio: MAINTAINERS: Add an entry for the ATH79 GPIO driver
  gpio / ACPI: Allow shared GPIO event to be read via operation region
  gpio: group port-mapped I/O drivers in a menu
  gpio: Add ACCES 104-IDIO-16 driver maintainer entry
  gpio: zynq: Document interrupt-controller DT binding
  gpio: xilinx: Drop architecture dependencies
  gpio: generic: Revert to old error handling in bgpio_map
  gpio: add a real time compliance notes
  Revert "gpio: add a real time compliance checklist"
  gpio: Add GPIO support for the ACCES 104-IDIO-16
  gpio: driver for AMD Promontory
  gpio: xlp: Convert to use gpiolib irqchip helpers
  gpio: add a real time compliance checklist
  gpio/xilinx: enable for MIPS
  gpiolib: Add and use OF_GPIO_SINGLE_ENDED flag
  gpiolib: Split GPIO flags parsing and GPIO configuration
  ...
This commit is contained in:
Linus Torvalds 2015-11-02 12:59:12 -08:00
commit e86328c489
62 changed files with 1733 additions and 1478 deletions

View file

@ -1,26 +0,0 @@
MSM GPIO controller bindings
Required properties:
- compatible:
- "qcom,msm-gpio" for MSM controllers
- #gpio-cells : Should be two.
- first cell is the pin number
- second cell is used to specify optional parameters (unused)
- gpio-controller : Marks the device node as a GPIO controller.
- #interrupt-cells : Should be 2.
- interrupt-controller: Mark the device node as an interrupt controller
- interrupts : Specify the TLMM summary interrupt number
- ngpio : Specify the number of MSM GPIOs
Example:
msmgpio: gpio@fd510000 {
compatible = "qcom,msm-gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
interrupts = <0 208 0>;
ngpio = <150>;
};

View file

@ -24,6 +24,7 @@ Required properties:
ti,tca6408
ti,tca6416
ti,tca6424
ti,tca9539
exar,xra1202
Example:

View file

@ -12,6 +12,13 @@ Required properties:
- interrupts : Interrupt specifier (see interrupt bindings for
details)
- interrupt-parent : Must be core interrupt controller
- interrupt-controller : Marks the device node as an interrupt controller.
- #interrupt-cells : Should be 2. The first cell is the GPIO number.
The second cell bits[3:0] is used to specify trigger type and level flags:
1 = low-to-high edge triggered.
2 = high-to-low edge triggered.
4 = active high level-sensitive.
8 = active low level-sensitive.
- reg : Address and length of the register set for the device
Example:
@ -22,5 +29,7 @@ Example:
gpio-controller;
interrupt-parent = <&intc>;
interrupts = <0 20 4>;
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xe000a000 0x1000>;
};

View file

@ -54,9 +54,13 @@ only uses one.
gpio-specifier may encode: bank, pin position inside the bank,
whether pin is open-drain and whether pin is logically inverted.
Exact meaning of each specifier cell is controller specific, and must
be documented in the device tree binding for the device. Use the macros
defined in include/dt-bindings/gpio/gpio.h whenever possible:
be documented in the device tree binding for the device.
Most controllers are however specifying a generic flag bitfield
in the last cell, so for these, use the macros defined in
include/dt-bindings/gpio/gpio.h whenever possible:
Example of a node using GPIOs:
@ -67,6 +71,15 @@ Example of a node using GPIOs:
GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes
GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
Optional standard bitfield specifiers for the last cell:
- Bit 0: 0 means active high, 1 means active low
- Bit 1: 1 means single-ended wiring, see:
https://en.wikipedia.org/wiki/Single-ended_triode
When used with active-low, this means open drain/collector, see:
https://en.wikipedia.org/wiki/Open_collector
When used with active-high, this means open source/emitter
1.1) GPIO specifier best practices
----------------------------------
@ -118,6 +131,30 @@ Every GPIO controller node must contain both an empty "gpio-controller"
property, and a #gpio-cells integer property, which indicates the number of
cells in a gpio-specifier.
Optionally, a GPIO controller may have a "ngpios" property. This property
indicates the number of in-use slots of available slots for GPIOs. The
typical example is something like this: the hardware register is 32 bits
wide, but only 18 of the bits have a physical counterpart. The driver is
generally written so that all 32 bits can be used, but the IP block is reused
in a lot of designs, some using all 32 bits, some using 18 and some using
12. In this case, setting "ngpios = <18>;" informs the driver that only the
first 18 GPIOs, at local offset 0 .. 17, are in use.
If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an
additional bitmask is needed to specify which GPIOs are actually in use,
and which are dummies. The bindings for this case has not yet been
specified, but should be specified if/when such hardware appears.
Example:
gpio-controller@00000000 {
compatible = "foo";
reg = <0x00000000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
ngpios = <18>;
}
The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
providing automatic GPIO request and configuration as part of the
gpio-controller's driver probe function.

View file

@ -62,6 +62,11 @@ Any debugfs dump method should normally ignore signals which haven't been
requested as GPIOs. They can use gpiochip_is_requested(), which returns either
NULL or the label associated with that GPIO when it was requested.
RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs
(like PM runtime) in its gpio_chip implementation (.get/.set and direction
control callbacks) if it is expected to call GPIO APIs from atomic context
on -RT (inside hard IRQ handlers and similar contexts). Normally this should
not be required.
GPIO drivers providing IRQs
---------------------------
@ -73,6 +78,13 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using
the header <linux/irq.h>. So basically such a driver is utilizing two sub-
systems simultaneously: gpio and irq.
RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs
(like PM runtime) as part of its irq_chip implementation on -RT.
- spinlock_t should be replaced with raw_spinlock_t [1].
- If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks
on an irqchip. Create the callbacks if needed [2].
GPIO irqchips usually fall in one of two categories:
* CHAINED GPIO irqchips: these are usually the type that is embedded on
@ -93,6 +105,38 @@ GPIO irqchips usually fall in one of two categories:
Chained GPIO irqchips typically can NOT set the .can_sleep flag on
struct gpio_chip, as everything happens directly in the callbacks.
RT_FULL: Note, chained IRQ handlers will not be forced threaded on -RT.
As result, spinlock_t or any sleepable APIs (like PM runtime) can't be used
in chained IRQ handler.
if required (and if it can't be converted to the nested threaded GPIO irqchip)
- chained IRQ handler can be converted to generic irq handler and this way
it will be threaded IRQ handler on -RT and hard IRQ handler on non-RT
(for example, see [3]).
Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled,
so IRQ core will complain if it will be called from IRQ handler wich is forced
thread. The "fake?" raw lock can be used to W/A this problem:
raw_spinlock_t wa_lock;
static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
unsigned long wa_lock_flags;
raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, bit));
raw_spin_unlock_irqrestore(&bank->wa_lock, wa_lock_flags);
* GENERIC CHAINED GPIO irqchips: these are the same as "CHAINED GPIO irqchips",
but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is
performed by generic IRQ handler which is configured using request_irq().
The GPIO irqchip will then end up calling something like this sequence in
its interrupt handler:
static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
for each detected GPIO IRQ
generic_handle_irq(...);
RT_FULL: Such kind of handlers will be forced threaded on -RT, as result IRQ
core will complain that generic_handle_irq() is called with IRQ enabled and
the same W/A as for "CHAINED GPIO irqchips" can be applied.
* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any
other GPIO irqchip residing on the other side of a sleeping bus. Of course
such drivers that need slow bus traffic to read out IRQ status and similar,
@ -133,6 +177,13 @@ To use the helpers please keep the following in mind:
the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
properly.
- Nominally set all handlers to handle_bad_irq() in the setup call and pass
handle_bad_irq() as flow handler parameter in gpiochip_irqchip_add() if it is
expected for GPIO driver that irqchip .set_type() callback have to be called
before using/enabling GPIO IRQ. Then set the handler to handle_level_irq()
and/or handle_edge_irq() in the irqchip .set_type() callback depending on
what your controller supports.
It is legal for any IRQ consumer to request an IRQ from any irqchip no matter
if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
irq_chip are orthogonal, and offering their services independent of each
@ -169,6 +220,31 @@ When implementing an irqchip inside a GPIO driver, these two functions should
typically be called in the .startup() and .shutdown() callbacks from the
irqchip.
Real-Time compliance for GPIO IRQ chips
---------------------------------------
Any provider of irqchips needs to be carefully tailored to support Real Time
preemption. It is desireable that all irqchips in the GPIO subsystem keep this
in mind and does the proper testing to assure they are real time-enabled.
So, pay attention on above " RT_FULL:" notes, please.
The following is a checklist to follow when preparing a driver for real
time-compliance:
- ensure spinlock_t is not used as part irq_chip implementation;
- ensure that sleepable APIs are not used as part irq_chip implementation.
If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
and .irq_bus_unlock() callbacks;
- Chained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used
from chained IRQ handler;
- Generic chained GPIO irqchips: take care about generic_handle_irq() calls and
apply corresponding W/A;
- Chained GPIO irqchips: get rid of chained IRQ handler and use generic irq
handler if possible :)
- regmap_mmio: Sry, but you are in trouble :( if MMIO regmap is used as for
GPIO IRQ chip implementation;
- Test your driver with the appropriate in-kernel real time test cases for both
level and edge IRQs.
Requesting self-owned GPIO pins
-------------------------------
@ -190,3 +266,7 @@ gpiochip_free_own_desc().
These functions must be used with care since they do not affect module use
count. Do not use the functions to request gpio descriptors not owned by the
calling driver.
[1] http://www.spinics.net/lists/linux-omap/msg120425.html
[2] https://lkml.org/lkml/2015/9/25/494
[3] https://lkml.org/lkml/2015/9/25/495

View file

@ -240,6 +240,12 @@ L: lm-sensors@lm-sensors.org
S: Maintained
F: drivers/hwmon/abituguru3.c
ACCES 104-IDIO-16 GPIO DRIVER
M: "William Breathitt Gray" <vilhelm.gray@gmail.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-104-idio-16.c
ACENIC DRIVER
M: Jes Sorensen <jes@trained-monkey.org>
L: linux-acenic@sunsite.dk
@ -1780,6 +1786,14 @@ S: Supported
F: Documentation/aoe/
F: drivers/block/aoe/
ATHEROS 71XX/9XXX GPIO DRIVER
M: Alban Bedel <albeu@free.fr>
W: https://github.com/AlbanBedel/linux
T: git git://github.com/AlbanBedel/linux
S: Maintained
F: drivers/gpio/gpio-ath79.c
F: Documentation/devicetree/bindings/gpio/gpio-ath79.txt
ATHEROS ATH GENERIC UTILITIES
M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
L: linux-wireless@vger.kernel.org

View file

@ -119,6 +119,13 @@ config GPIO_ALTERA
If driver is built as a module it will be called gpio-altera.
config GPIO_AMDPT
tristate "AMD Promontory GPIO support"
depends on ACPI
help
driver for GPIO functionality on Promontory IOHub
Require ACPI ASL code to enumerate as a platform device.
config GPIO_BCM_KONA
bool "Broadcom Kona GPIO"
depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
@ -176,16 +183,6 @@ config GPIO_ETRAXFS
help
Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
config GPIO_F7188X
tristate "F71869, F71869A, F71882FG and F71889F GPIO support"
depends on X86
help
This option enables support for GPIOs found on Fintek Super-I/O
chips F71869, F71869A, F71882FG and F71889F.
To compile this driver as a module, choose M here: the module will
be called f7188x-gpio.
config GPIO_GE_FPGA
bool "GE FPGA based GPIO"
depends on GE_FPGA
@ -235,12 +232,6 @@ config GPIO_IOP
If unsure, say N.
config GPIO_IT8761E
tristate "IT8761E GPIO support"
depends on X86 # unconditional access to IO space.
help
Say yes here to support GPIO functionality of IT8761E super I/O chip.
config GPIO_LOONGSON
bool "Loongson-2/3 GPIO support"
depends on CPU_LOONGSON2 || CPU_LOONGSON3
@ -297,14 +288,6 @@ config GPIO_MPC8XXX
Say Y here if you're going to use hardware that connects to the
MPC512x/831x/834x/837x/8572/8610 GPIOs.
config GPIO_MSM_V2
tristate "Qualcomm MSM GPIO v2"
depends on GPIOLIB && OF && ARCH_QCOM
help
Say yes here to support the GPIO interface on ARM v7 based
Qualcomm MSM chips. Most of the pins on the MSM can be
selected for GPIO, and are controlled by this driver.
config GPIO_MVEBU
def_bool y
depends on PLAT_ORION
@ -368,42 +351,6 @@ config GPIO_SAMSUNG
Legacy GPIO support. Use only for platforms without support for
pinctrl.
config GPIO_SCH
tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
depends on PCI && X86
select MFD_CORE
select LPC_SCH
help
Say yes here to support GPIO interface on Intel Poulsbo SCH,
Intel Tunnel Creek processor, Intel Centerton processor or
Intel Quark X1000 SoC.
The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
powered by the core power rail and are turned off during sleep
modes (S3 and higher). The remaining four GPIOs are powered by
the Intel SCH suspend power supply. These GPIOs remain
active during S3. The suspend powered GPIOs can be used to wake the
system from the Suspend-to-RAM state.
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
The Intel Centerton processor has a total of 30 GPIO pins.
Twenty-one are powered by the core power rail and 9 from the
suspend power supply.
The Intel Quark X1000 SoC has 2 GPIOs powered by the core
power well and 6 from the suspend power well.
config GPIO_SCH311X
tristate "SMSC SCH311x SuperI/O GPIO"
help
Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and
SCH3116 "Super I/O" chipsets.
To compile this driver as a module, choose M here: the module will
be called gpio-sch311x.
config GPIO_SPEAR_SPICS
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
depends on PLAT_SPEAR
@ -440,15 +387,6 @@ config GPIO_TB10X
select GENERIC_IRQ_CHIP
select OF_GPIO
config GPIO_TS5500
tristate "TS-5500 DIO blocks and compatibles"
depends on TS5500 || COMPILE_TEST
help
This driver supports Digital I/O exposed by pin blocks found on some
Technologic Systems platforms. It includes, but is not limited to, 3
blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
LCD port.
config GPIO_TZ1090
bool "Toumaz Xenif TZ1090 GPIO support"
depends on SOC_TZ1090
@ -508,13 +446,13 @@ config GPIO_XGENE_SB
config GPIO_XILINX
tristate "Xilinx GPIO support"
depends on OF_GPIO && (PPC || MICROBLAZE || ARCH_ZYNQ || X86)
depends on OF_GPIO
help
Say yes here to support the Xilinx FPGA GPIO device
config GPIO_XLP
tristate "Netlogic XLP GPIO support"
depends on CPU_XLP
depends on CPU_XLP && OF_GPIO
select GPIOLIB_IRQCHIP
help
This driver provides support for GPIO interface on Netlogic XLP MIPS64
@ -545,6 +483,87 @@ config GPIO_ZYNQ
help
Say yes here to support Xilinx Zynq GPIO controller.
config GPIO_ZX
bool "ZTE ZX GPIO support"
select GPIOLIB_IRQCHIP
help
Say yes here to support the GPIO device on ZTE ZX SoCs.
endmenu
menu "Port-mapped I/O GPIO drivers"
depends on X86 # Unconditional I/O space access
config GPIO_104_IDIO_16
tristate "ACCES 104-IDIO-16 GPIO support"
help
Enables GPIO support for the ACCES 104-IDIO-16 family.
config GPIO_F7188X
tristate "F71869, F71869A, F71882FG and F71889F GPIO support"
help
This option enables support for GPIOs found on Fintek Super-I/O
chips F71869, F71869A, F71882FG and F71889F.
To compile this driver as a module, choose M here: the module will
be called f7188x-gpio.
config GPIO_IT87
tristate "IT87xx GPIO support"
help
Say yes here to support GPIO functionality of IT87xx Super I/O chips.
This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and
supports the IT8761E Super I/O chip as well.
To compile this driver as a module, choose M here: the module will
be called gpio_it87
config GPIO_SCH
tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
depends on PCI
select MFD_CORE
select LPC_SCH
help
Say yes here to support GPIO interface on Intel Poulsbo SCH,
Intel Tunnel Creek processor, Intel Centerton processor or
Intel Quark X1000 SoC.
The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
powered by the core power rail and are turned off during sleep
modes (S3 and higher). The remaining four GPIOs are powered by
the Intel SCH suspend power supply. These GPIOs remain
active during S3. The suspend powered GPIOs can be used to wake the
system from the Suspend-to-RAM state.
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
The Intel Centerton processor has a total of 30 GPIO pins.
Twenty-one are powered by the core power rail and 9 from the
suspend power supply.
The Intel Quark X1000 SoC has 2 GPIOs powered by the core
power well and 6 from the suspend power well.
config GPIO_SCH311X
tristate "SMSC SCH311x SuperI/O GPIO"
help
Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and
SCH3116 "Super I/O" chipsets.
To compile this driver as a module, choose M here: the module will
be called gpio-sch311x.
config GPIO_TS5500
tristate "TS-5500 DIO blocks and compatibles"
depends on TS5500 || COMPILE_TEST
help
This driver supports Digital I/O exposed by pin blocks found on some
Technologic Systems platforms. It includes, but is not limited to, 3
blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
LCD port.
endmenu
menu "I2C GPIO expanders"
@ -552,7 +571,6 @@ menu "I2C GPIO expanders"
config GPIO_ADP5588
tristate "ADP5588 I2C GPIO expander"
depends on I2C
help
This option enables support for 18 GPIOs found
on Analog Devices ADP5588 GPIO Expanders.
@ -566,7 +584,7 @@ config GPIO_ADP5588_IRQ
config GPIO_ADNP
tristate "Avionic Design N-bit GPIO expander"
depends on I2C && OF_GPIO
depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
This option enables support for N GPIOs found on Avionic Design
@ -578,14 +596,12 @@ config GPIO_ADNP
config GPIO_MAX7300
tristate "Maxim MAX7300 GPIO expander"
depends on I2C
select GPIO_MAX730X
help
GPIO driver for Maxim MAX7300 I2C-based GPIO expander.
config GPIO_MAX732X
tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
depends on I2C
help
Say yes here to support the MAX7319, MAX7320-7327 series of I2C
Port Expanders. Each IO port on these chips has a fixed role of
@ -618,7 +634,6 @@ config GPIO_MC9S08DZ60
config GPIO_PCA953X
tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
depends on I2C
help
Say yes here to provide access to several register-oriented
SMBus I/O expanders, made mostly by NXP or TI. Compatible
@ -646,7 +661,6 @@ config GPIO_PCA953X_IRQ
config GPIO_PCF857X
tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
depends on I2C
select GPIOLIB_IRQCHIP
select IRQ_DOMAIN
help
@ -976,7 +990,7 @@ menu "SPI GPIO expanders"
config GPIO_74X164
tristate "74x164 serial-in/parallel-out 8-bits shift register"
depends on SPI_MASTER && OF
depends on OF
help
Driver for 74x164 compatible serial-in/parallel-out 8-outputs
shift registers. This driver can be used to provide access
@ -984,33 +998,29 @@ config GPIO_74X164
config GPIO_MAX7301
tristate "Maxim MAX7301 GPIO expander"
depends on SPI_MASTER
select GPIO_MAX730X
help
GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
config GPIO_MC33880
tristate "Freescale MC33880 high-side/low-side switch"
help
SPI driver for Freescale MC33880 high-side/low-side switch.
This provides GPIO interface supporting inputs and outputs.
endmenu
menu "SPI or I2C GPIO expanders"
depends on (SPI_MASTER && !I2C) || I2C
config GPIO_MCP23S08
tristate "Microchip MCP23xxx I/O expander"
depends on (SPI_MASTER && !I2C) || I2C
help
SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
I/O expanders.
This provides a GPIO interface supporting inputs and outputs.
The I2C versions of the chips can be used as interrupt-controller.
config GPIO_MC33880
tristate "Freescale MC33880 high-side/low-side switch"
depends on SPI_MASTER
help
SPI driver for Freescale MC33880 high-side/low-side switch.
This provides GPIO interface supporting inputs and outputs.
config GPIO_ZX
bool "ZTE ZX GPIO support"
select GPIOLIB_IRQCHIP
help
Say yes here to support the GPIO device on ZTE ZX SoCs.
endmenu
menu "USB GPIO expanders"

View file

@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
@ -19,6 +20,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
@ -40,7 +42,7 @@ obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
@ -64,7 +66,6 @@ obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o
obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o

View file

@ -0,0 +1,216 @@
/*
* GPIO driver for the ACCES 104-IDIO-16 family
* Copyright (C) 2015 William Breathitt Gray
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
static unsigned idio_16_base;
module_param(idio_16_base, uint, 0);
MODULE_PARM_DESC(idio_16_base, "ACCES 104-IDIO-16 base address");
/**
* struct idio_16_gpio - GPIO device private data structure
* @chip: instance of the gpio_chip
* @lock: synchronization lock to prevent gpio_set race conditions
* @base: base port address of the GPIO device
* @extent: extent of port address region of the GPIO device
* @out_state: output bits state
*/
struct idio_16_gpio {
struct gpio_chip chip;
spinlock_t lock;
unsigned base;
unsigned extent;
unsigned out_state;
};
static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
if (offset > 15)
return 1;
return 0;
}
static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
return 0;
}
static int idio_16_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
chip->set(chip, offset, value);
return 0;
}
static struct idio_16_gpio *to_idio16gpio(struct gpio_chip *gc)
{
return container_of(gc, struct idio_16_gpio, chip);
}
static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct idio_16_gpio *const idio16gpio = to_idio16gpio(chip);
const unsigned BIT_MASK = 1U << (offset-16);
if (offset < 16)
return -EINVAL;
if (offset < 24)
return !!(inb(idio16gpio->base + 1) & BIT_MASK);
return !!(inb(idio16gpio->base + 5) & (BIT_MASK>>8));
}
static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct idio_16_gpio *const idio16gpio = to_idio16gpio(chip);
const unsigned BIT_MASK = 1U << offset;
unsigned long flags;
if (offset > 15)
return;
spin_lock_irqsave(&idio16gpio->lock, flags);
if (value)
idio16gpio->out_state |= BIT_MASK;
else
idio16gpio->out_state &= ~BIT_MASK;
if (offset > 7)
outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
else
outb(idio16gpio->out_state, idio16gpio->base);
spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
static int __init idio_16_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct idio_16_gpio *idio16gpio;
int err;
const unsigned BASE = idio_16_base;
const unsigned EXTENT = 8;
const char *const NAME = dev_name(dev);
idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
if (!idio16gpio)
return -ENOMEM;
if (!request_region(BASE, EXTENT, NAME)) {
dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n",
NAME, BASE, BASE + EXTENT);
err = -EBUSY;
goto err_lock_io_port;
}
idio16gpio->chip.label = NAME;
idio16gpio->chip.dev = dev;
idio16gpio->chip.owner = THIS_MODULE;
idio16gpio->chip.base = -1;
idio16gpio->chip.ngpio = 32;
idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
idio16gpio->chip.get = idio_16_gpio_get;
idio16gpio->chip.set = idio_16_gpio_set;
idio16gpio->base = BASE;
idio16gpio->extent = EXTENT;
idio16gpio->out_state = 0xFFFF;
spin_lock_init(&idio16gpio->lock);
dev_set_drvdata(dev, idio16gpio);
err = gpiochip_add(&idio16gpio->chip);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
goto err_gpio_register;
}
return 0;
err_gpio_register:
release_region(BASE, EXTENT);
err_lock_io_port:
return err;
}
static int idio_16_remove(struct platform_device *pdev)
{
struct idio_16_gpio *const idio16gpio = platform_get_drvdata(pdev);
gpiochip_remove(&idio16gpio->chip);
release_region(idio16gpio->base, idio16gpio->extent);
return 0;
}
static struct platform_device *idio_16_device;
static struct platform_driver idio_16_driver = {
.driver = {
.name = "104-idio-16"
},
.remove = idio_16_remove
};
static void __exit idio_16_exit(void)
{
platform_device_unregister(idio_16_device);
platform_driver_unregister(&idio_16_driver);
}
static int __init idio_16_init(void)
{
int err;
idio_16_device = platform_device_alloc(idio_16_driver.driver.name, -1);
if (!idio_16_device)
return -ENOMEM;
err = platform_device_add(idio_16_device);
if (err)
goto err_platform_device;
err = platform_driver_probe(&idio_16_driver, idio_16_probe);
if (err)
goto err_platform_driver;
return 0;
err_platform_driver:
platform_device_del(idio_16_device);
err_platform_device:
platform_device_put(idio_16_device);
return err;
}
module_init(idio_16_init);
module_exit(idio_16_exit);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
MODULE_LICENSE("GPL");

View file

@ -42,6 +42,11 @@ struct altera_gpio_chip {
int mapped_irq;
};
static struct altera_gpio_chip *to_altera(struct gpio_chip *gc)
{
return container_of(gc, struct altera_gpio_chip, mmchip.gc);
}
static void altera_gpio_irq_unmask(struct irq_data *d)
{
struct altera_gpio_chip *altera_gc;
@ -49,7 +54,7 @@ static void altera_gpio_irq_unmask(struct irq_data *d)
unsigned long flags;
u32 intmask;
altera_gc = irq_data_get_irq_chip_data(d);
altera_gc = to_altera(irq_data_get_irq_chip_data(d));
mm_gc = &altera_gc->mmchip;
spin_lock_irqsave(&altera_gc->gpio_lock, flags);
@ -67,7 +72,7 @@ static void altera_gpio_irq_mask(struct irq_data *d)
unsigned long flags;
u32 intmask;
altera_gc = irq_data_get_irq_chip_data(d);
altera_gc = to_altera(irq_data_get_irq_chip_data(d));
mm_gc = &altera_gc->mmchip;
spin_lock_irqsave(&altera_gc->gpio_lock, flags);
@ -87,7 +92,7 @@ static int altera_gpio_irq_set_type(struct irq_data *d,
{
struct altera_gpio_chip *altera_gc;
altera_gc = irq_data_get_irq_chip_data(d);
altera_gc = to_altera(irq_data_get_irq_chip_data(d));
if (type == IRQ_TYPE_NONE)
return 0;
@ -210,7 +215,7 @@ static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
unsigned long status;
int i;
altera_gc = irq_desc_get_handler_data(desc);
altera_gc = to_altera(irq_desc_get_handler_data(desc));
chip = irq_desc_get_chip(desc);
mm_gc = &altera_gc->mmchip;
irqdomain = altera_gc->mmchip.gc.irqdomain;
@ -239,7 +244,7 @@ static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
unsigned long status;
int i;
altera_gc = irq_desc_get_handler_data(desc);
altera_gc = to_altera(irq_desc_get_handler_data(desc));
chip = irq_desc_get_chip(desc);
mm_gc = &altera_gc->mmchip;
irqdomain = altera_gc->mmchip.gc.irqdomain;

261
drivers/gpio/gpio-amdpt.c Normal file
View file

@ -0,0 +1,261 @@
/*
* AMD Promontory GPIO driver
*
* Copyright (C) 2015 ASMedia Technology Inc.
* Author: YD Tseng <yd_tseng@asmedia.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio/driver.h>
#include <linux/spinlock.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#define PT_TOTAL_GPIO 8
/* PCI-E MMIO register offsets */
#define PT_DIRECTION_REG 0x00
#define PT_INPUTDATA_REG 0x04
#define PT_OUTPUTDATA_REG 0x08
#define PT_CLOCKRATE_REG 0x0C
#define PT_SYNC_REG 0x28
struct pt_gpio_chip {
struct gpio_chip gc;
void __iomem *reg_base;
spinlock_t lock;
};
#define to_pt_gpio(c) container_of(c, struct pt_gpio_chip, gc)
static int pt_gpio_request(struct gpio_chip *gc, unsigned offset)
{
struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
unsigned long flags;
u32 using_pins;
dev_dbg(gc->dev, "pt_gpio_request offset=%x\n", offset);
spin_lock_irqsave(&pt_gpio->lock, flags);
using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
if (using_pins & BIT(offset)) {
dev_warn(gc->dev, "PT GPIO pin %x reconfigured\n",
offset);
spin_unlock_irqrestore(&pt_gpio->lock, flags);
return -EINVAL;
}
writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG);
spin_unlock_irqrestore(&pt_gpio->lock, flags);
return 0;
}
static void pt_gpio_free(struct gpio_chip *gc, unsigned offset)
{
struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
unsigned long flags;
u32 using_pins;
spin_lock_irqsave(&pt_gpio->lock, flags);
using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
using_pins &= ~BIT(offset);
writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG);
spin_unlock_irqrestore(&pt_gpio->lock, flags);
dev_dbg(gc->dev, "pt_gpio_free offset=%x\n", offset);
}
static void pt_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
{
struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
unsigned long flags;
u32 data;
dev_dbg(gc->dev, "pt_gpio_set_value offset=%x, value=%x\n",
offset, value);
spin_lock_irqsave(&pt_gpio->lock, flags);
data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
data &= ~BIT(offset);
if (value)
data |= BIT(offset);
writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG);
spin_unlock_irqrestore(&pt_gpio->lock, flags);
}
static int pt_gpio_get_value(struct gpio_chip *gc, unsigned offset)
{
struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
unsigned long flags;
u32 data;
spin_lock_irqsave(&pt_gpio->lock, flags);
data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
/* configure as output */
if (data & BIT(offset))
data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
else /* configure as input */
data = readl(pt_gpio->reg_base + PT_INPUTDATA_REG);
spin_unlock_irqrestore(&pt_gpio->lock, flags);
data >>= offset;
data &= 1;
dev_dbg(gc->dev, "pt_gpio_get_value offset=%x, value=%x\n",
offset, data);
return data;
}
static int pt_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
unsigned long flags;
u32 data;
dev_dbg(gc->dev, "pt_gpio_dirction_input offset=%x\n", offset);
spin_lock_irqsave(&pt_gpio->lock, flags);
data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
data &= ~BIT(offset);
writel(data, pt_gpio->reg_base + PT_DIRECTION_REG);
spin_unlock_irqrestore(&pt_gpio->lock, flags);
return 0;
}
static int pt_gpio_direction_output(struct gpio_chip *gc,
unsigned offset, int value)
{
struct pt_gpio_chip *pt_gpio = to_pt_gpio(gc);
unsigned long flags;
u32 data;
dev_dbg(gc->dev, "pt_gpio_direction_output offset=%x, value=%x\n",
offset, value);
spin_lock_irqsave(&pt_gpio->lock, flags);
data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
if (value)
data |= BIT(offset);
else
data &= ~BIT(offset);
writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG);
data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
data |= BIT(offset);
writel(data, pt_gpio->reg_base + PT_DIRECTION_REG);
spin_unlock_irqrestore(&pt_gpio->lock, flags);
return 0;
}
static int pt_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acpi_device *acpi_dev;
acpi_handle handle = ACPI_HANDLE(dev);
struct pt_gpio_chip *pt_gpio;
struct resource *res_mem;
int ret = 0;
if (acpi_bus_get_device(handle, &acpi_dev)) {
dev_err(dev, "PT GPIO device node not found\n");
return -ENODEV;
}
pt_gpio = devm_kzalloc(dev, sizeof(struct pt_gpio_chip), GFP_KERNEL);
if (!pt_gpio)
return -ENOMEM;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_mem) {
dev_err(&pdev->dev, "Failed to get MMIO resource for PT GPIO.\n");
return -EINVAL;
}
pt_gpio->reg_base = devm_ioremap_resource(dev, res_mem);
if (IS_ERR(pt_gpio->reg_base)) {
dev_err(&pdev->dev, "Failed to map MMIO resource for PT GPIO.\n");
return PTR_ERR(pt_gpio->reg_base);
}
spin_lock_init(&pt_gpio->lock);
pt_gpio->gc.label = pdev->name;
pt_gpio->gc.owner = THIS_MODULE;
pt_gpio->gc.dev = dev;
pt_gpio->gc.request = pt_gpio_request;
pt_gpio->gc.free = pt_gpio_free;
pt_gpio->gc.direction_input = pt_gpio_direction_input;
pt_gpio->gc.direction_output = pt_gpio_direction_output;
pt_gpio->gc.get = pt_gpio_get_value;
pt_gpio->gc.set = pt_gpio_set_value;
pt_gpio->gc.base = -1;
pt_gpio->gc.ngpio = PT_TOTAL_GPIO;
#if defined(CONFIG_OF_GPIO)
pt_gpio->gc.of_node = pdev->dev.of_node;
#endif
ret = gpiochip_add(&pt_gpio->gc);
if (ret) {
dev_err(&pdev->dev, "Failed to register GPIO lib\n");
return ret;
}
platform_set_drvdata(pdev, pt_gpio);
/* initialize register setting */
writel(0, pt_gpio->reg_base + PT_SYNC_REG);
writel(0, pt_gpio->reg_base + PT_CLOCKRATE_REG);
dev_dbg(&pdev->dev, "PT GPIO driver loaded\n");
return ret;
}
static int pt_gpio_remove(struct platform_device *pdev)
{
struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev);
gpiochip_remove(&pt_gpio->gc);
return 0;
}
static const struct acpi_device_id pt_gpio_acpi_match[] = {
{ "AMDF030", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match);
static struct platform_driver pt_gpio_driver = {
.driver = {
.name = "pt-gpio",
.acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),
},
.probe = pt_gpio_probe,
.remove = pt_gpio_remove,
};
module_platform_driver(pt_gpio_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("YD Tseng <yd_tseng@asmedia.com.tw>");
MODULE_DESCRIPTION("AMD Promontory GPIO Driver");

View file

@ -118,6 +118,8 @@ static int arizona_gpio_probe(struct platform_device *pdev)
case WM5110:
case WM8280:
case WM8997:
case WM8998:
case WM1814:
arizona_gpio->gpio_chip.ngpio = 5;
break;
default:

View file

@ -12,61 +12,51 @@
* by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/platform_data/gpio-ath79.h>
#include <linux/of_device.h>
#include <asm/mach-ath79/ar71xx_regs.h>
static void __iomem *ath79_gpio_base;
static u32 ath79_gpio_count;
static DEFINE_SPINLOCK(ath79_gpio_lock);
struct ath79_gpio_ctrl {
struct gpio_chip chip;
void __iomem *base;
spinlock_t lock;
};
static void __ath79_gpio_set_value(unsigned gpio, int value)
{
void __iomem *base = ath79_gpio_base;
if (value)
__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
else
__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
}
static int __ath79_gpio_get_value(unsigned gpio)
{
return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
}
static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
{
return __ath79_gpio_get_value(offset);
}
#define to_ath79_gpio_ctrl(c) container_of(c, struct ath79_gpio_ctrl, chip)
static void ath79_gpio_set_value(struct gpio_chip *chip,
unsigned offset, int value)
unsigned gpio, int value)
{
__ath79_gpio_set_value(offset, value);
struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
if (value)
__raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_SET);
else
__raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_CLEAR);
}
static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
return (__raw_readl(ctrl->base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
}
static int ath79_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
void __iomem *base = ath79_gpio_base;
struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
spin_lock_irqsave(&ath79_gpio_lock, flags);
spin_lock_irqsave(&ctrl->lock, flags);
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
base + AR71XX_GPIO_REG_OE);
__raw_writel(
__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset),
ctrl->base + AR71XX_GPIO_REG_OE);
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
@ -74,35 +64,37 @@ static int ath79_gpio_direction_input(struct gpio_chip *chip,
static int ath79_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
void __iomem *base = ath79_gpio_base;
struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
spin_lock_irqsave(&ath79_gpio_lock, flags);
spin_lock_irqsave(&ctrl->lock, flags);
if (value)
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
else
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
base + AR71XX_GPIO_REG_OE);
__raw_writel(
__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
ctrl->base + AR71XX_GPIO_REG_OE);
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
void __iomem *base = ath79_gpio_base;
struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
spin_lock_irqsave(&ath79_gpio_lock, flags);
spin_lock_irqsave(&ctrl->lock, flags);
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
base + AR71XX_GPIO_REG_OE);
__raw_writel(
__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset),
ctrl->base + AR71XX_GPIO_REG_OE);
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
@ -110,25 +102,26 @@ static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
int value)
{
void __iomem *base = ath79_gpio_base;
struct ath79_gpio_ctrl *ctrl = to_ath79_gpio_ctrl(chip);
unsigned long flags;
spin_lock_irqsave(&ath79_gpio_lock, flags);
spin_lock_irqsave(&ctrl->lock, flags);
if (value)
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET);
else
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
__raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
base + AR71XX_GPIO_REG_OE);
__raw_writel(
__raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & BIT(offset),
ctrl->base + AR71XX_GPIO_REG_OE);
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
spin_unlock_irqrestore(&ctrl->lock, flags);
return 0;
}
static struct gpio_chip ath79_gpio_chip = {
static const struct gpio_chip ath79_gpio_chip = {
.label = "ath79",
.get = ath79_gpio_get_value,
.set = ath79_gpio_set_value,
@ -147,10 +140,16 @@ static int ath79_gpio_probe(struct platform_device *pdev)
{
struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data;
struct device_node *np = pdev->dev.of_node;
struct ath79_gpio_ctrl *ctrl;
struct resource *res;
u32 ath79_gpio_count;
bool oe_inverted;
int err;
ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
if (!ctrl)
return -ENOMEM;
if (np) {
err = of_property_read_u32(np, "ngpios", &ath79_gpio_count);
if (err) {
@ -171,19 +170,21 @@ static int ath79_gpio_probe(struct platform_device *pdev)
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ath79_gpio_base = devm_ioremap_nocache(
ctrl->base = devm_ioremap_nocache(
&pdev->dev, res->start, resource_size(res));
if (!ath79_gpio_base)
if (!ctrl->base)
return -ENOMEM;
ath79_gpio_chip.dev = &pdev->dev;
ath79_gpio_chip.ngpio = ath79_gpio_count;
spin_lock_init(&ctrl->lock);
memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip));
ctrl->chip.dev = &pdev->dev;
ctrl->chip.ngpio = ath79_gpio_count;
if (oe_inverted) {
ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
ctrl->chip.direction_input = ar934x_gpio_direction_input;
ctrl->chip.direction_output = ar934x_gpio_direction_output;
}
err = gpiochip_add(&ath79_gpio_chip);
err = gpiochip_add(&ctrl->chip);
if (err) {
dev_err(&pdev->dev,
"cannot add AR71xx GPIO chip, error=%d", err);

View file

@ -176,6 +176,11 @@ static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = {
.rw_intr_pins = ARTPEC3_rw_intr_pins,
};
static struct etraxfs_gpio_chip *to_etraxfs(struct gpio_chip *gc)
{
return container_of(gc, struct etraxfs_gpio_chip, bgc.gc);
}
static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc)
{
return gc->label[0] - 'A';
@ -220,7 +225,8 @@ static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip,
static void etraxfs_gpio_irq_ack(struct irq_data *d)
{
struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct etraxfs_gpio_chip *chip =
to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
@ -229,7 +235,8 @@ static void etraxfs_gpio_irq_ack(struct irq_data *d)
static void etraxfs_gpio_irq_mask(struct irq_data *d)
{
struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct etraxfs_gpio_chip *chip =
to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
@ -241,7 +248,8 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d)
static void etraxfs_gpio_irq_unmask(struct irq_data *d)
{
struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct etraxfs_gpio_chip *chip =
to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
@ -253,7 +261,8 @@ static void etraxfs_gpio_irq_unmask(struct irq_data *d)
static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
{
struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct etraxfs_gpio_chip *chip =
to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
u32 cfg;
@ -289,7 +298,8 @@ static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
{
struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct etraxfs_gpio_chip *chip =
to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
int ret = -EBUSY;
@ -319,7 +329,8 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
{
struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct etraxfs_gpio_chip *chip =
to_etraxfs(irq_data_get_irq_chip_data(d));
struct etraxfs_gpio_block *block = chip->block;
unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);

View file

@ -579,40 +579,20 @@ EXPORT_SYMBOL_GPL(bgpio_init);
static void __iomem *bgpio_map(struct platform_device *pdev,
const char *name,
resource_size_t sane_sz,
int *err)
resource_size_t sane_sz)
{
struct device *dev = &pdev->dev;
struct resource *r;
resource_size_t start;
resource_size_t sz;
void __iomem *ret;
*err = 0;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
if (!r)
return NULL;
sz = resource_size(r);
if (sz != sane_sz) {
*err = -EINVAL;
return NULL;
}
if (sz != sane_sz)
return IOMEM_ERR_PTR(-EINVAL);
start = r->start;
if (!devm_request_mem_region(dev, start, sz, r->name)) {
*err = -EBUSY;
return NULL;
}
ret = devm_ioremap(dev, start, sz);
if (!ret) {
*err = -ENOMEM;
return NULL;
}
return ret;
return devm_ioremap_resource(&pdev->dev, r);
}
static int bgpio_pdev_probe(struct platform_device *pdev)
@ -636,25 +616,25 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
sz = resource_size(r);
dat = bgpio_map(pdev, "dat", sz, &err);
if (!dat)
return err ? err : -EINVAL;
dat = bgpio_map(pdev, "dat", sz);
if (IS_ERR(dat))
return PTR_ERR(dat);
set = bgpio_map(pdev, "set", sz, &err);
if (err)
return err;
set = bgpio_map(pdev, "set", sz);
if (IS_ERR(set))
return PTR_ERR(set);
clr = bgpio_map(pdev, "clr", sz, &err);
if (err)
return err;
clr = bgpio_map(pdev, "clr", sz);
if (IS_ERR(clr))
return PTR_ERR(clr);
dirout = bgpio_map(pdev, "dirout", sz, &err);
if (err)
return err;
dirout = bgpio_map(pdev, "dirout", sz);
if (IS_ERR(dirout))
return PTR_ERR(dirout);
dirin = bgpio_map(pdev, "dirin", sz, &err);
if (err)
return err;
dirin = bgpio_map(pdev, "dirin", sz);
if (IS_ERR(dirin))
return PTR_ERR(dirin);
bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
if (!bgc)

411
drivers/gpio/gpio-it87.c Normal file
View file

@ -0,0 +1,411 @@
/*
* GPIO interface for IT87xx Super I/O chips
*
* Author: Diego Elio Pettenò <flameeyes@flameeyes.eu>
*
* Based on it87_wdt.c by Oliver Schuster
* gpio-it8761e.c by Denis Turischev
* gpio-stmpe.c by Rabin Vincent
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/gpio.h>
/* Chip Id numbers */
#define NO_DEV_ID 0xffff
#define IT8728_ID 0x8728
#define IT8732_ID 0x8732
#define IT8761_ID 0x8761
/* IO Ports */
#define REG 0x2e
#define VAL 0x2f
/* Logical device Numbers LDN */
#define GPIO 0x07
/* Configuration Registers and Functions */
#define LDNREG 0x07
#define CHIPID 0x20
#define CHIPREV 0x22
/**
* struct it87_gpio - it87-specific GPIO chip
* @chip the underlying gpio_chip structure
* @lock a lock to avoid races between operations
* @io_base base address for gpio ports
* @io_size size of the port rage starting from io_base.
* @output_base Super I/O register address for Output Enable register
* @simple_base Super I/O 'Simple I/O' Enable register
* @simple_size Super IO 'Simple I/O' Enable register size; this is
* required because IT87xx chips might only provide Simple I/O
* switches on a subset of lines, whereas the others keep the
* same status all time.
*/
struct it87_gpio {
struct gpio_chip chip;
spinlock_t lock;
u16 io_base;
u16 io_size;
u8 output_base;
u8 simple_base;
u8 simple_size;
};
static struct it87_gpio it87_gpio_chip = {
.lock = __SPIN_LOCK_UNLOCKED(it87_gpio_chip.lock),
};
static inline struct it87_gpio *to_it87_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct it87_gpio, chip);
}
/* Superio chip access functions; copied from wdt_it87 */
static inline int superio_enter(void)
{
/*
* Try to reserve REG and REG + 1 for exclusive access.
*/
if (!request_muxed_region(REG, 2, KBUILD_MODNAME))
return -EBUSY;
outb(0x87, REG);
outb(0x01, REG);
outb(0x55, REG);
outb(0x55, REG);
return 0;
}
static inline void superio_exit(void)
{
outb(0x02, REG);
outb(0x02, VAL);
release_region(REG, 2);
}
static inline void superio_select(int ldn)
{
outb(LDNREG, REG);
outb(ldn, VAL);
}
static inline int superio_inb(int reg)
{
outb(reg, REG);
return inb(VAL);
}
static inline void superio_outb(int val, int reg)
{
outb(reg, REG);
outb(val, VAL);
}
static inline int superio_inw(int reg)
{
int val;
outb(reg++, REG);
val = inb(VAL) << 8;
outb(reg, REG);
val |= inb(VAL);
return val;
}
static inline void superio_outw(int val, int reg)
{
outb(reg++, REG);
outb(val >> 8, VAL);
outb(reg, REG);
outb(val, VAL);
}
static inline void superio_set_mask(int mask, int reg)
{
u8 curr_val = superio_inb(reg);
u8 new_val = curr_val | mask;
if (curr_val != new_val)
superio_outb(new_val, reg);
}
static inline void superio_clear_mask(int mask, int reg)
{
u8 curr_val = superio_inb(reg);
u8 new_val = curr_val & ~mask;
if (curr_val != new_val)
superio_outb(new_val, reg);
}
static int it87_gpio_request(struct gpio_chip *chip, unsigned gpio_num)
{
u8 mask, group;
int rc = 0;
struct it87_gpio *it87_gpio = to_it87_gpio(chip);
mask = 1 << (gpio_num % 8);
group = (gpio_num / 8);
spin_lock(&it87_gpio->lock);
rc = superio_enter();
if (rc)
goto exit;
/* not all the IT87xx chips support Simple I/O and not all of
* them allow all the lines to be set/unset to Simple I/O.
*/
if (group < it87_gpio->simple_size)
superio_set_mask(mask, group + it87_gpio->simple_base);
/* clear output enable, setting the pin to input, as all the
* newly-exported GPIO interfaces are set to input.
*/
superio_clear_mask(mask, group + it87_gpio->output_base);
superio_exit();
exit:
spin_unlock(&it87_gpio->lock);
return rc;
}
static int it87_gpio_get(struct gpio_chip *chip, unsigned gpio_num)
{
u16 reg;
u8 mask;
struct it87_gpio *it87_gpio = to_it87_gpio(chip);
mask = 1 << (gpio_num % 8);
reg = (gpio_num / 8) + it87_gpio->io_base;
return !!(inb(reg) & mask);
}
static int it87_gpio_direction_in(struct gpio_chip *chip, unsigned gpio_num)
{
u8 mask, group;
int rc = 0;
struct it87_gpio *it87_gpio = to_it87_gpio(chip);
mask = 1 << (gpio_num % 8);
group = (gpio_num / 8);
spin_lock(&it87_gpio->lock);
rc = superio_enter();
if (rc)
goto exit;
/* clear the output enable bit */
superio_clear_mask(mask, group + it87_gpio->output_base);
superio_exit();
exit:
spin_unlock(&it87_gpio->lock);
return rc;
}
static void it87_gpio_set(struct gpio_chip *chip,
unsigned gpio_num, int val)
{
u8 mask, curr_vals;
u16 reg;
struct it87_gpio *it87_gpio = to_it87_gpio(chip);
mask = 1 << (gpio_num % 8);
reg = (gpio_num / 8) + it87_gpio->io_base;
curr_vals = inb(reg);
if (val)
outb(curr_vals | mask, reg);
else
outb(curr_vals & ~mask, reg);
}
static int it87_gpio_direction_out(struct gpio_chip *chip,
unsigned gpio_num, int val)
{
u8 mask, group;
int rc = 0;
struct it87_gpio *it87_gpio = to_it87_gpio(chip);
mask = 1 << (gpio_num % 8);
group = (gpio_num / 8);
spin_lock(&it87_gpio->lock);
rc = superio_enter();
if (rc)
goto exit;
/* set the output enable bit */
superio_set_mask(mask, group + it87_gpio->output_base);
it87_gpio_set(chip, gpio_num, val);
superio_exit();
exit:
spin_unlock(&it87_gpio->lock);
return rc;
}
static struct gpio_chip it87_template_chip = {
.label = KBUILD_MODNAME,
.owner = THIS_MODULE,
.request = it87_gpio_request,
.get = it87_gpio_get,
.direction_input = it87_gpio_direction_in,
.set = it87_gpio_set,
.direction_output = it87_gpio_direction_out,
.base = -1
};
static int __init it87_gpio_init(void)
{
int rc = 0, i;
u16 chip_type;
u8 chip_rev, gpio_ba_reg;
char *labels, **labels_table;
struct it87_gpio *it87_gpio = &it87_gpio_chip;
rc = superio_enter();
if (rc)
return rc;
chip_type = superio_inw(CHIPID);
chip_rev = superio_inb(CHIPREV) & 0x0f;
superio_exit();
it87_gpio->chip = it87_template_chip;
switch (chip_type) {
case IT8728_ID:
case IT8732_ID:
gpio_ba_reg = 0x62;
it87_gpio->io_size = 8;
it87_gpio->output_base = 0xc8;
it87_gpio->simple_base = 0xc0;
it87_gpio->simple_size = 5;
it87_gpio->chip.ngpio = 64;
break;
case IT8761_ID:
gpio_ba_reg = 0x60;
it87_gpio->io_size = 4;
it87_gpio->output_base = 0xf0;
it87_gpio->simple_size = 0;
it87_gpio->chip.ngpio = 16;
break;
case NO_DEV_ID:
pr_err("no device\n");
return -ENODEV;
default:
pr_err("Unknown Chip found, Chip %04x Revision %x\n",
chip_type, chip_rev);
return -ENODEV;
}
rc = superio_enter();
if (rc)
return rc;
superio_select(GPIO);
/* fetch GPIO base address */
it87_gpio->io_base = superio_inw(gpio_ba_reg);
superio_exit();
pr_info("Found Chip IT%04x rev %x. %u GPIO lines starting at %04xh\n",
chip_type, chip_rev, it87_gpio->chip.ngpio,
it87_gpio->io_base);
if (!request_region(it87_gpio->io_base, it87_gpio->io_size,
KBUILD_MODNAME))
return -EBUSY;
/* Set up aliases for the GPIO connection.
*
* ITE documentation for recent chips such as the IT8728F
* refers to the GPIO lines as GPxy, with a coordinates system
* where x is the GPIO group (starting from 1) and y is the
* bit within the group.
*
* By creating these aliases, we make it easier to understand
* to which GPIO pin we're referring to.
*/
labels = kcalloc(it87_gpio->chip.ngpio, sizeof("it87_gpXY"),
GFP_KERNEL);
labels_table = kcalloc(it87_gpio->chip.ngpio, sizeof(const char *),
GFP_KERNEL);
if (!labels || !labels_table) {
rc = -ENOMEM;
goto labels_free;
}
for (i = 0; i < it87_gpio->chip.ngpio; i++) {
char *label = &labels[i * sizeof("it87_gpXY")];
sprintf(label, "it87_gp%u%u", 1+(i/8), i%8);
labels_table[i] = label;
}
it87_gpio->chip.names = (const char *const*)labels_table;
rc = gpiochip_add(&it87_gpio->chip);
if (rc)
goto labels_free;
return 0;
labels_free:
kfree(labels_table);
kfree(labels);
release_region(it87_gpio->io_base, it87_gpio->io_size);
return rc;
}
static void __exit it87_gpio_exit(void)
{
struct it87_gpio *it87_gpio = &it87_gpio_chip;
gpiochip_remove(&it87_gpio->chip);
release_region(it87_gpio->io_base, it87_gpio->io_size);
kfree(it87_gpio->chip.names[0]);
kfree(it87_gpio->chip.names);
}
module_init(it87_gpio_init);
module_exit(it87_gpio_exit);
MODULE_AUTHOR("Diego Elio Pettenò <flameeyes@flameeyes.eu>");
MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips");
MODULE_LICENSE("GPL");

View file

@ -1,230 +0,0 @@
/*
* GPIO interface for IT8761E Super I/O chip
*
* Author: Denis Turischev <denis@compulab.co.il>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/gpio.h>
#define SIO_CHIP_ID 0x8761
#define CHIP_ID_HIGH_BYTE 0x20
#define CHIP_ID_LOW_BYTE 0x21
static u8 ports[2] = { 0x2e, 0x4e };
static u8 port;
static DEFINE_SPINLOCK(sio_lock);
#define GPIO_NAME "it8761-gpio"
#define GPIO_BA_HIGH_BYTE 0x60
#define GPIO_BA_LOW_BYTE 0x61
#define GPIO_IOSIZE 4
#define GPIO1X_IO 0xf0
#define GPIO2X_IO 0xf1
static u16 gpio_ba;
static u8 read_reg(u8 addr, u8 port)
{
outb(addr, port);
return inb(port + 1);
}
static void write_reg(u8 data, u8 addr, u8 port)
{
outb(addr, port);
outb(data, port + 1);
}
static void enter_conf_mode(u8 port)
{
outb(0x87, port);
outb(0x61, port);
outb(0x55, port);
outb((port == 0x2e) ? 0x55 : 0xaa, port);
}
static void exit_conf_mode(u8 port)
{
outb(0x2, port);
outb(0x2, port + 1);
}
static void enter_gpio_mode(u8 port)
{
write_reg(0x2, 0x7, port);
}
static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
{
u16 reg;
u8 bit;
bit = gpio_num % 8;
reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
return !!(inb(reg) & (1 << bit));
}
static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
{
u8 curr_dirs;
u8 io_reg, bit;
bit = gpio_num % 8;
io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
spin_lock(&sio_lock);
enter_conf_mode(port);
enter_gpio_mode(port);
curr_dirs = read_reg(io_reg, port);
if (curr_dirs & (1 << bit))
write_reg(curr_dirs & ~(1 << bit), io_reg, port);
exit_conf_mode(port);
spin_unlock(&sio_lock);
return 0;
}
static void it8761e_gpio_set(struct gpio_chip *gc,
unsigned gpio_num, int val)
{
u8 curr_vals, bit;
u16 reg;
bit = gpio_num % 8;
reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
spin_lock(&sio_lock);
curr_vals = inb(reg);
if (val)
outb(curr_vals | (1 << bit), reg);
else
outb(curr_vals & ~(1 << bit), reg);
spin_unlock(&sio_lock);
}
static int it8761e_gpio_direction_out(struct gpio_chip *gc,
unsigned gpio_num, int val)
{
u8 curr_dirs, io_reg, bit;
bit = gpio_num % 8;
io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
it8761e_gpio_set(gc, gpio_num, val);
spin_lock(&sio_lock);
enter_conf_mode(port);
enter_gpio_mode(port);
curr_dirs = read_reg(io_reg, port);
if (!(curr_dirs & (1 << bit)))
write_reg(curr_dirs | (1 << bit), io_reg, port);
exit_conf_mode(port);
spin_unlock(&sio_lock);
return 0;
}
static struct gpio_chip it8761e_gpio_chip = {
.label = GPIO_NAME,
.owner = THIS_MODULE,
.get = it8761e_gpio_get,
.direction_input = it8761e_gpio_direction_in,
.set = it8761e_gpio_set,
.direction_output = it8761e_gpio_direction_out,
};
static int __init it8761e_gpio_init(void)
{
int i, id, err;
/* chip and port detection */
for (i = 0; i < ARRAY_SIZE(ports); i++) {
spin_lock(&sio_lock);
enter_conf_mode(ports[i]);
id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
read_reg(CHIP_ID_LOW_BYTE, ports[i]);
exit_conf_mode(ports[i]);
spin_unlock(&sio_lock);
if (id == SIO_CHIP_ID) {
port = ports[i];
break;
}
}
if (!port)
return -ENODEV;
/* fetch GPIO base address */
enter_conf_mode(port);
enter_gpio_mode(port);
gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
read_reg(GPIO_BA_LOW_BYTE, port);
exit_conf_mode(port);
if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
return -EBUSY;
it8761e_gpio_chip.base = -1;
it8761e_gpio_chip.ngpio = 16;
err = gpiochip_add(&it8761e_gpio_chip);
if (err < 0)
goto gpiochip_add_err;
return 0;
gpiochip_add_err:
release_region(gpio_ba, GPIO_IOSIZE);
gpio_ba = 0;
return err;
}
static void __exit it8761e_gpio_exit(void)
{
if (gpio_ba) {
gpiochip_remove(&it8761e_gpio_chip);
release_region(gpio_ba, GPIO_IOSIZE);
gpio_ba = 0;
}
}
module_init(it8761e_gpio_init);
module_exit(it8761e_gpio_exit);
MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
MODULE_LICENSE("GPL");

View file

@ -36,16 +36,6 @@ static inline struct lpc18xx_gpio_chip *to_lpc18xx_gpio(struct gpio_chip *chip)
return container_of(chip, struct lpc18xx_gpio_chip, gpio);
}
static int lpc18xx_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(offset);
}
static void lpc18xx_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(offset);
}
static void lpc18xx_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct lpc18xx_gpio_chip *gc = to_lpc18xx_gpio(chip);
@ -95,8 +85,8 @@ static int lpc18xx_gpio_direction_output(struct gpio_chip *chip,
static struct gpio_chip lpc18xx_chip = {
.label = "lpc18xx/43xx-gpio",
.request = lpc18xx_gpio_request,
.free = lpc18xx_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.direction_input = lpc18xx_gpio_direction_input,
.direction_output = lpc18xx_gpio_direction_output,
.set = lpc18xx_gpio_set,

View file

@ -236,7 +236,6 @@ int __max730x_remove(struct device *dev)
ts->write(dev, 0x04, 0x00);
gpiochip_remove(&ts->chip);
mutex_destroy(&ts->lock);
kfree(ts);
return 0;
}
EXPORT_SYMBOL_GPL(__max730x_remove);

View file

@ -29,16 +29,6 @@
#define GPIO_DATA_IN 0x04
#define GPIO_PIN_DIRECTION 0x08
static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(offset);
}
static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(offset);
}
static int moxart_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -66,8 +56,8 @@ static int moxart_gpio_probe(struct platform_device *pdev)
}
bgc->gc.label = "moxart-gpio";
bgc->gc.request = moxart_gpio_request;
bgc->gc.free = moxart_gpio_free;
bgc->gc.request = gpiochip_generic_request;
bgc->gc.free = gpiochip_generic_free;
bgc->data = bgc->read_reg(bgc->reg_set);
bgc->gc.base = 0;
bgc->gc.ngpio = 32;

View file

@ -1,453 +0,0 @@
/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#define MAX_NR_GPIO 300
/* Bits of interest in the GPIO_IN_OUT register.
*/
enum {
GPIO_IN = 0,
GPIO_OUT = 1
};
/* Bits of interest in the GPIO_INTR_STATUS register.
*/
enum {
INTR_STATUS = 0,
};
/* Bits of interest in the GPIO_CFG register.
*/
enum {
GPIO_OE = 9,
};
/* Bits of interest in the GPIO_INTR_CFG register.
* When a GPIO triggers, two separate decisions are made, controlled
* by two separate flags.
*
* - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
* register for that GPIO will be updated to reflect the triggering of that
* gpio. If this bit is 0, this register will not be updated.
* - Second, INTR_ENABLE controls whether an interrupt is triggered.
*
* If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
* can be triggered but the status register will not reflect it.
*/
enum {
INTR_ENABLE = 0,
INTR_POL_CTL = 1,
INTR_DECT_CTL = 2,
INTR_RAW_STATUS_EN = 3,
};
/* Codes of interest in GPIO_INTR_CFG_SU.
*/
enum {
TARGET_PROC_SCORPION = 4,
TARGET_PROC_NONE = 7,
};
/**
* struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
*
* @enabled_irqs: a bitmap used to optimize the summary-irq handler. By
* keeping track of which gpios are unmasked as irq sources, we avoid
* having to do readl calls on hundreds of iomapped registers each time
* the summary interrupt fires in order to locate the active interrupts.
*
* @wake_irqs: a bitmap for tracking which interrupt lines are enabled
* as wakeup sources. When the device is suspended, interrupts which are
* not wakeup sources are disabled.
*
* @dual_edge_irqs: a bitmap used to track which irqs are configured
* as dual-edge, as this is not supported by the hardware and requires
* some special handling in the driver.
*/
struct msm_gpio_dev {
struct gpio_chip gpio_chip;
DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
struct irq_domain *domain;
int summary_irq;
void __iomem *msm_tlmm_base;
};
static struct msm_gpio_dev msm_gpio;
#define GPIO_INTR_CFG_SU(gpio) (msm_gpio.msm_tlmm_base + 0x0400 + \
(0x04 * (gpio)))
#define GPIO_CONFIG(gpio) (msm_gpio.msm_tlmm_base + 0x1000 + \
(0x10 * (gpio)))
#define GPIO_IN_OUT(gpio) (msm_gpio.msm_tlmm_base + 0x1004 + \
(0x10 * (gpio)))
#define GPIO_INTR_CFG(gpio) (msm_gpio.msm_tlmm_base + 0x1008 + \
(0x10 * (gpio)))
#define GPIO_INTR_STATUS(gpio) (msm_gpio.msm_tlmm_base + 0x100c + \
(0x10 * (gpio)))
static DEFINE_SPINLOCK(tlmm_lock);
static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
{
return container_of(chip, struct msm_gpio_dev, gpio_chip);
}
static inline void set_gpio_bits(unsigned n, void __iomem *reg)
{
writel(readl(reg) | n, reg);
}
static inline void clear_gpio_bits(unsigned n, void __iomem *reg)
{
writel(readl(reg) & ~n, reg);
}
static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
{
return readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN);
}
static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
{
writel(val ? BIT(GPIO_OUT) : 0, GPIO_IN_OUT(offset));
}
static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
unsigned long irq_flags;
spin_lock_irqsave(&tlmm_lock, irq_flags);
clear_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
return 0;
}
static int msm_gpio_direction_output(struct gpio_chip *chip,
unsigned offset,
int val)
{
unsigned long irq_flags;
spin_lock_irqsave(&tlmm_lock, irq_flags);
msm_gpio_set(chip, offset, val);
set_gpio_bits(BIT(GPIO_OE), GPIO_CONFIG(offset));
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
return 0;
}
static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return 0;
}
static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
{
return;
}
static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
struct irq_domain *domain = g_dev->domain;
return irq_create_mapping(domain, offset);
}
/* For dual-edge interrupts in software, since the hardware has no
* such support:
*
* At appropriate moments, this function may be called to flip the polarity
* settings of both-edge irq lines to try and catch the next edge.
*
* The attempt is considered successful if:
* - the status bit goes high, indicating that an edge was caught, or
* - the input value of the gpio doesn't change during the attempt.
* If the value changes twice during the process, that would cause the first
* test to fail but would force the second, as two opposite
* transitions would cause a detection no matter the polarity setting.
*
* The do-loop tries to sledge-hammer closed the timing hole between
* the initial value-read and the polarity-write - if the line value changes
* during that window, an interrupt is lost, the new polarity setting is
* incorrect, and the first success test will fail, causing a retry.
*
* Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
*/
static void msm_gpio_update_dual_edge_pos(unsigned gpio)
{
int loop_limit = 100;
unsigned val, val2, intstat;
do {
val = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
if (val)
clear_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
else
set_gpio_bits(BIT(INTR_POL_CTL), GPIO_INTR_CFG(gpio));
val2 = readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN);
intstat = readl(GPIO_INTR_STATUS(gpio)) & BIT(INTR_STATUS);
if (intstat || val == val2)
return;
} while (loop_limit-- > 0);
pr_err("%s: dual-edge irq failed to stabilize, "
"interrupts dropped. %#08x != %#08x\n",
__func__, val, val2);
}
static void msm_gpio_irq_ack(struct irq_data *d)
{
int gpio = d->hwirq;
writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
if (test_bit(gpio, msm_gpio.dual_edge_irqs))
msm_gpio_update_dual_edge_pos(gpio);
}
static void msm_gpio_irq_mask(struct irq_data *d)
{
unsigned long irq_flags;
int gpio = d->hwirq;
spin_lock_irqsave(&tlmm_lock, irq_flags);
writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
__clear_bit(gpio, msm_gpio.enabled_irqs);
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
}
static void msm_gpio_irq_unmask(struct irq_data *d)
{
unsigned long irq_flags;
int gpio = d->hwirq;
spin_lock_irqsave(&tlmm_lock, irq_flags);
__set_bit(gpio, msm_gpio.enabled_irqs);
set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
}
static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
unsigned long irq_flags;
int gpio = d->hwirq;
uint32_t bits;
spin_lock_irqsave(&tlmm_lock, irq_flags);
bits = readl(GPIO_INTR_CFG(gpio));
if (flow_type & IRQ_TYPE_EDGE_BOTH) {
bits |= BIT(INTR_DECT_CTL);
irq_set_handler_locked(d, handle_edge_irq);
if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
__set_bit(gpio, msm_gpio.dual_edge_irqs);
else
__clear_bit(gpio, msm_gpio.dual_edge_irqs);
} else {
bits &= ~BIT(INTR_DECT_CTL);
irq_set_handler_locked(d, handle_level_irq);
__clear_bit(gpio, msm_gpio.dual_edge_irqs);
}
if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
bits |= BIT(INTR_POL_CTL);
else
bits &= ~BIT(INTR_POL_CTL);
writel(bits, GPIO_INTR_CFG(gpio));
if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
msm_gpio_update_dual_edge_pos(gpio);
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
return 0;
}
/*
* When the summary IRQ is raised, any number of GPIO lines may be high.
* It is the job of the summary handler to find all those GPIO lines
* which have been set as summary IRQ lines and which are triggered,
* and to call their interrupt handlers.
*/
static void msm_summary_irq_handler(struct irq_desc *desc)
{
unsigned long i;
struct irq_chip *chip = irq_desc_get_chip(desc);
chained_irq_enter(chip, desc);
for_each_set_bit(i, msm_gpio.enabled_irqs, MAX_NR_GPIO) {
if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS))
generic_handle_irq(irq_find_mapping(msm_gpio.domain,
i));
}
chained_irq_exit(chip, desc);
}
static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
{
int gpio = d->hwirq;
if (on) {
if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO))
irq_set_irq_wake(msm_gpio.summary_irq, 1);
set_bit(gpio, msm_gpio.wake_irqs);
} else {
clear_bit(gpio, msm_gpio.wake_irqs);
if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO))
irq_set_irq_wake(msm_gpio.summary_irq, 0);
}
return 0;
}
static struct irq_chip msm_gpio_irq_chip = {
.name = "msmgpio",
.irq_mask = msm_gpio_irq_mask,
.irq_unmask = msm_gpio_irq_unmask,
.irq_ack = msm_gpio_irq_ack,
.irq_set_type = msm_gpio_irq_set_type,
.irq_set_wake = msm_gpio_irq_set_wake,
};
static struct lock_class_key msm_gpio_lock_class;
static int msm_gpio_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
irq_set_lockdep_class(irq, &msm_gpio_lock_class);
irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
handle_level_irq);
return 0;
}
static const struct irq_domain_ops msm_gpio_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
.map = msm_gpio_irq_domain_map,
};
static int msm_gpio_probe(struct platform_device *pdev)
{
int ret, ngpio;
struct resource *res;
if (of_property_read_u32(pdev->dev.of_node, "ngpio", &ngpio)) {
dev_err(&pdev->dev, "%s: ngpio property missing\n", __func__);
return -EINVAL;
}
if (ngpio > MAX_NR_GPIO)
WARN(1, "ngpio exceeds the MAX_NR_GPIO. Increase MAX_NR_GPIO\n");
bitmap_zero(msm_gpio.enabled_irqs, MAX_NR_GPIO);
bitmap_zero(msm_gpio.wake_irqs, MAX_NR_GPIO);
bitmap_zero(msm_gpio.dual_edge_irqs, MAX_NR_GPIO);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
msm_gpio.msm_tlmm_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(msm_gpio.msm_tlmm_base))
return PTR_ERR(msm_gpio.msm_tlmm_base);
msm_gpio.gpio_chip.ngpio = ngpio;
msm_gpio.gpio_chip.label = pdev->name;
msm_gpio.gpio_chip.dev = &pdev->dev;
msm_gpio.gpio_chip.base = 0;
msm_gpio.gpio_chip.direction_input = msm_gpio_direction_input;
msm_gpio.gpio_chip.direction_output = msm_gpio_direction_output;
msm_gpio.gpio_chip.get = msm_gpio_get;
msm_gpio.gpio_chip.set = msm_gpio_set;
msm_gpio.gpio_chip.to_irq = msm_gpio_to_irq;
msm_gpio.gpio_chip.request = msm_gpio_request;
msm_gpio.gpio_chip.free = msm_gpio_free;
ret = gpiochip_add(&msm_gpio.gpio_chip);
if (ret < 0) {
dev_err(&pdev->dev, "gpiochip_add failed with error %d\n", ret);
return ret;
}
msm_gpio.summary_irq = platform_get_irq(pdev, 0);
if (msm_gpio.summary_irq < 0) {
dev_err(&pdev->dev, "No Summary irq defined for msmgpio\n");
return msm_gpio.summary_irq;
}
msm_gpio.domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,
&msm_gpio_irq_domain_ops,
&msm_gpio);
if (!msm_gpio.domain)
return -ENODEV;
irq_set_chained_handler(msm_gpio.summary_irq, msm_summary_irq_handler);
return 0;
}
static const struct of_device_id msm_gpio_of_match[] = {
{ .compatible = "qcom,msm-gpio", },
{ },
};
MODULE_DEVICE_TABLE(of, msm_gpio_of_match);
static int msm_gpio_remove(struct platform_device *dev)
{
gpiochip_remove(&msm_gpio.gpio_chip);
irq_set_handler(msm_gpio.summary_irq, NULL);
return 0;
}
static struct platform_driver msm_gpio_driver = {
.probe = msm_gpio_probe,
.remove = msm_gpio_remove,
.driver = {
.name = "msmgpio",
.of_match_table = msm_gpio_of_match,
},
};
module_platform_driver(msm_gpio_driver)
MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:msmgpio");

View file

@ -185,16 +185,6 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
* Functions implementing the gpio_chip methods
*/
static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
{
return pinctrl_request_gpio(chip->base + pin);
}
static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
{
pinctrl_free_gpio(chip->base + pin);
}
static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
{
struct mvebu_gpio_chip *mvchip =
@ -709,8 +699,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
mvchip->soc_variant = soc_variant;
mvchip->chip.label = dev_name(&pdev->dev);
mvchip->chip.dev = &pdev->dev;
mvchip->chip.request = mvebu_gpio_request;
mvchip->chip.free = mvebu_gpio_free;
mvchip->chip.request = gpiochip_generic_request;
mvchip->chip.free = gpiochip_generic_free;
mvchip->chip.direction_input = mvebu_gpio_direction_input;
mvchip->chip.get = mvebu_gpio_get;
mvchip->chip.direction_output = mvebu_gpio_direction_output;

View file

@ -51,7 +51,7 @@ struct gpio_regs {
struct gpio_bank {
struct list_head node;
void __iomem *base;
u16 irq;
int irq;
u32 non_wakeup_gpios;
u32 enabled_non_wakeup_gpios;
struct gpio_regs context;
@ -59,6 +59,7 @@ struct gpio_bank {
u32 level_mask;
u32 toggle_mask;
raw_spinlock_t lock;
raw_spinlock_t wa_lock;
struct gpio_chip chip;
struct clk *dbck;
u32 mod_usage;
@ -496,9 +497,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
(type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
return -EINVAL;
if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev);
raw_spin_lock_irqsave(&bank->lock, flags);
retval = omap_set_gpio_triggering(bank, offset, type);
if (retval) {
@ -521,8 +519,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
return 0;
error:
if (!BANK_USED(bank))
pm_runtime_put(bank->dev);
return retval;
}
@ -654,8 +650,13 @@ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned offset = d->hwirq;
int ret;
return omap_set_gpio_wakeup(bank, offset, enable);
ret = omap_set_gpio_wakeup(bank, offset, enable);
if (!ret)
ret = irq_set_irq_wake(bank->irq, enable);
return ret;
}
static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@ -709,26 +710,21 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
* line's interrupt handler has been run, we may miss some nested
* interrupts.
*/
static void omap_gpio_irq_handler(struct irq_desc *desc)
static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
{
void __iomem *isr_reg = NULL;
u32 isr;
unsigned int bit;
struct gpio_bank *bank;
int unmasked = 0;
struct irq_chip *irqchip = irq_desc_get_chip(desc);
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
struct gpio_bank *bank = gpiobank;
unsigned long wa_lock_flags;
unsigned long lock_flags;
chained_irq_enter(irqchip, desc);
bank = container_of(chip, struct gpio_bank, chip);
isr_reg = bank->base + bank->regs->irqstatus;
pm_runtime_get_sync(bank->dev);
if (WARN_ON(!isr_reg))
goto exit;
pm_runtime_get_sync(bank->dev);
while (1) {
u32 isr_saved, level_mask = 0;
u32 enabled;
@ -750,13 +746,6 @@ static void omap_gpio_irq_handler(struct irq_desc *desc)
raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
/* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */
if (!level_mask && !unmasked) {
unmasked = 1;
chained_irq_exit(irqchip, desc);
}
if (!isr)
break;
@ -777,18 +766,18 @@ static void omap_gpio_irq_handler(struct irq_desc *desc)
raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
bit));
raw_spin_unlock_irqrestore(&bank->wa_lock,
wa_lock_flags);
}
}
/* if bank has any level sensitive GPIO pin interrupt
configured, we must unmask the bank interrupt only after
handler(s) are executed in order to avoid spurious bank
interrupt */
exit:
if (!unmasked)
chained_irq_exit(irqchip, desc);
pm_runtime_put(bank->dev);
return IRQ_HANDLED;
}
static unsigned int omap_gpio_irq_startup(struct irq_data *d)
@ -797,9 +786,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
unsigned long flags;
unsigned offset = d->hwirq;
if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev);
raw_spin_lock_irqsave(&bank->lock, flags);
if (!LINE_USED(bank->mod_usage, offset))
@ -815,8 +801,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
return 0;
err:
raw_spin_unlock_irqrestore(&bank->lock, flags);
if (!BANK_USED(bank))
pm_runtime_put(bank->dev);
return -EINVAL;
}
@ -835,6 +819,19 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
omap_clear_gpio_debounce(bank, offset);
omap_disable_gpio_module(bank, offset);
raw_spin_unlock_irqrestore(&bank->lock, flags);
}
static void omap_gpio_irq_bus_lock(struct irq_data *data)
{
struct gpio_bank *bank = omap_irq_data_get_bank(data);
if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev);
}
static void gpio_irq_bus_sync_unlock(struct irq_data *data)
{
struct gpio_bank *bank = omap_irq_data_get_bank(data);
/*
* If this is the last IRQ to be freed in the bank,
@ -1132,7 +1129,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
}
ret = gpiochip_irqchip_add(&bank->chip, irqc,
irq_base, omap_gpio_irq_handler,
irq_base, handle_bad_irq,
IRQ_TYPE_NONE);
if (ret) {
@ -1141,10 +1138,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
return -ENODEV;
}
gpiochip_set_chained_irqchip(&bank->chip, irqc,
bank->irq, omap_gpio_irq_handler);
gpiochip_set_chained_irqchip(&bank->chip, irqc, bank->irq, NULL);
return 0;
ret = devm_request_irq(bank->dev, bank->irq, omap_gpio_irq_handler,
0, dev_name(bank->dev), bank);
if (ret)
gpiochip_remove(&bank->chip);
return ret;
}
static const struct of_device_id omap_gpio_match[];
@ -1183,6 +1184,8 @@ static int omap_gpio_probe(struct platform_device *pdev)
irqc->irq_unmask = omap_gpio_unmask_irq,
irqc->irq_set_type = omap_gpio_irq_type,
irqc->irq_set_wake = omap_gpio_wake_enable,
irqc->irq_bus_lock = omap_gpio_irq_bus_lock,
irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock,
irqc->name = dev_name(&pdev->dev);
bank->irq = platform_get_irq(pdev, 0);
@ -1224,6 +1227,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
bank->set_dataout = omap_set_gpio_dataout_mask;
raw_spin_lock_init(&bank->lock);
raw_spin_lock_init(&bank->wa_lock);
/* Static mapping, never released */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

View file

@ -21,6 +21,7 @@
#ifdef CONFIG_OF_GPIO
#include <linux/of_platform.h>
#endif
#include <linux/acpi.h>
#define PCA953X_INPUT 0
#define PCA953X_OUTPUT 1
@ -42,6 +43,9 @@
#define PCA_INT 0x0100
#define PCA953X_TYPE 0x1000
#define PCA957X_TYPE 0x2000
#define PCA_TYPE_MASK 0xF000
#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK)
static const struct i2c_device_id pca953x_id[] = {
{ "pca9505", 40 | PCA953X_TYPE | PCA_INT, },
@ -67,11 +71,18 @@ static const struct i2c_device_id pca953x_id[] = {
{ "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
{ "tca9539", 16 | PCA953X_TYPE | PCA_INT, },
{ "xra1202", 8 | PCA953X_TYPE },
{ }
};
MODULE_DEVICE_TABLE(i2c, pca953x_id);
static const struct acpi_device_id pca953x_acpi_ids[] = {
{ "INT3491", 16 | PCA953X_TYPE | PCA_INT, },
{ }
};
MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
#define MAX_BANK 5
#define BANK_SZ 8
@ -95,6 +106,7 @@ struct pca953x_chip {
struct gpio_chip gpio_chip;
const char *const *names;
int chip_type;
unsigned long driver_data;
};
static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
@ -517,14 +529,13 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
}
static int pca953x_irq_setup(struct pca953x_chip *chip,
const struct i2c_device_id *id,
int irq_base)
{
struct i2c_client *client = chip->client;
int ret, i, offset = 0;
if (client->irq && irq_base != -1
&& (id->driver_data & PCA_INT)) {
&& (chip->driver_data & PCA_INT)) {
switch (chip->chip_type) {
case PCA953X_TYPE:
@ -581,12 +592,11 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
#else /* CONFIG_GPIO_PCA953X_IRQ */
static int pca953x_irq_setup(struct pca953x_chip *chip,
const struct i2c_device_id *id,
int irq_base)
{
struct i2c_client *client = chip->client;
if (irq_base != -1 && (id->driver_data & PCA_INT))
if (irq_base != -1 && (chip->driver_data & PCA_INT))
dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0;
@ -635,11 +645,15 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
memset(val, 0xFF, NBANK(chip));
else
memset(val, 0, NBANK(chip));
pca953x_write_regs(chip, PCA957X_INVRT, val);
ret = pca953x_write_regs(chip, PCA957X_INVRT, val);
if (ret)
goto out;
/* To enable register 6, 7 to control pull up and pull down */
memset(val, 0x02, NBANK(chip));
pca953x_write_regs(chip, PCA957X_BKEN, val);
ret = pca953x_write_regs(chip, PCA957X_BKEN, val);
if (ret)
goto out;
return 0;
out:
@ -673,14 +687,26 @@ static int pca953x_probe(struct i2c_client *client,
chip->client = client;
chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
if (id) {
chip->driver_data = id->driver_data;
} else {
const struct acpi_device_id *id;
id = acpi_match_device(pca953x_acpi_ids, &client->dev);
if (!id)
return -ENODEV;
chip->driver_data = id->driver_data;
}
chip->chip_type = PCA_CHIP_TYPE(chip->driver_data);
mutex_init(&chip->i2c_lock);
/* initialize cached registers from their original values.
* we can't share this chip with another i2c master.
*/
pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
if (chip->chip_type == PCA953X_TYPE)
ret = device_pca953x_init(chip, invert);
@ -693,7 +719,7 @@ static int pca953x_probe(struct i2c_client *client,
if (ret)
return ret;
ret = pca953x_irq_setup(chip, id, irq_base);
ret = pca953x_irq_setup(chip, irq_base);
if (ret)
return ret;
@ -765,6 +791,7 @@ static struct i2c_driver pca953x_driver = {
.driver = {
.name = "pca953x",
.of_match_table = pca953x_dt_ids,
.acpi_match_table = ACPI_PTR(pca953x_acpi_ids),
},
.probe = pca953x_probe,
.remove = pca953x_remove,

View file

@ -52,36 +52,12 @@ struct pl061_gpio {
void __iomem *base;
struct gpio_chip gc;
bool uses_pinctrl;
#ifdef CONFIG_PM
struct pl061_context_save_regs csave_regs;
#endif
};
static int pl061_gpio_request(struct gpio_chip *gc, unsigned offset)
{
/*
* Map back to global GPIO space and request muxing, the direction
* parameter does not matter for this controller.
*/
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
int gpio = gc->base + offset;
if (chip->uses_pinctrl)
return pinctrl_request_gpio(gpio);
return 0;
}
static void pl061_gpio_free(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
int gpio = gc->base + offset;
if (chip->uses_pinctrl)
pinctrl_free_gpio(gpio);
}
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
@ -152,6 +128,17 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
if (offset < 0 || offset >= PL061_GPIO_NR)
return -EINVAL;
if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
(trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))
{
dev_err(gc->dev,
"trying to configure line %d for both level and edge "
"detection, choose one!\n",
offset);
return -EINVAL;
}
spin_lock_irqsave(&chip->lock, flags);
gpioiev = readb(chip->base + GPIOIEV);
@ -159,23 +146,53 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
gpioibe = readb(chip->base + GPIOIBE);
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
/* Disable edge detection */
gpioibe &= ~bit;
/* Enable level detection */
gpiois |= bit;
if (trigger & IRQ_TYPE_LEVEL_HIGH)
/* Select polarity */
if (polarity)
gpioiev |= bit;
else
gpioiev &= ~bit;
} else
irq_set_handler_locked(d, handle_level_irq);
dev_dbg(gc->dev, "line %d: IRQ on %s level\n",
offset,
polarity ? "HIGH" : "LOW");
} else if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
/* Disable level detection */
gpiois &= ~bit;
if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
/* Setting this makes GPIOEV be ignored */
/* Select both edges, setting this makes GPIOEV be ignored */
gpioibe |= bit;
else {
irq_set_handler_locked(d, handle_edge_irq);
dev_dbg(gc->dev, "line %d: IRQ on both edges\n", offset);
} else if ((trigger & IRQ_TYPE_EDGE_RISING) ||
(trigger & IRQ_TYPE_EDGE_FALLING)) {
bool rising = trigger & IRQ_TYPE_EDGE_RISING;
/* Disable level detection */
gpiois &= ~bit;
/* Clear detection on both edges */
gpioibe &= ~bit;
if (trigger & IRQ_TYPE_EDGE_RISING)
/* Select edge */
if (rising)
gpioiev |= bit;
else if (trigger & IRQ_TYPE_EDGE_FALLING)
else
gpioiev &= ~bit;
irq_set_handler_locked(d, handle_edge_irq);
dev_dbg(gc->dev, "line %d: IRQ on %s edge\n",
offset,
rising ? "RISING" : "FALLING");
} else {
/* No trigger: disable everything */
gpiois &= ~bit;
gpioibe &= ~bit;
gpioiev &= ~bit;
irq_set_handler_locked(d, handle_bad_irq);
dev_warn(gc->dev, "no trigger selected for line %d\n",
offset);
}
writeb(gpiois, chip->base + GPIOIS);
@ -198,7 +215,6 @@ static void pl061_irq_handler(struct irq_desc *desc)
chained_irq_enter(irqchip, desc);
pending = readb(chip->base + GPIOMIS);
writeb(pending, chip->base + GPIOIC);
if (pending) {
for_each_set_bit(offset, &pending, PL061_GPIO_NR)
generic_handle_irq(irq_find_mapping(gc->irqdomain,
@ -234,8 +250,28 @@ static void pl061_irq_unmask(struct irq_data *d)
spin_unlock(&chip->lock);
}
/**
* pl061_irq_ack() - ACK an edge IRQ
* @d: IRQ data for this IRQ
*
* This gets called from the edge IRQ handler to ACK the edge IRQ
* in the GPIOIC (interrupt-clear) register. For level IRQs this is
* not needed: these go away when the level signal goes away.
*/
static void pl061_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
spin_lock(&chip->lock);
writeb(mask, chip->base + GPIOIC);
spin_unlock(&chip->lock);
}
static struct irq_chip pl061_irqchip = {
.name = "pl061",
.irq_ack = pl061_irq_ack,
.irq_mask = pl061_irq_mask,
.irq_unmask = pl061_irq_unmask,
.irq_set_type = pl061_irq_type,
@ -269,11 +305,11 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(chip->base);
spin_lock_init(&chip->lock);
if (of_property_read_bool(dev->of_node, "gpio-ranges"))
chip->uses_pinctrl = true;
if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
chip->gc.request = gpiochip_generic_request;
chip->gc.free = gpiochip_generic_free;
}
chip->gc.request = pl061_gpio_request;
chip->gc.free = pl061_gpio_free;
chip->gc.direction_input = pl061_direction_input;
chip->gc.direction_output = pl061_direction_output;
chip->gc.get = pl061_get_value;
@ -298,7 +334,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
}
ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip,
irq_base, handle_simple_irq,
irq_base, handle_bad_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_info(&adev->dev, "could not add irqchip\n");

View file

@ -160,6 +160,11 @@ static const struct of_device_id sx150x_of_match[] = {
};
MODULE_DEVICE_TABLE(of, sx150x_of_match);
struct sx150x_chip *to_sx150x(struct gpio_chip *gc)
{
return container_of(gc, struct sx150x_chip, gpio_chip);
}
static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
{
s32 err = i2c_smbus_write_byte_data(client, reg, val);
@ -296,11 +301,9 @@ static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
{
struct sx150x_chip *chip;
struct sx150x_chip *chip = to_sx150x(gc);
int status = -EINVAL;
chip = container_of(gc, struct sx150x_chip, gpio_chip);
if (!offset_is_oscio(chip, offset)) {
mutex_lock(&chip->lock);
status = sx150x_get_io(chip, offset);
@ -312,9 +315,7 @@ static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
{
struct sx150x_chip *chip;
chip = container_of(gc, struct sx150x_chip, gpio_chip);
struct sx150x_chip *chip = to_sx150x(gc);
mutex_lock(&chip->lock);
if (offset_is_oscio(chip, offset))
@ -326,11 +327,9 @@ static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct sx150x_chip *chip;
struct sx150x_chip *chip = to_sx150x(gc);
int status = -EINVAL;
chip = container_of(gc, struct sx150x_chip, gpio_chip);
if (!offset_is_oscio(chip, offset)) {
mutex_lock(&chip->lock);
status = sx150x_io_input(chip, offset);
@ -343,11 +342,9 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc,
unsigned offset,
int val)
{
struct sx150x_chip *chip;
struct sx150x_chip *chip = to_sx150x(gc);
int status = 0;
chip = container_of(gc, struct sx150x_chip, gpio_chip);
if (!offset_is_oscio(chip, offset)) {
mutex_lock(&chip->lock);
status = sx150x_io_output(chip, offset, val);
@ -358,7 +355,7 @@ static int sx150x_gpio_direction_output(struct gpio_chip *gc,
static void sx150x_irq_mask(struct irq_data *d)
{
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n = d->hwirq;
chip->irq_masked |= (1 << n);
@ -367,7 +364,7 @@ static void sx150x_irq_mask(struct irq_data *d)
static void sx150x_irq_unmask(struct irq_data *d)
{
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n = d->hwirq;
chip->irq_masked &= ~(1 << n);
@ -376,7 +373,7 @@ static void sx150x_irq_unmask(struct irq_data *d)
static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
{
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n, val = 0;
if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
@ -431,14 +428,14 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
static void sx150x_irq_bus_lock(struct irq_data *d)
{
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
mutex_lock(&chip->lock);
}
static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
{
struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
struct sx150x_chip *chip = to_sx150x(irq_data_get_irq_chip_data(d));
unsigned n;
if (chip->irq_update == NO_UPDATE_PENDING)

View file

@ -138,16 +138,6 @@ static int tb10x_gpio_direction_out(struct gpio_chip *chip,
return 0;
}
static int tb10x_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void tb10x_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip);
@ -213,8 +203,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
tb10x_gpio->gc.get = tb10x_gpio_get;
tb10x_gpio->gc.direction_output = tb10x_gpio_direction_out;
tb10x_gpio->gc.set = tb10x_gpio_set;
tb10x_gpio->gc.request = tb10x_gpio_request;
tb10x_gpio->gc.free = tb10x_gpio_free;
tb10x_gpio->gc.request = gpiochip_generic_request;
tb10x_gpio->gc.free = gpiochip_generic_free;
tb10x_gpio->gc.base = -1;
tb10x_gpio->gc.ngpio = ngpio;
tb10x_gpio->gc.can_sleep = false;

View file

@ -137,16 +137,6 @@ static void tz1090_pdc_gpio_set(struct gpio_chip *chip, unsigned int offset,
__global_unlock2(lstat);
}
static int tz1090_pdc_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void tz1090_pdc_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int tz1090_pdc_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct tz1090_pdc_gpio *priv = to_pdc(chip);
@ -203,8 +193,8 @@ static int tz1090_pdc_gpio_probe(struct platform_device *pdev)
priv->chip.direction_output = tz1090_pdc_gpio_direction_output;
priv->chip.get = tz1090_pdc_gpio_get;
priv->chip.set = tz1090_pdc_gpio_set;
priv->chip.free = tz1090_pdc_gpio_free;
priv->chip.request = tz1090_pdc_gpio_request;
priv->chip.free = gpiochip_generic_free;
priv->chip.request = gpiochip_generic_request;
priv->chip.to_irq = tz1090_pdc_gpio_to_irq;
priv->chip.of_node = np;

View file

@ -62,6 +62,11 @@ struct vf610_gpio_port {
static struct irq_chip vf610_gpio_irq_chip;
static struct vf610_gpio_port *to_vf610_gp(struct gpio_chip *gc)
{
return container_of(gc, struct vf610_gpio_port, gc);
}
static const struct of_device_id vf610_gpio_dt_ids[] = {
{ .compatible = "fsl,vf610-gpio" },
{ /* sentinel */ }
@ -77,28 +82,16 @@ static inline u32 vf610_gpio_readl(void __iomem *reg)
return readl_relaxed(reg);
}
static int vf610_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void vf610_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct vf610_gpio_port *port =
container_of(gc, struct vf610_gpio_port, gc);
struct vf610_gpio_port *port = to_vf610_gp(gc);
return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio));
}
static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct vf610_gpio_port *port =
container_of(gc, struct vf610_gpio_port, gc);
struct vf610_gpio_port *port = to_vf610_gp(gc);
unsigned long mask = BIT(gpio);
if (val)
@ -122,7 +115,8 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
static void vf610_gpio_irq_handler(struct irq_desc *desc)
{
struct vf610_gpio_port *port = irq_desc_get_handler_data(desc);
struct vf610_gpio_port *port =
to_vf610_gp(irq_desc_get_handler_data(desc));
struct irq_chip *chip = irq_desc_get_chip(desc);
int pin;
unsigned long irq_isfr;
@ -142,7 +136,8 @@ static void vf610_gpio_irq_handler(struct irq_desc *desc)
static void vf610_gpio_irq_ack(struct irq_data *d)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
struct vf610_gpio_port *port =
to_vf610_gp(irq_data_get_irq_chip_data(d));
int gpio = d->hwirq;
vf610_gpio_writel(BIT(gpio), port->base + PORT_ISFR);
@ -150,7 +145,8 @@ static void vf610_gpio_irq_ack(struct irq_data *d)
static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
struct vf610_gpio_port *port =
to_vf610_gp(irq_data_get_irq_chip_data(d));
u8 irqc;
switch (type) {
@ -185,7 +181,8 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
static void vf610_gpio_irq_mask(struct irq_data *d)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
struct vf610_gpio_port *port =
to_vf610_gp(irq_data_get_irq_chip_data(d));
void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
vf610_gpio_writel(0, pcr_base);
@ -193,7 +190,8 @@ static void vf610_gpio_irq_mask(struct irq_data *d)
static void vf610_gpio_irq_unmask(struct irq_data *d)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
struct vf610_gpio_port *port =
to_vf610_gp(irq_data_get_irq_chip_data(d));
void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
vf610_gpio_writel(port->irqc[d->hwirq] << PORT_PCR_IRQC_OFFSET,
@ -202,7 +200,8 @@ static void vf610_gpio_irq_unmask(struct irq_data *d)
static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
struct vf610_gpio_port *port =
to_vf610_gp(irq_data_get_irq_chip_data(d));
if (enable)
enable_irq_wake(port->irq);
@ -255,8 +254,8 @@ static int vf610_gpio_probe(struct platform_device *pdev)
gc->ngpio = VF610_GPIO_PER_PORT;
gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT;
gc->request = vf610_gpio_request;
gc->free = vf610_gpio_free;
gc->request = gpiochip_generic_request;
gc->free = gpiochip_generic_free;
gc->direction_input = vf610_gpio_direction_input;
gc->get = vf610_gpio_get;
gc->direction_output = vf610_gpio_direction_output;

View file

@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
/*
* XLP GPIO has multiple 32 bit registers for each feature where each register
@ -208,25 +209,28 @@ static struct irq_chip xlp_gpio_irq_chip = {
.flags = IRQCHIP_ONESHOT_SAFE,
};
static irqreturn_t xlp_gpio_generic_handler(int irq, void *data)
static void xlp_gpio_generic_handler(struct irq_desc *desc)
{
struct xlp_gpio_priv *priv = data;
struct xlp_gpio_priv *priv = irq_desc_get_handler_data(desc);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
int gpio, regoff;
u32 gpio_stat;
regoff = -1;
gpio_stat = 0;
chained_irq_enter(irqchip, desc);
for_each_set_bit(gpio, priv->gpio_enabled_mask, XLP_MAX_NR_GPIO) {
if (regoff != gpio / XLP_GPIO_REGSZ) {
regoff = gpio / XLP_GPIO_REGSZ;
gpio_stat = readl(priv->gpio_intr_stat + regoff * 4);
}
if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ))
generic_handle_irq(irq_find_mapping(
priv->chip.irqdomain, gpio));
}
return IRQ_HANDLED;
chained_irq_exit(irqchip, desc);
}
static int xlp_gpio_dir_output(struct gpio_chip *gc, unsigned gpio, int state)
@ -378,12 +382,6 @@ static int xlp_gpio_probe(struct platform_device *pdev)
gc->get = xlp_gpio_get;
spin_lock_init(&priv->lock);
err = devm_request_irq(&pdev->dev, irq, xlp_gpio_generic_handler,
IRQ_TYPE_NONE, pdev->name, priv);
if (err)
return err;
irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
@ -401,6 +399,9 @@ static int xlp_gpio_probe(struct platform_device *pdev)
goto out_gpio_remove;
}
gpiochip_set_chained_irqchip(gc, &xlp_gpio_irq_chip, irq,
xlp_gpio_generic_handler);
dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio);
return 0;

View file

@ -41,7 +41,6 @@ struct zx_gpio {
void __iomem *base;
struct gpio_chip gc;
bool uses_pinctrl;
};
static inline struct zx_gpio *to_zx(struct gpio_chip *gc)
@ -49,25 +48,6 @@ static inline struct zx_gpio *to_zx(struct gpio_chip *gc)
return container_of(gc, struct zx_gpio, gc);
}
static int zx_gpio_request(struct gpio_chip *gc, unsigned offset)
{
struct zx_gpio *chip = to_zx(gc);
int gpio = gc->base + offset;
if (chip->uses_pinctrl)
return pinctrl_request_gpio(gpio);
return 0;
}
static void zx_gpio_free(struct gpio_chip *gc, unsigned offset)
{
struct zx_gpio *chip = to_zx(gc);
int gpio = gc->base + offset;
if (chip->uses_pinctrl)
pinctrl_free_gpio(gpio);
}
static int zx_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct zx_gpio *chip = to_zx(gc);
@ -252,12 +232,12 @@ static int zx_gpio_probe(struct platform_device *pdev)
return PTR_ERR(chip->base);
spin_lock_init(&chip->lock);
if (of_property_read_bool(dev->of_node, "gpio-ranges"))
chip->uses_pinctrl = true;
if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
chip->gc.request = gpiochip_generic_request;
chip->gc.free = gpiochip_generic_free;
}
id = of_alias_get_id(dev->of_node, "gpio");
chip->gc.request = zx_gpio_request;
chip->gc.free = zx_gpio_free;
chip->gc.direction_input = zx_direction_input;
chip->gc.direction_output = zx_direction_output;
chip->gc.get = zx_get_value;

View file

@ -130,6 +130,12 @@ struct zynq_platform_data {
static struct irq_chip zynq_gpio_level_irqchip;
static struct irq_chip zynq_gpio_edge_irqchip;
static struct zynq_gpio *to_zynq_gpio(struct gpio_chip *gc)
{
return container_of(gc, struct zynq_gpio, chip);
}
/**
* zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
* for a given pin in the GPIO device
@ -177,7 +183,7 @@ static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
{
u32 data;
unsigned int bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@ -201,7 +207,7 @@ static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
int state)
{
unsigned int reg_offset, bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@ -238,7 +244,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
{
u32 reg;
unsigned int bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@ -271,7 +277,7 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
{
u32 reg;
unsigned int bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
struct zynq_gpio *gpio = to_zynq_gpio(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@ -301,7 +307,8 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
static void zynq_gpio_irq_mask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
struct zynq_gpio *gpio =
to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@ -321,7 +328,8 @@ static void zynq_gpio_irq_mask(struct irq_data *irq_data)
static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
struct zynq_gpio *gpio =
to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@ -340,7 +348,8 @@ static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
static void zynq_gpio_irq_ack(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
struct zynq_gpio *gpio =
to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@ -390,7 +399,8 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
{
u32 int_type, int_pol, int_any;
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
struct zynq_gpio *gpio =
to_zynq_gpio(irq_data_get_irq_chip_data(irq_data));
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num, gpio);
@ -453,7 +463,8 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
{
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(data);
struct zynq_gpio *gpio =
to_zynq_gpio(irq_data_get_irq_chip_data(data));
irq_set_irq_wake(gpio->irq, on);
@ -518,7 +529,8 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc)
{
u32 int_sts, int_enb;
unsigned int bank_num;
struct zynq_gpio *gpio = irq_desc_get_handler_data(desc);
struct zynq_gpio *gpio =
to_zynq_gpio(irq_desc_get_handler_data(desc));
struct irq_chip *irqchip = irq_desc_get_chip(desc);
chained_irq_enter(irqchip, desc);

View file

@ -304,7 +304,6 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
if (ACPI_FAILURE(status))
return;
INIT_LIST_HEAD(&acpi_gpio->events);
acpi_walk_resources(handle, "_AEI",
acpi_gpiochip_request_interrupt, acpi_gpio);
}
@ -603,6 +602,25 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
break;
}
}
/*
* The same GPIO can be shared between operation region and
* event but only if the access here is ACPI_READ. In that
* case we "borrow" the event GPIO instead.
*/
if (!found && agpio->sharable == ACPI_SHARED &&
function == ACPI_READ) {
struct acpi_gpio_event *event;
list_for_each_entry(event, &achip->events, node) {
if (event->pin == pin) {
desc = event->desc;
found = true;
break;
}
}
}
if (!found) {
desc = gpiochip_request_own_desc(chip, pin,
"ACPI:OpRegion");
@ -719,6 +737,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
}
acpi_gpio->chip = chip;
INIT_LIST_HEAD(&acpi_gpio->events);
status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio);
if (ACPI_FAILURE(status)) {

View file

@ -28,10 +28,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (!desc && gpio_is_valid(gpio))
return -EPROBE_DEFER;
err = gpiod_request(desc, label);
if (err)
return err;
if (flags & GPIOF_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
@ -41,6 +37,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (flags & GPIOF_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
err = gpiod_request(desc, label);
if (err)
return err;
if (flags & GPIOF_DIR_IN)
err = gpiod_direction_input(desc);
else

View file

@ -119,20 +119,20 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
EXPORT_SYMBOL(of_get_named_gpio_flags);
/**
* of_get_gpio_hog() - Get a GPIO hog descriptor, names and flags for GPIO API
* of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API
* @np: device node to get GPIO from
* @name: GPIO line name
* @lflags: gpio_lookup_flags - returned from of_find_gpio() or
* of_get_gpio_hog()
* of_parse_own_gpio()
* @dflags: gpiod_flags - optional GPIO initialization flags
*
* Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
* value on the error condition.
*/
static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
const char **name,
enum gpio_lookup_flags *lflags,
enum gpiod_flags *dflags)
static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
const char **name,
enum gpio_lookup_flags *lflags,
enum gpiod_flags *dflags)
{
struct device_node *chip_np;
enum of_gpio_flags xlate_flags;
@ -196,13 +196,13 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
}
/**
* of_gpiochip_scan_hogs - Scan gpio-controller and apply GPIO hog as requested
* of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
* @chip: gpio chip to act on
*
* This is only used by of_gpiochip_add to request/set GPIO initial
* configuration.
*/
static void of_gpiochip_scan_hogs(struct gpio_chip *chip)
static void of_gpiochip_scan_gpios(struct gpio_chip *chip)
{
struct gpio_desc *desc = NULL;
struct device_node *np;
@ -214,7 +214,7 @@ static void of_gpiochip_scan_hogs(struct gpio_chip *chip)
if (!of_property_read_bool(np, "gpio-hog"))
continue;
desc = of_get_gpio_hog(np, &name, &lflags, &dflags);
desc = of_parse_own_gpio(np, &name, &lflags, &dflags);
if (IS_ERR(desc))
continue;
@ -440,7 +440,7 @@ int of_gpiochip_add(struct gpio_chip *chip)
of_node_get(chip->of_node);
of_gpiochip_scan_hogs(chip);
of_gpiochip_scan_gpios(chip);
return 0;
}

View file

@ -15,6 +15,7 @@
#include <linux/acpi.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/pinctrl/consumer.h>
#include "gpiolib.h"
@ -47,8 +48,6 @@
*/
DEFINE_SPINLOCK(gpio_lock);
#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
static DEFINE_MUTEX(gpio_lookup_lock);
static LIST_HEAD(gpio_lookup_list);
LIST_HEAD(gpio_chips);
@ -218,6 +217,68 @@ static int gpiochip_add_to_list(struct gpio_chip *chip)
return err;
}
/**
* Convert a GPIO name to its descriptor
*/
static struct gpio_desc *gpio_name_to_desc(const char * const name)
{
struct gpio_chip *chip;
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(chip, &gpio_chips, list) {
int i;
for (i = 0; i != chip->ngpio; ++i) {
struct gpio_desc *gpio = &chip->desc[i];
if (!gpio->name)
continue;
if (!strcmp(gpio->name, name)) {
spin_unlock_irqrestore(&gpio_lock, flags);
return gpio;
}
}
}
spin_unlock_irqrestore(&gpio_lock, flags);
return NULL;
}
/*
* Takes the names from gc->names and checks if they are all unique. If they
* are, they are assigned to their gpio descriptors.
*
* Returns -EEXIST if one of the names is already used for a different GPIO.
*/
static int gpiochip_set_desc_names(struct gpio_chip *gc)
{
int i;
if (!gc->names)
return 0;
/* First check all names if they are unique */
for (i = 0; i != gc->ngpio; ++i) {
struct gpio_desc *gpio;
gpio = gpio_name_to_desc(gc->names[i]);
if (gpio)
dev_warn(gc->dev, "Detected name collision for "
"GPIO name '%s'\n",
gc->names[i]);
}
/* Then add all names to the GPIO descriptors */
for (i = 0; i != gc->ngpio; ++i)
gc->desc[i].name = gc->names[i];
return 0;
}
/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
@ -290,6 +351,10 @@ int gpiochip_add(struct gpio_chip *chip)
if (!chip->owner && chip->dev && chip->dev->driver)
chip->owner = chip->dev->driver->owner;
status = gpiochip_set_desc_names(chip);
if (status)
goto err_remove_from_list;
status = of_gpiochip_add(chip);
if (status)
goto err_remove_chip;
@ -310,6 +375,7 @@ int gpiochip_add(struct gpio_chip *chip)
acpi_gpiochip_remove(chip);
gpiochip_free_hogs(chip);
of_gpiochip_remove(chip);
err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags);
list_del(&chip->list);
spin_unlock_irqrestore(&gpio_lock, flags);
@ -680,6 +746,28 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
#endif /* CONFIG_GPIOLIB_IRQCHIP */
/**
* gpiochip_generic_request() - request the gpio function for a pin
* @chip: the gpiochip owning the GPIO
* @offset: the offset of the GPIO to request for GPIO function
*/
int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_request);
/**
* gpiochip_generic_free() - free the gpio function from a pin
* @chip: the gpiochip to request the gpio function for
* @offset: the offset of the GPIO to free from GPIO function
*/
void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
EXPORT_SYMBOL_GPL(gpiochip_generic_free);
#ifdef CONFIG_PINCTRL
/**
@ -839,6 +927,14 @@ static int __gpiod_request(struct gpio_desc *desc, const char *label)
spin_lock_irqsave(&gpio_lock, flags);
}
done:
if (status < 0) {
/* Clear flags that might have been set by the caller before
* requesting the GPIO.
*/
clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
}
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
}
@ -928,7 +1024,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
{
struct gpio_desc *desc;
if (!GPIO_OFFSET_VALID(chip, offset))
if (offset >= chip->ngpio)
return NULL;
desc = &chip->desc[offset];
@ -1735,6 +1831,13 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
if (of_flags & OF_GPIO_ACTIVE_LOW)
*flags |= GPIO_ACTIVE_LOW;
if (of_flags & OF_GPIO_SINGLE_ENDED) {
if (of_flags & OF_GPIO_ACTIVE_LOW)
*flags |= GPIO_OPEN_DRAIN;
else
*flags |= GPIO_OPEN_SOURCE;
}
return desc;
}
@ -1953,13 +2056,28 @@ struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
}
EXPORT_SYMBOL_GPL(gpiod_get_optional);
/**
* gpiod_parse_flags - helper function to parse GPIO lookup flags
* @desc: gpio to be setup
* @lflags: gpio_lookup_flags - returned from of_find_gpio() or
* of_get_gpio_hog()
*
* Set the GPIO descriptor flags based on the given GPIO lookup flags.
*/
static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
{
if (lflags & GPIO_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (lflags & GPIO_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
if (lflags & GPIO_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
}
/**
* gpiod_configure_flags - helper function to configure a given GPIO
* @desc: gpio whose value will be assigned
* @con_id: function within the GPIO consumer
* @lflags: gpio_lookup_flags - returned from of_find_gpio() or
* of_get_gpio_hog()
* @dflags: gpiod_flags - optional GPIO initialization flags
*
* Return 0 on success, -ENOENT if no GPIO has been assigned to the
@ -1967,17 +2085,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
* occurred while trying to acquire the GPIO.
*/
static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags)
enum gpiod_flags dflags)
{
int status;
if (lflags & GPIO_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (lflags & GPIO_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
if (lflags & GPIO_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
/* No particular flag request, return here... */
if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
pr_debug("no flags found for %s\n", con_id);
@ -2044,11 +2155,13 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
return desc;
}
gpiod_parse_flags(desc, lookupflags);
status = gpiod_request(desc, con_id);
if (status < 0)
return ERR_PTR(status);
status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
status = gpiod_configure_flags(desc, con_id, flags);
if (status < 0) {
dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
gpiod_put(desc);
@ -2078,6 +2191,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
{
struct gpio_desc *desc = ERR_PTR(-ENODEV);
bool active_low = false;
bool single_ended = false;
int ret;
if (!fwnode)
@ -2088,8 +2202,10 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
desc = of_get_named_gpiod_flags(to_of_node(fwnode), propname, 0,
&flags);
if (!IS_ERR(desc))
if (!IS_ERR(desc)) {
active_low = flags & OF_GPIO_ACTIVE_LOW;
single_ended = flags & OF_GPIO_SINGLE_ENDED;
}
} else if (is_acpi_node(fwnode)) {
struct acpi_gpio_info info;
@ -2102,14 +2218,20 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
if (IS_ERR(desc))
return desc;
if (active_low)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (single_ended) {
if (active_low)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
else
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
}
ret = gpiod_request(desc, NULL);
if (ret)
return ERR_PTR(ret);
/* Only value flag can be set from both DT and ACPI is active_low */
if (active_low)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
return desc;
}
EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
@ -2162,6 +2284,8 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
chip = gpiod_to_chip(desc);
hwnum = gpio_chip_hwgpio(desc);
gpiod_parse_flags(desc, lflags);
local_desc = gpiochip_request_own_desc(chip, hwnum, name);
if (IS_ERR(local_desc)) {
pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n",
@ -2169,7 +2293,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
return PTR_ERR(local_desc);
}
status = gpiod_configure_flags(desc, name, lflags, dflags);
status = gpiod_configure_flags(desc, name, dflags);
if (status < 0) {
pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n",
name, chip->label, hwnum);
@ -2309,14 +2433,19 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
int is_irq;
for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) {
if (gdesc->name) {
seq_printf(s, " gpio-%-3d (%-20.20s)\n",
gpio, gdesc->name);
}
continue;
}
gpiod_get_direction(gdesc);
is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
is_irq = test_bit(FLAG_USED_AS_IRQ, &gdesc->flags);
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s",
gpio, gdesc->label,
seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s",
gpio, gdesc->name ? gdesc->name : "", gdesc->label,
is_out ? "out" : "in ",
chip->get
? (chip->get(chip, i) ? "hi" : "lo")

View file

@ -89,7 +89,10 @@ struct gpio_desc {
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
/* Connection label */
const char *label;
/* Name of the GPIO */
const char *name;
};
int gpiod_request(struct gpio_desc *desc, const char *label);

View file

@ -330,16 +330,6 @@ static inline void bcm2835_pinctrl_fsel_set(
bcm2835_gpio_wr(pc, FSEL_REG(pin), val);
}
static int bcm2835_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void bcm2835_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_gpio_direction_input(chip->base + offset);
@ -375,8 +365,8 @@ static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
static struct gpio_chip bcm2835_gpio_chip = {
.label = MODULE_NAME,
.owner = THIS_MODULE,
.request = bcm2835_gpio_request,
.free = bcm2835_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.direction_input = bcm2835_gpio_direction_input,
.direction_output = bcm2835_gpio_direction_output,
.get = bcm2835_gpio_get,

View file

@ -1149,16 +1149,6 @@ static struct pinctrl_desc chv_pinctrl_desc = {
.owner = THIS_MODULE,
};
static int chv_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void chv_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static unsigned chv_gpio_offset_to_pin(struct chv_pinctrl *pctrl,
unsigned offset)
{
@ -1238,8 +1228,8 @@ static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static const struct gpio_chip chv_gpio_chip = {
.owner = THIS_MODULE,
.request = chv_gpio_request,
.free = chv_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get_direction = chv_gpio_get_direction,
.direction_input = chv_gpio_direction_input,
.direction_output = chv_gpio_direction_output,

View file

@ -596,16 +596,6 @@ static const struct pinctrl_desc intel_pinctrl_desc = {
.owner = THIS_MODULE,
};
static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void intel_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(chip);
@ -653,8 +643,8 @@ static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static const struct gpio_chip intel_gpio_chip = {
.owner = THIS_MODULE,
.request = intel_gpio_request,
.free = intel_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.direction_input = intel_gpio_direction_input,
.direction_output = intel_gpio_direction_output,
.get = intel_gpio_get,

View file

@ -723,16 +723,6 @@ static const struct pinmux_ops mtk_pmx_ops = {
.gpio_set_direction = mtk_pmx_gpio_set_direction,
};
static int mtk_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void mtk_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int mtk_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
@ -1005,8 +995,8 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
static struct gpio_chip mtk_gpio_chip = {
.owner = THIS_MODULE,
.request = mtk_gpio_request,
.free = mtk_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.direction_input = mtk_gpio_direction_input,
.direction_output = mtk_gpio_direction_output,
.get = mtk_gpio_get,

View file

@ -654,25 +654,11 @@ static inline void abx500_gpio_dbg_show_one(struct seq_file *s,
#define abx500_gpio_dbg_show NULL
#endif
static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
return pinctrl_request_gpio(gpio);
}
static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
pinctrl_free_gpio(gpio);
}
static struct gpio_chip abx500gpio_chip = {
.label = "abx500-gpio",
.owner = THIS_MODULE,
.request = abx500_gpio_request,
.free = abx500_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.direction_input = abx500_gpio_direction_input,
.get = abx500_gpio_get,
.direction_output = abx500_gpio_direction_output,

View file

@ -884,24 +884,6 @@ static void nmk_gpio_latent_irq_handler(struct irq_desc *desc)
/* I/O Functions */
static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset)
{
/*
* Map back to global GPIO space and request muxing, the direction
* parameter does not matter for this controller.
*/
int gpio = chip->base + offset;
return pinctrl_request_gpio(gpio);
}
static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
pinctrl_free_gpio(gpio);
}
static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
{
struct nmk_gpio_chip *nmk_chip =
@ -1267,8 +1249,8 @@ static int nmk_gpio_probe(struct platform_device *dev)
spin_lock_init(&nmk_chip->lock);
chip = &nmk_chip->chip;
chip->request = nmk_gpio_request;
chip->free = nmk_gpio_free;
chip->request = gpiochip_generic_request;
chip->free = gpiochip_generic_free;
chip->direction_input = nmk_gpio_make_input;
chip->get = nmk_gpio_get_input;
chip->direction_output = nmk_gpio_make_output;

View file

@ -713,16 +713,6 @@ static struct pinctrl_desc adi_pinmux_desc = {
.owner = THIS_MODULE,
};
static int adi_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void adi_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
struct gpio_port *port;
@ -994,8 +984,8 @@ static int adi_gpio_probe(struct platform_device *pdev)
port->chip.get = adi_gpio_get_value;
port->chip.direction_output = adi_gpio_direction_output;
port->chip.set = adi_gpio_set_value;
port->chip.request = adi_gpio_request;
port->chip.free = adi_gpio_free;
port->chip.request = gpiochip_generic_request,
port->chip.free = gpiochip_generic_free,
port->chip.to_irq = adi_gpio_to_irq;
if (pdata->port_gpio_base > 0)
port->chip.base = pdata->port_gpio_base;

View file

@ -536,21 +536,11 @@ static int as3722_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return as3722_irq_get_virq(as_pci->as3722, offset);
}
static int as3722_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void as3722_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static const struct gpio_chip as3722_gpio_chip = {
.label = "as3722-gpio",
.owner = THIS_MODULE,
.request = as3722_gpio_request,
.free = as3722_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get = as3722_gpio_get,
.set = as3722_gpio_set,
.direction_input = as3722_gpio_direction_input,

View file

@ -1280,28 +1280,6 @@ static int at91_pinctrl_remove(struct platform_device *pdev)
return 0;
}
static int at91_gpio_request(struct gpio_chip *chip, unsigned offset)
{
/*
* Map back to global GPIO space and request muxing, the direction
* parameter does not matter for this controller.
*/
int gpio = chip->base + offset;
int bank = chip->base / chip->ngpio;
dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
'A' + bank, offset, gpio);
return pinctrl_request_gpio(gpio);
}
static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
pinctrl_free_gpio(gpio);
}
static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
@ -1687,8 +1665,8 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
/* This structure is replicated for each GPIO block allocated at probe time */
static struct gpio_chip at91_gpio_template = {
.request = at91_gpio_request,
.free = at91_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get_direction = at91_gpio_get_direction,
.direction_input = at91_gpio_direction_input,
.get = at91_gpio_get,

View file

@ -217,24 +217,6 @@ static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip)
return container_of(chip, struct u300_gpio, chip);
}
static int u300_gpio_request(struct gpio_chip *chip, unsigned offset)
{
/*
* Map back to global GPIO space and request muxing, the direction
* parameter does not matter for this controller.
*/
int gpio = chip->base + offset;
return pinctrl_request_gpio(gpio);
}
static void u300_gpio_free(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
pinctrl_free_gpio(gpio);
}
static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct u300_gpio *gpio = to_u300_gpio(chip);
@ -417,8 +399,8 @@ int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset,
static struct gpio_chip u300_gpio_chip = {
.label = "u300-gpio-chip",
.owner = THIS_MODULE,
.request = u300_gpio_request,
.free = u300_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get = u300_gpio_get,
.set = u300_gpio_set,
.direction_input = u300_gpio_direction_input,

View file

@ -169,16 +169,6 @@ static struct pinmux_ops dc_pmxops = {
.gpio_request_enable = dc_pmx_request_gpio,
};
static int dc_gpio_request(struct gpio_chip *chip, unsigned gpio)
{
return pinctrl_request_gpio(chip->base + gpio);
}
static void dc_gpio_free(struct gpio_chip *chip, unsigned gpio)
{
pinctrl_free_gpio(chip->base + gpio);
}
static int dc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
struct dc_pinmap *pmap = container_of(chip, struct dc_pinmap, chip);
@ -255,8 +245,8 @@ static int dc_gpiochip_add(struct dc_pinmap *pmap, struct device_node *np)
chip->label = DRIVER_NAME;
chip->dev = pmap->dev;
chip->request = dc_gpio_request;
chip->free = dc_gpio_free;
chip->request = gpiochip_generic_request;
chip->free = gpiochip_generic_free;
chip->direction_input = dc_gpio_direction_input;
chip->direction_output = dc_gpio_direction_output;
chip->get = dc_gpio_get;

View file

@ -1171,16 +1171,6 @@ static struct pinctrl_desc pistachio_pinctrl_desc = {
.confops = &pistachio_pinconf_ops,
};
static int pistachio_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void pistachio_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int pistachio_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct pistachio_gpio_bank *bank = gc_to_bank(chip);
@ -1332,8 +1322,8 @@ static void pistachio_gpio_irq_handler(struct irq_desc *desc)
.npins = _npins, \
.gpio_chip = { \
.label = "GPIO" #_bank, \
.request = pistachio_gpio_request, \
.free = pistachio_gpio_free, \
.request = gpiochip_generic_request, \
.free = gpiochip_generic_free, \
.get_direction = pistachio_gpio_get_direction, \
.direction_input = pistachio_gpio_direction_input, \
.direction_output = pistachio_gpio_direction_output, \

View file

@ -1374,16 +1374,6 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
* GPIO handling
*/
static int rockchip_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void rockchip_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
{
struct rockchip_pin_bank *bank = gc_to_pin_bank(gc);
@ -1461,8 +1451,8 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
}
static const struct gpio_chip rockchip_gpiolib_chip = {
.request = rockchip_gpio_request,
.free = rockchip_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.set = rockchip_gpio_set,
.get = rockchip_gpio_get,
.direction_input = rockchip_gpio_direction_input,

View file

@ -742,16 +742,6 @@ static void st_gpio_direction(struct st_gpio_bank *bank,
}
}
static int st_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void st_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int st_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct st_gpio_bank *bank = gpio_chip_to_bank(chip);
@ -1490,8 +1480,8 @@ static void st_gpio_irqmux_handler(struct irq_desc *desc)
}
static struct gpio_chip st_gpio_template = {
.request = st_gpio_request,
.free = st_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get = st_gpio_get,
.set = st_gpio_set,
.direction_input = st_gpio_direction_input,

View file

@ -682,28 +682,14 @@ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
return 0;
}
static int xway_gpio_req(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
return pinctrl_request_gpio(gpio);
}
static void xway_gpio_free(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
pinctrl_free_gpio(gpio);
}
static struct gpio_chip xway_chip = {
.label = "gpio-xway",
.direction_input = xway_gpio_dir_in,
.direction_output = xway_gpio_dir_out,
.get = xway_gpio_get,
.set = xway_gpio_set,
.request = xway_gpio_req,
.free = xway_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.base = -1,
};

View file

@ -458,18 +458,6 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_unlock_irqrestore(&pctrl->lock, flags);
}
static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
return pinctrl_request_gpio(gpio);
}
static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
return pinctrl_free_gpio(gpio);
}
#ifdef CONFIG_DEBUG_FS
#include <linux/seq_file.h>
@ -527,8 +515,8 @@ static struct gpio_chip msm_gpio_template = {
.direction_output = msm_gpio_direction_output,
.get = msm_gpio_get,
.set = msm_gpio_set,
.request = msm_gpio_request,
.free = msm_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.dbg_show = msm_gpio_dbg_show,
};

View file

@ -546,16 +546,6 @@ static void pmic_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
pmic_gpio_config_set(state->ctrl, pin, &config, 1);
}
static int pmic_gpio_request(struct gpio_chip *chip, unsigned base)
{
return pinctrl_request_gpio(chip->base + base);
}
static void pmic_gpio_free(struct gpio_chip *chip, unsigned base)
{
pinctrl_free_gpio(chip->base + base);
}
static int pmic_gpio_of_xlate(struct gpio_chip *chip,
const struct of_phandle_args *gpio_desc,
u32 *flags)
@ -595,8 +585,8 @@ static const struct gpio_chip pmic_gpio_gpio_template = {
.direction_output = pmic_gpio_direction_output,
.get = pmic_gpio_get,
.set = pmic_gpio_set,
.request = pmic_gpio_request,
.free = pmic_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.of_xlate = pmic_gpio_of_xlate,
.to_irq = pmic_gpio_to_irq,
.dbg_show = pmic_gpio_dbg_show,

View file

@ -604,16 +604,6 @@ static void pmic_mpp_set(struct gpio_chip *chip, unsigned pin, int value)
pmic_mpp_config_set(state->ctrl, pin, &config, 1);
}
static int pmic_mpp_request(struct gpio_chip *chip, unsigned base)
{
return pinctrl_request_gpio(chip->base + base);
}
static void pmic_mpp_free(struct gpio_chip *chip, unsigned base)
{
pinctrl_free_gpio(chip->base + base);
}
static int pmic_mpp_of_xlate(struct gpio_chip *chip,
const struct of_phandle_args *gpio_desc,
u32 *flags)
@ -653,8 +643,8 @@ static const struct gpio_chip pmic_mpp_gpio_template = {
.direction_output = pmic_mpp_direction_output,
.get = pmic_mpp_get,
.set = pmic_mpp_set,
.request = pmic_mpp_request,
.free = pmic_mpp_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.of_xlate = pmic_mpp_of_xlate,
.to_irq = pmic_mpp_to_irq,
.dbg_show = pmic_mpp_dbg_show,

View file

@ -888,19 +888,9 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
return 0;
}
static int samsung_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void samsung_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static const struct gpio_chip samsung_gpiolib_chip = {
.request = samsung_gpio_request,
.free = samsung_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.set = samsung_gpio_set,
.get = samsung_gpio_get,
.direction_input = samsung_gpio_direction_input,

View file

@ -446,16 +446,6 @@ static const struct pinmux_ops sunxi_pmx_ops = {
.gpio_set_direction = sunxi_pmx_gpio_set_direction,
};
static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
@ -956,8 +946,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number;
pctl->chip->owner = THIS_MODULE;
pctl->chip->request = sunxi_pinctrl_gpio_request,
pctl->chip->free = sunxi_pinctrl_gpio_free,
pctl->chip->request = gpiochip_generic_request,
pctl->chip->free = gpiochip_generic_free,
pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input,
pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output,
pctl->chip->get = sunxi_pinctrl_gpio_get,

View file

@ -486,16 +486,6 @@ static struct pinctrl_desc wmt_desc = {
.confops = &wmt_pinconf_ops,
};
static int wmt_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void wmt_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev);
@ -560,8 +550,8 @@ static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static struct gpio_chip wmt_gpio_chip = {
.label = "gpio-wmt",
.owner = THIS_MODULE,
.request = wmt_gpio_request,
.free = wmt_gpio_free,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get_direction = wmt_gpio_get_direction,
.direction_input = wmt_gpio_direction_input,
.direction_output = wmt_gpio_direction_output,

View file

@ -9,7 +9,19 @@
#ifndef _DT_BINDINGS_GPIO_GPIO_H
#define _DT_BINDINGS_GPIO_GPIO_H
/* Bit 0 express polarity */
#define GPIO_ACTIVE_HIGH 0
#define GPIO_ACTIVE_LOW 1
/* Bit 1 express single-endedness */
#define GPIO_PUSH_PULL 0
#define GPIO_SINGLE_ENDED 2
/*
* Open Drain/Collector is the combination of single-ended active low,
* Open Source/Emitter is the combination of single-ended active high.
*/
#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_ACTIVE_LOW)
#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_ACTIVE_HIGH)
#endif

View file

@ -400,6 +400,7 @@ static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
{
return ERR_PTR(-EINVAL);
}
static inline int desc_to_gpio(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */

View file

@ -206,6 +206,9 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
#endif /* CONFIG_GPIOLIB_IRQCHIP */
int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset);
void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset);
#ifdef CONFIG_PINCTRL
/**

View file

@ -29,6 +29,7 @@ struct device_node;
*/
enum of_gpio_flags {
OF_GPIO_ACTIVE_LOW = 0x1,
OF_GPIO_SINGLE_ENDED = 0x2,
};
#ifdef CONFIG_OF_GPIO