You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'gpio-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Luinus Walleij:
"Bulk GPIO changes for the v4.10 kernel cycle:
Core changes:
- Simplify threaded interrupt handling: instead of passing numbed
parameters to gpiochip_irqchip_add_chained() we create a new call:
gpiochip_irqchip_add_nested() so the two types are clearly
semantically different. Also make sure that all nested chips call
gpiochip_set_nested_irqchip() which is necessary for IRQ resend to
work properly if it happens.
- Return error on seek operations for the chardev.
- Clamp values set as part of gpio[d]_direction_output() so that
anything != 0 will be send down to the driver as "1" not the value
passed in.
- ACPI can now support naming of GPIO lines, hogs and holes in the
GPIO lists.
New drivers:
- The SX150x driver was deemed unfit for the GPIO subsystem and was
moved over to a combined GPIO+pinctrl driver in the pinctrl
subsystem.
New features:
- Various cleanups to various drivers"
* tag 'gpio-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (49 commits)
gpio: merrifield: Implement gpio_get_direction callback
gpio: merrifield: Add support for hardware debouncer
gpio: chardev: Return error for seek operations
gpio: arizona: Tidy up probe error path
gpio: arizona: Remove pointless set of platform drvdata
gpio: pl061: delete platform data handling
gpio: pl061: move platform data into driver
gpio: pl061: rename variable from chip to pl061
gpio: pl061: rename state container struct
gpio: pl061: use local state for parent IRQ storage
gpio: set explicit nesting on drivers
gpio: simplify adding threaded interrupts
gpio: vf610: use builtin_platform_driver
gpio: axp209: use correct register for GPIO input status
gpio: stmpe: fix interrupt handling bug
gpio: em: depnd on ARCH_SHMOBILE
gpio: zx: depend on ARCH_ZX
gpio: x86: update config dependencies for x86 specific hardware
gpio: mb86s7x: use builtin_platform_driver
gpio: etraxfs: use builtin_platform_driver
...
This commit is contained in:
@@ -51,6 +51,68 @@ it to 1 marks the GPIO as active low.
|
||||
In our Bluetooth example the "reset-gpios" refers to the second GpioIo()
|
||||
resource, second pin in that resource with the GPIO number of 31.
|
||||
|
||||
It is possible to leave holes in the array of GPIOs. This is useful in
|
||||
cases like with SPI host controllers where some chip selects may be
|
||||
implemented as GPIOs and some as native signals. For example a SPI host
|
||||
controller can have chip selects 0 and 2 implemented as GPIOs and 1 as
|
||||
native:
|
||||
|
||||
Package () {
|
||||
"cs-gpios",
|
||||
Package () {
|
||||
^GPIO, 19, 0, 0, // chip select 0: GPIO
|
||||
0, // chip select 1: native signal
|
||||
^GPIO, 20, 0, 0, // chip select 2: GPIO
|
||||
}
|
||||
}
|
||||
|
||||
Other supported properties
|
||||
--------------------------
|
||||
|
||||
Following Device Tree compatible device properties are also supported by
|
||||
_DSD device properties for GPIO controllers:
|
||||
|
||||
- gpio-hog
|
||||
- output-high
|
||||
- output-low
|
||||
- input
|
||||
- line-name
|
||||
|
||||
Example:
|
||||
|
||||
Name (_DSD, Package () {
|
||||
// _DSD Hierarchical Properties Extension UUID
|
||||
ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
|
||||
Package () {
|
||||
Package () {"hog-gpio8", "G8PU"}
|
||||
}
|
||||
})
|
||||
|
||||
Name (G8PU, Package () {
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package () {
|
||||
Package () {"gpio-hog", 1},
|
||||
Package () {"gpios", Package () {8, 0}},
|
||||
Package () {"output-high", 1},
|
||||
Package () {"line-name", "gpio8-pullup"},
|
||||
}
|
||||
})
|
||||
|
||||
- gpio-line-names
|
||||
|
||||
Example:
|
||||
|
||||
Package () {
|
||||
"gpio-line-names",
|
||||
Package () {
|
||||
"SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD", "MUX7_IO",
|
||||
"LVL_C_A1", "MUX0_IO", "SPI1_MISO"
|
||||
}
|
||||
}
|
||||
|
||||
See Documentation/devicetree/bindings/gpio/gpio.txt for more information
|
||||
about these properties.
|
||||
|
||||
ACPI GPIO Mappings Provided by Drivers
|
||||
--------------------------------------
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
SEMTECH SX150x GPIO expander bindings
|
||||
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be "semtech,sx1506q",
|
||||
"semtech,sx1508q",
|
||||
"semtech,sx1509q",
|
||||
"semtech,sx1502q".
|
||||
|
||||
- reg: The I2C slave address for this device.
|
||||
|
||||
- interrupt-parent: phandle of the parent interrupt controller.
|
||||
|
||||
- interrupts: Interrupt specifier for the controllers interrupt.
|
||||
|
||||
- #gpio-cells: Should be 2. The first cell is the GPIO number and the
|
||||
second cell is used to specify optional parameters:
|
||||
bit 0: polarity (0: normal, 1: inverted)
|
||||
|
||||
- gpio-controller: Marks the device as a GPIO controller.
|
||||
|
||||
- interrupt-controller: Marks the device as a interrupt controller.
|
||||
|
||||
The GPIO expander can optionally be used as an interrupt controller, in
|
||||
which case it uses the default two cell specifier as described in
|
||||
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
|
||||
|
||||
Example:
|
||||
|
||||
i2c_gpio_expander@20{
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
compatible = "semtech,sx1506q";
|
||||
reg = <0x20>;
|
||||
interrupt-parent = <&gpio_1>;
|
||||
interrupts = <16 0>;
|
||||
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
SEMTECH SX150x GPIO expander bindings
|
||||
|
||||
Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and
|
||||
../interrupt-controller/interrupts.txt for generic information regarding
|
||||
pin controller, GPIO, and interrupt bindings.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be one of :
|
||||
"semtech,sx1506q",
|
||||
"semtech,sx1508q",
|
||||
"semtech,sx1509q",
|
||||
"semtech,sx1502q".
|
||||
|
||||
- reg: The I2C slave address for this device.
|
||||
|
||||
- #gpio-cells: Should be 2. The first cell is the GPIO number and the
|
||||
second cell is used to specify optional parameters:
|
||||
bit 0: polarity (0: normal, 1: inverted)
|
||||
|
||||
- gpio-controller: Marks the device as a GPIO controller.
|
||||
|
||||
Optional properties :
|
||||
- interrupt-parent: phandle of the parent interrupt controller.
|
||||
|
||||
- interrupts: Interrupt specifier for the controllers interrupt.
|
||||
|
||||
- interrupt-controller: Marks the device as a interrupt controller.
|
||||
|
||||
- semtech,probe-reset: Will trigger a reset of the GPIO expander on probe,
|
||||
only for sx1508q and sx1509q
|
||||
|
||||
The GPIO expander can optionally be used as an interrupt controller, in
|
||||
which case it uses the default two cell specifier.
|
||||
|
||||
Required properties for pin configuration sub-nodes:
|
||||
- pins: List of pins to which the configuration applies.
|
||||
|
||||
Optional properties for pin configuration sub-nodes:
|
||||
----------------------------------------------------
|
||||
- bias-disable: disable any pin bias, except the OSCIO pin
|
||||
- bias-pull-up: pull up the pin, except the OSCIO pin
|
||||
- bias-pull-down: pull down the pin, except the OSCIO pin
|
||||
- bias-pull-pin-default: use pin-default pull state, except the OSCIO pin
|
||||
- drive-push-pull: drive actively high and low
|
||||
- drive-open-drain: drive with open drain only for sx1508q and sx1509q and except the OSCIO pin
|
||||
- output-low: set the pin to output mode with low level
|
||||
- output-high: set the pin to output mode with high level
|
||||
|
||||
Example:
|
||||
|
||||
i2c0gpio-expander@20{
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
compatible = "semtech,sx1506q";
|
||||
reg = <0x20>;
|
||||
interrupt-parent = <&gpio_1>;
|
||||
interrupts = <16 0>;
|
||||
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpio1_cfg_pins>;
|
||||
|
||||
gpio1_cfg_pins: gpio1-cfg {
|
||||
pins = "gpio1";
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
@@ -175,8 +175,8 @@ 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.
|
||||
RT_FULL: a realtime compliant GPIO driver should not use spinlock_t or any
|
||||
sleepable APIs (like PM runtime) as part of its irq_chip implementation.
|
||||
- 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
|
||||
@@ -185,33 +185,32 @@ RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs
|
||||
GPIO irqchips usually fall in one of two categories:
|
||||
|
||||
* CHAINED GPIO irqchips: these are usually the type that is embedded on
|
||||
an SoC. This means that there is a fast IRQ handler for the GPIOs that
|
||||
an SoC. This means that there is a fast IRQ flow handler for the GPIOs that
|
||||
gets called in a chain from the parent IRQ handler, most typically the
|
||||
system interrupt controller. This means the GPIO irqchip is registered
|
||||
using irq_set_chained_handler() or the corresponding
|
||||
gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
|
||||
handler will be called immediately from the parent irqchip, while
|
||||
holding the IRQs disabled. The GPIO irqchip will then end up calling
|
||||
something like this sequence in its interrupt handler:
|
||||
system interrupt controller. This means that the GPIO irqchip handler will
|
||||
be called immediately from the parent irqchip, while holding the IRQs
|
||||
disabled. The GPIO irqchip will then end up calling something like this
|
||||
sequence in its interrupt handler:
|
||||
|
||||
static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
|
||||
static irqreturn_t foo_gpio_irq(int irq, void *data)
|
||||
chained_irq_enter(...);
|
||||
generic_handle_irq(...);
|
||||
chained_irq_exit(...);
|
||||
|
||||
Chained GPIO irqchips typically can NOT set the .can_sleep flag on
|
||||
struct gpio_chip, as everything happens directly in the callbacks.
|
||||
struct gpio_chip, as everything happens directly in the callbacks: no
|
||||
slow bus traffic like I2C can be used.
|
||||
|
||||
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
|
||||
If required (and if it can't be converted to the nested threaded GPIO irqchip)
|
||||
a chained IRQ handler can be converted to generic irq handler and this way
|
||||
it will be a threaded IRQ handler on -RT and a 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 which is
|
||||
forced thread. The "fake?" raw lock can be used to W/A this problem:
|
||||
so the IRQ core will complain if it is called from an IRQ handler which is
|
||||
forced to a 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)
|
||||
@@ -243,7 +242,7 @@ GPIO irqchips usually fall in one of two categories:
|
||||
by the driver. The hallmark of this driver is to call something like
|
||||
this in its interrupt handler:
|
||||
|
||||
static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
|
||||
static irqreturn_t foo_gpio_irq(int irq, void *data)
|
||||
...
|
||||
handle_nested_irq(irq);
|
||||
|
||||
@@ -256,23 +255,31 @@ associated irqdomain and resource allocation callbacks, the gpiolib has
|
||||
some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
|
||||
symbol:
|
||||
|
||||
* gpiochip_irqchip_add(): adds an irqchip to a gpiochip. It will pass
|
||||
* gpiochip_irqchip_add(): adds a chained irqchip to a gpiochip. It will pass
|
||||
the struct gpio_chip* for the chip to all IRQ callbacks, so the callbacks
|
||||
need to embed the gpio_chip in its state container and obtain a pointer
|
||||
to the container using container_of().
|
||||
(See Documentation/driver-model/design-patterns.txt)
|
||||
|
||||
If there is a need to exclude certain GPIOs from the IRQ domain, one can
|
||||
set .irq_need_valid_mask of the gpiochip before gpiochip_add_data() is
|
||||
called. This allocates .irq_valid_mask with as many bits set as there are
|
||||
GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this
|
||||
mask. The mask must be filled in before gpiochip_irqchip_add() is called.
|
||||
* gpiochip_irqchip_add_nested(): adds a nested irqchip to a gpiochip.
|
||||
Apart from that it works exactly like the chained irqchip.
|
||||
|
||||
* gpiochip_set_chained_irqchip(): sets up a chained irq handler for a
|
||||
gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
|
||||
data. (Notice handler data, since the irqchip data is likely used by the
|
||||
parent irqchip!) This is for the chained type of chip. This is also used
|
||||
to set up a nested irqchip if NULL is passed as handler.
|
||||
parent irqchip!).
|
||||
|
||||
* gpiochip_set_nested_irqchip(): sets up a nested irq handler for a
|
||||
gpio_chip from a parent IRQ. As the parent IRQ has usually been
|
||||
explicitly requested by the driver, this does very little more than
|
||||
mark all the child IRQs as having the other IRQ as parent.
|
||||
|
||||
If there is a need to exclude certain GPIOs from the IRQ domain, you can
|
||||
set .irq_need_valid_mask of the gpiochip before gpiochip_add_data() is
|
||||
called. This allocates an .irq_valid_mask with as many bits set as there
|
||||
are GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this
|
||||
mask. The mask must be filled in before gpiochip_irqchip_add() or
|
||||
gpiochip_irqchip_add_nested() is called.
|
||||
|
||||
To use the helpers please keep the following in mind:
|
||||
|
||||
@@ -323,6 +330,9 @@ When implementing an irqchip inside a GPIO driver, these two functions should
|
||||
typically be called in the .startup() and .shutdown() callbacks from the
|
||||
irqchip.
|
||||
|
||||
When using the gpiolib irqchip helpers, these callback are automatically
|
||||
assigned.
|
||||
|
||||
Real-Time compliance for GPIO IRQ chips
|
||||
---------------------------------------
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/amba/mmci.h>
|
||||
#include <linux/amba/pl061.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_data/clk-integrator.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
+24
-14
@@ -167,7 +167,7 @@ config GPIO_DWAPB
|
||||
|
||||
config GPIO_EM
|
||||
tristate "Emma Mobile GPIO"
|
||||
depends on ARM && OF_GPIO
|
||||
depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO
|
||||
help
|
||||
Say yes here to support GPIO on Renesas Emma Mobile SoCs.
|
||||
|
||||
@@ -451,7 +451,7 @@ config GPIO_VR41XX
|
||||
|
||||
config GPIO_VX855
|
||||
tristate "VIA VX855/VX875 GPIO"
|
||||
depends on PCI
|
||||
depends on (X86 || COMPILE_TEST) && PCI
|
||||
select MFD_CORE
|
||||
select MFD_VX855
|
||||
help
|
||||
@@ -520,6 +520,7 @@ config GPIO_ZYNQ
|
||||
|
||||
config GPIO_ZX
|
||||
bool "ZTE ZX GPIO support"
|
||||
depends on ARCH_ZX || COMPILE_TEST
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to support the GPIO device on ZTE ZX SoCs.
|
||||
@@ -603,7 +604,7 @@ config GPIO_IT87
|
||||
|
||||
config GPIO_SCH
|
||||
tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
|
||||
depends on PCI
|
||||
depends on (X86 || COMPILE_TEST) && PCI
|
||||
select MFD_CORE
|
||||
select LPC_SCH
|
||||
help
|
||||
@@ -777,16 +778,13 @@ config GPIO_PCF857X
|
||||
platform-neutral GPIO calls.
|
||||
|
||||
config GPIO_SX150X
|
||||
bool "Semtech SX150x I2C GPIO expander"
|
||||
depends on I2C=y
|
||||
select GPIOLIB_IRQCHIP
|
||||
bool "Semtech SX150x I2C GPIO expander (deprecated)"
|
||||
depends on PINCTRL && I2C=y
|
||||
select PINCTRL_SX150X
|
||||
default n
|
||||
help
|
||||
Say yes here to provide support for Semtech SX150-series I2C
|
||||
GPIO expanders. Compatible models include:
|
||||
|
||||
8 bits: sx1508q
|
||||
16 bits: sx1509q
|
||||
Say yes here to provide support for Semtech SX150x-series I2C
|
||||
GPIO expanders. The GPIO driver was replaced by a Pinctrl version.
|
||||
|
||||
config GPIO_TPIC2810
|
||||
tristate "TPIC2810 8-Bit I2C GPO expander"
|
||||
@@ -798,6 +796,7 @@ config GPIO_TPIC2810
|
||||
|
||||
config GPIO_TS4900
|
||||
tristate "Technologic Systems FPGA I2C GPIO"
|
||||
depends on SOC_IMX6 || COMPILE_TEST
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say yes here to enabled the GPIO driver for Technologic's FPGA core.
|
||||
@@ -814,6 +813,14 @@ config GPIO_ADP5520
|
||||
This option enables support for on-chip GPIO found
|
||||
on Analog Devices ADP5520 PMICs.
|
||||
|
||||
config GPIO_ALTERA_A10SR
|
||||
tristate "Altera Arria10 System Resource GPIO"
|
||||
depends on MFD_ALTERA_A10SR
|
||||
help
|
||||
Driver for Arria10 Development Kit GPIO expansion which
|
||||
includes reads of pushbuttons and DIP switches as well
|
||||
as writes to LEDs.
|
||||
|
||||
config GPIO_ARIZONA
|
||||
tristate "Wolfson Microelectronics Arizona class devices"
|
||||
depends on MFD_ARIZONA
|
||||
@@ -822,7 +829,7 @@ config GPIO_ARIZONA
|
||||
|
||||
config GPIO_CRYSTAL_COVE
|
||||
tristate "GPIO support for Crystal Cove PMIC"
|
||||
depends on INTEL_SOC_PMIC
|
||||
depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Support for GPIO pins on Crystal Cove PMIC.
|
||||
@@ -835,6 +842,7 @@ config GPIO_CRYSTAL_COVE
|
||||
|
||||
config GPIO_CS5535
|
||||
tristate "AMD CS5535/CS5536 GPIO support"
|
||||
depends on X86 || MIPS || COMPILE_TEST
|
||||
depends on MFD_CS5535
|
||||
help
|
||||
The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
|
||||
@@ -927,7 +935,7 @@ config GPIO_MAX77620
|
||||
|
||||
config GPIO_MSIC
|
||||
bool "Intel MSIC mixed signal gpio support"
|
||||
depends on MFD_INTEL_MSIC
|
||||
depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
|
||||
help
|
||||
Enable support for GPIO on intel MSIC controllers found in
|
||||
intel MID devices
|
||||
@@ -1028,7 +1036,7 @@ config GPIO_UCB1400
|
||||
|
||||
config GPIO_WHISKEY_COVE
|
||||
tristate "GPIO support for Whiskey Cove PMIC"
|
||||
depends on INTEL_SOC_PMIC
|
||||
depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Support for GPIO pins on Whiskey Cove PMIC.
|
||||
@@ -1067,6 +1075,7 @@ menu "PCI GPIO expanders"
|
||||
|
||||
config GPIO_AMD8111
|
||||
tristate "AMD 8111 GPIO driver"
|
||||
depends on X86 || COMPILE_TEST
|
||||
help
|
||||
The AMD 8111 south bridge contains 32 GPIO pins which can be used.
|
||||
|
||||
@@ -1108,6 +1117,7 @@ config GPIO_MERRIFIELD
|
||||
|
||||
config GPIO_ML_IOH
|
||||
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
|
||||
depends on X86 || COMPILE_TEST
|
||||
select GENERIC_IRQ_CHIP
|
||||
help
|
||||
ML7213 is companion chip for Intel Atom E6xx series.
|
||||
|
||||
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
|
||||
obj-$(CONFIG_GPIOLIB) += devres.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o
|
||||
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
|
||||
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
|
||||
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
|
||||
@@ -24,6 +25,7 @@ obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
|
||||
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
|
||||
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
|
||||
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
|
||||
obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o
|
||||
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
|
||||
obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
|
||||
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
||||
@@ -102,7 +104,6 @@ obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
|
||||
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
|
||||
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
|
||||
obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o
|
||||
obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
|
||||
obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o
|
||||
obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o
|
||||
obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
|
||||
|
||||
@@ -468,17 +468,19 @@ static int adnp_irq_setup(struct adnp *adnp)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = gpiochip_irqchip_add(chip,
|
||||
&adnp_irq_chip,
|
||||
0,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
err = gpiochip_irqchip_add_nested(chip,
|
||||
&adnp_irq_chip,
|
||||
0,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
if (err) {
|
||||
dev_err(chip->parent,
|
||||
"could not connect irqchip to gpiochip\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
gpiochip_set_nested_irqchip(chip, &adnp_irq_chip, adnp->client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright Intel Corporation (C) 2014-2016. All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* GPIO driver for Altera Arria10 MAX5 System Resource Chip
|
||||
*
|
||||
* Adapted from gpio-tps65910.c
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/mfd/altera-a10sr.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/**
|
||||
* struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure
|
||||
* @gp: : instance of the gpio_chip
|
||||
* @regmap: the regmap from the parent device.
|
||||
*/
|
||||
struct altr_a10sr_gpio {
|
||||
struct gpio_chip gp;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
|
||||
int ret, val;
|
||||
|
||||
ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT));
|
||||
}
|
||||
|
||||
static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG,
|
||||
BIT(ALTR_A10SR_LED_VALID_SHIFT + offset),
|
||||
value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset)
|
||||
: 0);
|
||||
}
|
||||
|
||||
static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
|
||||
unsigned int nr)
|
||||
{
|
||||
if (nr >= (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT))
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned int nr, int value)
|
||||
{
|
||||
if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct gpio_chip altr_a10sr_gc = {
|
||||
.label = "altr_a10sr_gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.get = altr_a10sr_gpio_get,
|
||||
.set = altr_a10sr_gpio_set,
|
||||
.direction_input = altr_a10sr_gpio_direction_input,
|
||||
.direction_output = altr_a10sr_gpio_direction_output,
|
||||
.can_sleep = true,
|
||||
.ngpio = 12,
|
||||
.base = -1,
|
||||
};
|
||||
|
||||
static int altr_a10sr_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct altr_a10sr_gpio *gpio;
|
||||
int ret;
|
||||
struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
if (!gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
gpio->regmap = a10sr->regmap;
|
||||
|
||||
gpio->gp = altr_a10sr_gc;
|
||||
|
||||
gpio->gp.of_node = pdev->dev.of_node;
|
||||
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, gpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id altr_a10sr_gpio_of_match[] = {
|
||||
{ .compatible = "altr,a10sr-gpio" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match);
|
||||
|
||||
static struct platform_driver altr_a10sr_gpio_driver = {
|
||||
.probe = altr_a10sr_gpio_probe,
|
||||
.driver = {
|
||||
.name = "altr_a10sr_gpio",
|
||||
.of_match_table = of_match_ptr(altr_a10sr_gpio_of_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(altr_a10sr_gpio_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>");
|
||||
MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO");
|
||||
@@ -137,15 +137,10 @@ static int arizona_gpio_probe(struct platform_device *pdev)
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
|
||||
ret);
|
||||
goto err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, arizona_gpio);
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver arizona_gpio_driver = {
|
||||
|
||||
@@ -64,13 +64,9 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct axp20x_gpio *gpio = gpiochip_get_data(chip);
|
||||
unsigned int val;
|
||||
int reg, ret;
|
||||
int ret;
|
||||
|
||||
reg = axp20x_gpio_get_reg(offset);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
ret = regmap_read(gpio->regmap, reg, &val);
|
||||
ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -351,8 +351,8 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
|
||||
return retval;
|
||||
}
|
||||
|
||||
gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0,
|
||||
handle_simple_irq, IRQ_TYPE_NONE);
|
||||
gpiochip_irqchip_add_nested(&cg->chip, &crystalcove_irqchip, 0,
|
||||
handle_simple_irq, IRQ_TYPE_NONE);
|
||||
|
||||
retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler,
|
||||
IRQF_ONESHOT, KBUILD_MODNAME, cg);
|
||||
@@ -362,6 +362,8 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
|
||||
return retval;
|
||||
}
|
||||
|
||||
gpiochip_set_nested_irqchip(&cg->chip, &crystalcove_irqchip, irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ struct davinci_gpio_regs {
|
||||
typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq);
|
||||
|
||||
#define BINTEN 0x8 /* GPIO Interrupt Per-Bank Enable Register */
|
||||
#define MAX_LABEL_SIZE 20
|
||||
|
||||
static void __iomem *gpio_base;
|
||||
|
||||
@@ -201,6 +202,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
|
||||
struct davinci_gpio_regs __iomem *regs;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
char label[MAX_LABEL_SIZE];
|
||||
|
||||
pdata = davinci_gpio_get_pdata(pdev);
|
||||
if (!pdata) {
|
||||
@@ -237,7 +239,10 @@ static int davinci_gpio_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(gpio_base);
|
||||
|
||||
for (i = 0, base = 0; base < ngpio; i++, base += 32) {
|
||||
chips[i].chip.label = "DaVinci";
|
||||
snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", i);
|
||||
chips[i].chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
|
||||
if (!chips[i].chip.label)
|
||||
return -ENOMEM;
|
||||
|
||||
chips[i].chip.direction_input = davinci_direction_in;
|
||||
chips[i].chip.get = davinci_gpio_get;
|
||||
|
||||
@@ -467,7 +467,6 @@ static int dln2_gpio_probe(struct platform_device *pdev)
|
||||
dln2->gpio.base = -1;
|
||||
dln2->gpio.ngpio = pins;
|
||||
dln2->gpio.can_sleep = true;
|
||||
dln2->gpio.irq_not_threaded = true;
|
||||
dln2->gpio.set = dln2_gpio_set;
|
||||
dln2->gpio.get = dln2_gpio_get;
|
||||
dln2->gpio.request = dln2_gpio_request;
|
||||
|
||||
@@ -471,9 +471,4 @@ static struct platform_driver etraxfs_gpio_driver = {
|
||||
.probe = etraxfs_gpio_probe,
|
||||
};
|
||||
|
||||
static int __init etraxfs_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&etraxfs_gpio_driver);
|
||||
}
|
||||
|
||||
device_initcall(etraxfs_gpio_init);
|
||||
builtin_platform_driver(etraxfs_gpio_driver);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <linux/platform_data/gpio-htc-egpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
struct egpio_chip {
|
||||
int reg_start;
|
||||
@@ -160,10 +160,14 @@ static int egpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
bit = egpio_bit(ei, offset);
|
||||
reg = egpio->reg_start + egpio_pos(ei, offset);
|
||||
|
||||
value = egpio_readw(ei, reg);
|
||||
pr_debug("readw(%p + %x) = %x\n",
|
||||
ei->base_addr, reg << ei->bus_shift, value);
|
||||
return !!(value & bit);
|
||||
if (test_bit(offset, &egpio->is_out)) {
|
||||
return !!(egpio->cached_values & (1 << offset));
|
||||
} else {
|
||||
value = egpio_readw(ei, reg);
|
||||
pr_debug("readw(%p + %x) = %x\n",
|
||||
ei->base_addr, reg << ei->bus_shift, value);
|
||||
return !!(value & bit);
|
||||
}
|
||||
}
|
||||
|
||||
static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
@@ -225,6 +229,15 @@ static int egpio_direction_output(struct gpio_chip *chip,
|
||||
}
|
||||
}
|
||||
|
||||
static int egpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct egpio_chip *egpio;
|
||||
|
||||
egpio = gpiochip_get_data(chip);
|
||||
|
||||
return !test_bit(offset, &egpio->is_out);
|
||||
}
|
||||
|
||||
static void egpio_write_cache(struct egpio_info *ei)
|
||||
{
|
||||
int i;
|
||||
@@ -327,6 +340,7 @@ static int __init egpio_probe(struct platform_device *pdev)
|
||||
chip->set = egpio_set;
|
||||
chip->direction_input = egpio_direction_input;
|
||||
chip->direction_output = egpio_direction_output;
|
||||
chip->get_direction = egpio_get_direction;
|
||||
chip->base = pdata->chip[i].gpio_base;
|
||||
chip->ngpio = pdata->chip[i].num_gpios;
|
||||
|
||||
@@ -367,24 +381,6 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __exit egpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct egpio_info *ei = platform_get_drvdata(pdev);
|
||||
unsigned int irq, irq_end;
|
||||
|
||||
if (ei->chained_irq) {
|
||||
irq_end = ei->irq_start + ei->nirqs;
|
||||
for (irq = ei->irq_start; irq < irq_end; irq++) {
|
||||
irq_set_chip_and_handler(irq, NULL, NULL);
|
||||
irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
|
||||
}
|
||||
irq_set_chained_handler(ei->chained_irq, NULL);
|
||||
device_init_wakeup(&pdev->dev, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
@@ -416,8 +412,8 @@ static int egpio_resume(struct platform_device *pdev)
|
||||
static struct platform_driver egpio_driver = {
|
||||
.driver = {
|
||||
.name = "htc-egpio",
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.remove = __exit_p(egpio_remove),
|
||||
.suspend = egpio_suspend,
|
||||
.resume = egpio_resume,
|
||||
};
|
||||
@@ -426,15 +422,5 @@ static int __init egpio_init(void)
|
||||
{
|
||||
return platform_driver_probe(&egpio_driver, egpio_probe);
|
||||
}
|
||||
|
||||
static void __exit egpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&egpio_driver);
|
||||
}
|
||||
|
||||
/* start early for dependencies */
|
||||
subsys_initcall(egpio_init);
|
||||
module_exit(egpio_exit)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Kevin O'Connor <kevin@koconnor.net>");
|
||||
|
||||
@@ -421,9 +421,4 @@ static struct pci_driver intel_gpio_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init intel_gpio_init(void)
|
||||
{
|
||||
return pci_register_driver(&intel_gpio_driver);
|
||||
}
|
||||
|
||||
device_initcall(intel_gpio_init);
|
||||
builtin_pci_driver(intel_gpio_driver);
|
||||
|
||||
@@ -520,20 +520,19 @@ static int max732x_irq_setup(struct max732x_chip *chip,
|
||||
client->irq);
|
||||
return ret;
|
||||
}
|
||||
ret = gpiochip_irqchip_add(&chip->gpio_chip,
|
||||
&max732x_irq_chip,
|
||||
irq_base,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
ret = gpiochip_irqchip_add_nested(&chip->gpio_chip,
|
||||
&max732x_irq_chip,
|
||||
irq_base,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"could not connect irqchip to gpiochip\n");
|
||||
return ret;
|
||||
}
|
||||
gpiochip_set_chained_irqchip(&chip->gpio_chip,
|
||||
&max732x_irq_chip,
|
||||
client->irq,
|
||||
NULL);
|
||||
gpiochip_set_nested_irqchip(&chip->gpio_chip,
|
||||
&max732x_irq_chip,
|
||||
client->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -21,9 +21,6 @@ struct max77620_gpio {
|
||||
struct gpio_chip gpio_chip;
|
||||
struct regmap *rmap;
|
||||
struct device *dev;
|
||||
int gpio_irq;
|
||||
int irq_base;
|
||||
int gpio_base;
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77620_gpio_irqs[] = {
|
||||
@@ -254,7 +251,6 @@ static int max77620_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
mgpio->rmap = chip->rmap;
|
||||
mgpio->dev = &pdev->dev;
|
||||
mgpio->gpio_irq = gpio_irq;
|
||||
|
||||
mgpio->gpio_chip.label = pdev->name;
|
||||
mgpio->gpio_chip.parent = &pdev->dev;
|
||||
@@ -268,7 +264,6 @@ static int max77620_gpio_probe(struct platform_device *pdev)
|
||||
mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
|
||||
mgpio->gpio_chip.can_sleep = 1;
|
||||
mgpio->gpio_chip.base = -1;
|
||||
mgpio->irq_base = -1;
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
mgpio->gpio_chip.of_node = pdev->dev.parent->of_node;
|
||||
#endif
|
||||
@@ -281,9 +276,8 @@ static int max77620_gpio_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mgpio->gpio_base = mgpio->gpio_chip.base;
|
||||
ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, mgpio->gpio_irq,
|
||||
IRQF_ONESHOT, mgpio->irq_base,
|
||||
ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, gpio_irq,
|
||||
IRQF_ONESHOT, -1,
|
||||
&max77620_gpio_irq_chip,
|
||||
&chip->gpio_irq_data);
|
||||
if (ret < 0) {
|
||||
@@ -296,6 +290,7 @@ static int max77620_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
static const struct platform_device_id max77620_gpio_devtype[] = {
|
||||
{ .name = "max77620-gpio", },
|
||||
{ .name = "max20024-gpio", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max77620_gpio_devtype);
|
||||
|
||||
@@ -217,8 +217,4 @@ static struct platform_driver mb86s70_gpio_driver = {
|
||||
.remove = mb86s70_gpio_remove,
|
||||
};
|
||||
|
||||
static int __init mb86s70_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&mb86s70_gpio_driver);
|
||||
}
|
||||
device_initcall(mb86s70_gpio_init);
|
||||
builtin_platform_driver(mb86s70_gpio_driver);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user