mirror of
https://github.com/suyu-emu/horinux.git
synced 2026-09-21 14:15:21 -07:00
Merge tag 'gpio-v3.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull bulk of gpio updates from Linus Walleij:
"A pretty big chunk of changes this time, but it has all been on
rotation in linux-next and had some testing. Of course there will be
some amount of fixes on top...
- Merged in a branch of irqchip changes from Thomas Gleixner: we need
to have new callbacks from the irqchip to determine if the GPIO
line will be eligible for IRQs, and this callback must be able to
say "no". After some thinking I got the branch from tglx and have
switched all current users over to use this.
- Based on tglx patches, we have added some generic irqchip helpers
in the gpiolib core. These will help centralize code when GPIO
drivers have simple chained/cascaded IRQs. Drivers will still
define their irqchip vtables, but the gpiolib core will take care
of irqdomain set-up, mapping from local offsets to Linux irqs, and
reserve resources by marking the GPIO lines for IRQs.
- Initially the PL061 and Nomadik GPIO/pin control drivers have been
switched over to use the new gpiochip-to-irqchip infrastructure
with more drivers expected for the next kernel cycle. The
factoring of just two drivers still makes it worth it so it is
already a win.
- A new driver for the Synopsys DesignWare APB GPIO block.
- Modify the DaVinci GPIO driver to be reusable also for the new TI
Keystone architecture.
- A new driver for the LSI ZEVIO SoCs.
- Delete the obsolte tnetv107x driver.
- Some incremental work on GPIO descriptors: have
gpiod_direction_output() use a logical level, respecting assertion
polarity through ACTIVE_LOW flags, adding gpiod_direction_output_raw()
for the case where you want to set that very value. Add
gpiochip_get_desc() to fetch a GPIO descriptor from a specific
offset on a certain chip inside driver code.
- Switch ACPI GPIO code over to using gpiochip_get_desc() and get rid
of gpio_to_desc().
- The ACPI GPIO event handling code has been reworked after
encountering an actual real life implementation.
- Support for ACPI GPIO operation regions.
- Generic GPIO chips can now be assigned labels/names from platform
data.
- We now clamp values returned from GPIO drivers to the boolean [0,1]
range.
- Some improved documentation on how to use the polarity flag was
added.
- a large slew of incremental driver updates and non-critical fixes.
Some targeted for stable"
* tag 'gpio-v3.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (80 commits)
gpio: rcar: Add helper variable dev = &pdev->dev
gpio-lynxpoint: force gpio_get() to return "1" and "0" only
gpio: unmap gpio irqs properly
pch_gpio: set value before enabling output direction
gpio: moxart: Actually set output state in moxart_gpio_direction_output()
gpio: moxart: Avoid forward declaration
gpio: mxs: Allow for recursive enable_irq_wake() call
gpio: samsung: Add missing "break" statement
gpio: twl4030: Remove redundant assignment
gpio: dwapb: correct gpio-cells in binding document
gpio: iop: fix devm_ioremap_resource() return value checking
pinctrl: coh901: convert driver to use gpiolib irqchip
pinctrl: nomadik: convert driver to use gpiolib irqchip
gpio: pl061: convert driver to use gpiolib irqchip
gpio: add IRQ chip helpers in gpiolib
pinctrl: nomadik: factor in platform data container
pinctrl: nomadik: rename secondary to latent
gpio: Driver for SYSCON-based GPIOs
gpio: generic: Use platform_device_id->driver_data field for driver flags
pinctrl: coh901: move irq line locking to resource callbacks
...
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
* ARM Cirrus Logic CLPS711X SYSFLG1 MCTRL GPIOs
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain "cirrus,clps711x-mctrl-gpio".
|
||||
- gpio-controller: Marks the device node as a gpio controller.
|
||||
- #gpio-cells: Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify the gpio polarity:
|
||||
0 = Active high,
|
||||
1 = Active low.
|
||||
|
||||
Example:
|
||||
sysgpio: sysgpio {
|
||||
compatible = "cirrus,ep7312-mctrl-gpio",
|
||||
"cirrus,clps711x-mctrl-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
@@ -1,13 +1,17 @@
|
||||
Davinci GPIO controller bindings
|
||||
Davinci/Keystone GPIO controller bindings
|
||||
|
||||
Required Properties:
|
||||
- compatible: should be "ti,dm6441-gpio"
|
||||
- compatible: should be "ti,dm6441-gpio", "ti,keystone-gpio"
|
||||
|
||||
- reg: Physical base address of the controller and the size of memory mapped
|
||||
registers.
|
||||
|
||||
- gpio-controller : Marks the device node as a gpio controller.
|
||||
|
||||
- #gpio-cells : Should be two.
|
||||
- first cell is the pin number
|
||||
- second cell is used to specify optional parameters (unused)
|
||||
|
||||
- interrupt-parent: phandle of the parent interrupt controller.
|
||||
|
||||
- interrupts: Array of GPIO interrupt number. Only banked or unbanked IRQs are
|
||||
@@ -27,6 +31,7 @@ Example:
|
||||
gpio: gpio@1e26000 {
|
||||
compatible = "ti,dm6441-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
reg = <0x226000 0x1000>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <42 IRQ_TYPE_EDGE_BOTH 43 IRQ_TYPE_EDGE_BOTH
|
||||
@@ -39,3 +44,19 @@ gpio: gpio@1e26000 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led1 {
|
||||
label = "davinci:green:usr1";
|
||||
gpios = <&gpio 10 GPIO_ACTIVE_HIGH>;
|
||||
...
|
||||
};
|
||||
|
||||
led2 {
|
||||
label = "davinci:red:debug1";
|
||||
gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
Zevio GPIO controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "lsi,zevio-gpio"
|
||||
- reg: Address and length of the register set for the device
|
||||
- #gpio-cells: Should be two. The first cell is the pin number and the
|
||||
second cell is used to specify optional parameters (currently unused).
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
|
||||
Example:
|
||||
gpio: gpio@90000000 {
|
||||
compatible = "lsi,zevio-gpio";
|
||||
reg = <0x90000000 0x1000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
@@ -13,11 +13,11 @@ properties, each containing a 'gpio-list':
|
||||
gpio-specifier : Array of #gpio-cells specifying specific gpio
|
||||
(controller specific)
|
||||
|
||||
GPIO properties should be named "[<name>-]gpios". Exact
|
||||
GPIO properties should be named "[<name>-]gpios". The exact
|
||||
meaning of each gpios property must be documented in the device tree
|
||||
binding for each device.
|
||||
|
||||
For example, the following could be used to describe gpios pins to use
|
||||
For example, the following could be used to describe GPIO pins used
|
||||
as chip select lines; with chip selects 0, 1 and 3 populated, and chip
|
||||
select 2 left empty:
|
||||
|
||||
@@ -44,35 +44,79 @@ 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.
|
||||
|
||||
Example of the node using GPIOs:
|
||||
Example of a node using GPIOs:
|
||||
|
||||
node {
|
||||
gpios = <&qe_pio_e 18 0>;
|
||||
};
|
||||
|
||||
In this example gpio-specifier is "18 0" and encodes GPIO pin number,
|
||||
and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
|
||||
and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
|
||||
|
||||
1.1) GPIO specifier best practices
|
||||
----------------------------------
|
||||
|
||||
A gpio-specifier should contain a flag indicating the GPIO polarity; active-
|
||||
high or active-low. If it does, the follow best practices should be followed:
|
||||
|
||||
The gpio-specifier's polarity flag should represent the physical level at the
|
||||
GPIO controller that achieves (or represents, for inputs) a logically asserted
|
||||
value at the device. The exact definition of logically asserted should be
|
||||
defined by the binding for the device. If the board inverts the signal between
|
||||
the GPIO controller and the device, then the gpio-specifier will represent the
|
||||
opposite physical level than the signal at the device's pin.
|
||||
|
||||
When the device's signal polarity is configurable, the binding for the
|
||||
device must either:
|
||||
|
||||
a) Define a single static polarity for the signal, with the expectation that
|
||||
any software using that binding would statically program the device to use
|
||||
that signal polarity.
|
||||
|
||||
The static choice of polarity may be either:
|
||||
|
||||
a1) (Preferred) Dictated by a binding-specific DT property.
|
||||
|
||||
or:
|
||||
|
||||
a2) Defined statically by the DT binding itself.
|
||||
|
||||
In particular, the polarity cannot be derived from the gpio-specifier, since
|
||||
that would prevent the DT from separately representing the two orthogonal
|
||||
concepts of configurable signal polarity in the device, and possible board-
|
||||
level signal inversion.
|
||||
|
||||
or:
|
||||
|
||||
b) Pick a single option for device signal polarity, and document this choice
|
||||
in the binding. The gpio-specifier should represent the polarity of the signal
|
||||
(at the GPIO controller) assuming that the device is configured for this
|
||||
particular signal polarity choice. If software chooses to program the device
|
||||
to generate or receive a signal of the opposite polarity, software will be
|
||||
responsible for correctly interpreting (inverting) the GPIO signal at the GPIO
|
||||
controller.
|
||||
|
||||
2) gpio-controller nodes
|
||||
------------------------
|
||||
|
||||
Every GPIO controller node must both an empty "gpio-controller"
|
||||
property, and have #gpio-cells contain the size of the gpio-specifier.
|
||||
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.
|
||||
|
||||
Example of two SOC GPIO banks defined as gpio-controller nodes:
|
||||
|
||||
qe_pio_a: gpio-controller@1400 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
|
||||
reg = <0x1400 0x18>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
qe_pio_e: gpio-controller@1460 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
|
||||
reg = <0x1460 0x18>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
2.1) gpio- and pin-controller interaction
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
* Synopsys DesignWare APB GPIO controller
|
||||
|
||||
Required properties:
|
||||
- compatible : Should contain "snps,dw-apb-gpio"
|
||||
- reg : Address and length of the register set for the device.
|
||||
- #address-cells : should be 1 (for addressing port subnodes).
|
||||
- #size-cells : should be 0 (port subnodes).
|
||||
|
||||
The GPIO controller has a configurable number of ports, each of which are
|
||||
represented as child nodes with the following properties:
|
||||
|
||||
Required properties:
|
||||
- compatible : "snps,dw-apb-gpio-port"
|
||||
- gpio-controller : Marks the device node as a gpio controller.
|
||||
- #gpio-cells : Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify the gpio polarity:
|
||||
0 = active high
|
||||
1 = active low
|
||||
- reg : The integer port index of the port, a single cell.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-controller : The first port may be configured to be an interrupt
|
||||
controller.
|
||||
- #interrupt-cells : Specifies the number of cells needed to encode an
|
||||
interrupt. Shall be set to 2. The first cell defines the interrupt number,
|
||||
the second encodes the triger flags encoded as described in
|
||||
Documentation/devicetree/bindings/interrupts.txt
|
||||
- interrupt-parent : The parent interrupt controller.
|
||||
- interrupts : The interrupt to the parent controller raised when GPIOs
|
||||
generate the interrupts.
|
||||
- snps,nr-gpios : The number of pins in the port, a single cell.
|
||||
|
||||
Example:
|
||||
|
||||
gpio: gpio@20000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0x20000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
porta: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
snps,nr-gpios = <8>;
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
|
||||
portb: gpio-controller@1 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
snps,nr-gpios = <8>;
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
@@ -154,6 +154,7 @@ raw line value:
|
||||
void gpiod_set_raw_value(struct gpio_desc *desc, int value)
|
||||
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
|
||||
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
|
||||
int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
|
||||
|
||||
The active-low state of a GPIO can also be queried using the following call:
|
||||
|
||||
|
||||
@@ -62,6 +62,37 @@ 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.
|
||||
|
||||
|
||||
GPIO drivers providing IRQs
|
||||
---------------------------
|
||||
It is custom that GPIO drivers (GPIO chips) are also providing interrupts,
|
||||
most often cascaded off a parent interrupt controller, and in some special
|
||||
cases the GPIO logic is melded with a SoC's primary interrupt controller.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
other.
|
||||
|
||||
gpiod_to_irq() is just a convenience function to figure out the IRQ for a
|
||||
certain GPIO line and should not be relied upon to have been called before
|
||||
the IRQ is used.
|
||||
|
||||
So always prepare the hardware and make it ready for action in respective
|
||||
callbacks from the GPIO and irqchip APIs. Do not rely on gpiod_to_irq() having
|
||||
been called first.
|
||||
|
||||
This orthogonality leads to ambiguities that we need to solve: if there is
|
||||
competition inside the subsystem which side is using the resource (a certain
|
||||
GPIO line and register for example) it needs to deny certain operations and
|
||||
keep track of usage inside of the gpiolib subsystem. This is why the API
|
||||
below exists.
|
||||
|
||||
|
||||
Locking IRQ usage
|
||||
-----------------
|
||||
Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
|
||||
@@ -73,3 +104,7 @@ This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
|
||||
is released:
|
||||
|
||||
void gpiod_unlock_as_irq(struct gpio_desc *desc)
|
||||
|
||||
When implementing an irqchip inside a GPIO driver, these two functions should
|
||||
typically be called in the .startup() and .shutdown() callbacks from the
|
||||
irqchip.
|
||||
|
||||
@@ -1928,6 +1928,13 @@ L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/scsi/bnx2i/
|
||||
|
||||
BROADCOM KONA GPIO DRIVER
|
||||
M: Markus Mayer <markus.mayer@linaro.org>
|
||||
L: bcm-kernel-feedback-list@broadcom.com
|
||||
S: Supported
|
||||
F: drivers/gpio/gpio-bcm-kona.c
|
||||
F: Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
|
||||
|
||||
BROADCOM SPECIFIC AMBA DRIVER (BCMA)
|
||||
M: Rafał Miłecki <zajec5@gmail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
||||
+35
-5
@@ -55,6 +55,9 @@ config GPIO_ACPI
|
||||
def_bool y
|
||||
depends on ACPI
|
||||
|
||||
config GPIOLIB_IRQCHIP
|
||||
bool
|
||||
|
||||
config DEBUG_GPIO
|
||||
bool "Debug GPIO calls"
|
||||
depends on DEBUG_KERNEL
|
||||
@@ -128,6 +131,15 @@ config GPIO_GENERIC_PLATFORM
|
||||
help
|
||||
Say yes here to support basic platform_device memory-mapped GPIO controllers.
|
||||
|
||||
config GPIO_DWAPB
|
||||
tristate "Synopsys DesignWare APB GPIO driver"
|
||||
select GPIO_GENERIC
|
||||
select GENERIC_IRQ_CHIP
|
||||
depends on OF_GPIO
|
||||
help
|
||||
Say Y or M here to build support for the Synopsys DesignWare APB
|
||||
GPIO block.
|
||||
|
||||
config GPIO_IT8761E
|
||||
tristate "IT8761E GPIO support"
|
||||
depends on X86 # unconditional access to IO space.
|
||||
@@ -145,6 +157,12 @@ config GPIO_EP93XX
|
||||
depends on ARCH_EP93XX
|
||||
select GPIO_GENERIC
|
||||
|
||||
config GPIO_ZEVIO
|
||||
bool "LSI ZEVIO SoC memory mapped GPIOs"
|
||||
depends on ARM && OF_GPIO
|
||||
help
|
||||
Say yes here to support the GPIO controller in LSI ZEVIO SoCs.
|
||||
|
||||
config GPIO_MM_LANTIQ
|
||||
bool "Lantiq Memory mapped GPIOs"
|
||||
depends on LANTIQ && SOC_XWAY
|
||||
@@ -228,7 +246,8 @@ config GPIO_OCTEON
|
||||
config GPIO_PL061
|
||||
bool "PrimeCell PL061 GPIO support"
|
||||
depends on ARM_AMBA
|
||||
select GENERIC_IRQ_CHIP
|
||||
select IRQ_DOMAIN
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to support the PrimeCell PL061 GPIO device
|
||||
|
||||
@@ -275,8 +294,15 @@ config GPIO_STA2X11
|
||||
Say yes here to support the STA2x11/ConneXt GPIO device.
|
||||
The GPIO module has 128 GPIO pins with alternate functions.
|
||||
|
||||
config GPIO_SYSCON
|
||||
tristate "GPIO based on SYSCON"
|
||||
depends on MFD_SYSCON && OF
|
||||
help
|
||||
Say yes here to support GPIO functionality though SYSCON driver.
|
||||
|
||||
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
|
||||
@@ -462,7 +488,7 @@ config GPIO_MC9S08DZ60
|
||||
Select this to enable the MC9S08DZ60 GPIO driver
|
||||
|
||||
config GPIO_PCA953X
|
||||
tristate "PCA953x, PCA955x, PCA957x, TCA64xx, and MAX7310 I/O ports"
|
||||
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
|
||||
@@ -472,11 +498,15 @@ config GPIO_PCA953X
|
||||
4 bits: pca9536, pca9537
|
||||
|
||||
8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554,
|
||||
pca9556, pca9557, pca9574, tca6408
|
||||
pca9556, pca9557, pca9574, tca6408, xra1202
|
||||
|
||||
16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575,
|
||||
tca6416
|
||||
|
||||
24 bits: tca6424
|
||||
|
||||
40 bits: pca9505, pca9698
|
||||
|
||||
config GPIO_PCA953X_IRQ
|
||||
bool "Interrupt controller support for PCA953x"
|
||||
depends on GPIO_PCA953X=y
|
||||
@@ -630,7 +660,7 @@ comment "PCI GPIO expanders:"
|
||||
|
||||
config GPIO_CS5535
|
||||
tristate "AMD CS5535/CS5536 GPIO support"
|
||||
depends on PCI && X86 && MFD_CS5535
|
||||
depends on MFD_CS5535
|
||||
help
|
||||
The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
|
||||
can be used for quite a number of things. The CS5535/6 is found on
|
||||
@@ -642,7 +672,7 @@ config GPIO_BT8XX
|
||||
tristate "BT8XX GPIO abuser"
|
||||
depends on PCI && VIDEO_BT848=n
|
||||
help
|
||||
The BT8xx frame grabber chip has 24 GPIO pins than can be abused
|
||||
The BT8xx frame grabber chip has 24 GPIO pins that can be abused
|
||||
as a cheap PCI GPIO card.
|
||||
|
||||
This chip can be found on Miro, Hauppauge and STB TV-cards.
|
||||
|
||||
@@ -23,6 +23,7 @@ obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
|
||||
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
|
||||
obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
|
||||
obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
|
||||
obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o
|
||||
obj-$(CONFIG_GPIO_EM) += gpio-em.o
|
||||
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
|
||||
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
|
||||
@@ -76,11 +77,11 @@ 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
|
||||
obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o
|
||||
obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
|
||||
obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
|
||||
obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o
|
||||
obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
|
||||
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
|
||||
@@ -99,3 +100,4 @@ obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
|
||||
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
|
||||
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
|
||||
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
|
||||
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
|
||||
|
||||
@@ -408,24 +408,23 @@ static void adnp_irq_bus_unlock(struct irq_data *data)
|
||||
mutex_unlock(&adnp->irq_lock);
|
||||
}
|
||||
|
||||
static unsigned int adnp_irq_startup(struct irq_data *data)
|
||||
static int adnp_irq_reqres(struct irq_data *data)
|
||||
{
|
||||
struct adnp *adnp = irq_data_get_irq_chip_data(data);
|
||||
|
||||
if (gpio_lock_as_irq(&adnp->gpio, data->hwirq))
|
||||
if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) {
|
||||
dev_err(adnp->gpio.dev,
|
||||
"unable to lock HW IRQ %lu for IRQ\n",
|
||||
data->hwirq);
|
||||
/* Satisfy the .enable semantics by unmasking the line */
|
||||
adnp_irq_unmask(data);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void adnp_irq_shutdown(struct irq_data *data)
|
||||
static void adnp_irq_relres(struct irq_data *data)
|
||||
{
|
||||
struct adnp *adnp = irq_data_get_irq_chip_data(data);
|
||||
|
||||
adnp_irq_mask(data);
|
||||
gpio_unlock_as_irq(&adnp->gpio, data->hwirq);
|
||||
}
|
||||
|
||||
@@ -436,8 +435,8 @@ static struct irq_chip adnp_irq_chip = {
|
||||
.irq_set_type = adnp_irq_set_type,
|
||||
.irq_bus_lock = adnp_irq_bus_lock,
|
||||
.irq_bus_sync_unlock = adnp_irq_bus_unlock,
|
||||
.irq_startup = adnp_irq_startup,
|
||||
.irq_shutdown = adnp_irq_shutdown,
|
||||
.irq_request_resources = adnp_irq_reqres,
|
||||
.irq_release_resources = adnp_irq_relres,
|
||||
};
|
||||
|
||||
static int adnp_irq_map(struct irq_domain *domain, unsigned int irq,
|
||||
|
||||
@@ -67,9 +67,20 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
|
||||
{
|
||||
struct adp5588_gpio *dev =
|
||||
container_of(chip, struct adp5588_gpio, gpio_chip);
|
||||
unsigned bank = ADP5588_BANK(off);
|
||||
unsigned bit = ADP5588_BIT(off);
|
||||
int val;
|
||||
|
||||
return !!(adp5588_gpio_read(dev->client,
|
||||
GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
if (dev->dir[bank] & bit)
|
||||
val = dev->dat_out[bank];
|
||||
else
|
||||
val = adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + bank);
|
||||
|
||||
mutex_unlock(&dev->lock);
|
||||
|
||||
return !!(val & bit);
|
||||
}
|
||||
|
||||
static void adp5588_gpio_set_value(struct gpio_chip *chip,
|
||||
@@ -386,6 +397,7 @@ static int adp5588_gpio_probe(struct i2c_client *client,
|
||||
gc->ngpio = ADP5588_MAXGPIO;
|
||||
gc->label = client->name;
|
||||
gc->owner = THIS_MODULE;
|
||||
gc->names = pdata->names;
|
||||
|
||||
mutex_init(&dev->lock);
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#define GPIO_BANK(gpio) ((gpio) >> 5)
|
||||
#define GPIO_BIT(gpio) ((gpio) & (GPIO_PER_BANK - 1))
|
||||
|
||||
/* There is a GPIO control register for each GPIO */
|
||||
#define GPIO_CONTROL(gpio) (0x00000100 + ((gpio) << 2))
|
||||
|
||||
/* The remaining registers are per GPIO bank */
|
||||
#define GPIO_OUT_STATUS(bank) (0x00000000 + ((bank) << 2))
|
||||
#define GPIO_IN_STATUS(bank) (0x00000020 + ((bank) << 2))
|
||||
#define GPIO_OUT_SET(bank) (0x00000040 + ((bank) << 2))
|
||||
@@ -35,7 +39,6 @@
|
||||
#define GPIO_INT_STATUS(bank) (0x00000080 + ((bank) << 2))
|
||||
#define GPIO_INT_MASK(bank) (0x000000a0 + ((bank) << 2))
|
||||
#define GPIO_INT_MSKCLR(bank) (0x000000c0 + ((bank) << 2))
|
||||
#define GPIO_CONTROL(bank) (0x00000100 + ((bank) << 2))
|
||||
#define GPIO_PWD_STATUS(bank) (0x00000500 + ((bank) << 2))
|
||||
|
||||
#define GPIO_GPPWR_OFFSET 0x00000520
|
||||
@@ -80,22 +83,43 @@ static inline struct bcm_kona_gpio *to_kona_gpio(struct gpio_chip *chip)
|
||||
return container_of(chip, struct bcm_kona_gpio, gpio_chip);
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_set_lockcode_bank(void __iomem *reg_base,
|
||||
int bank_id, int lockcode)
|
||||
static inline void bcm_kona_gpio_write_lock_regs(void __iomem *reg_base,
|
||||
int bank_id, u32 lockcode)
|
||||
{
|
||||
writel(BCM_GPIO_PASSWD, reg_base + GPIO_GPPWR_OFFSET);
|
||||
writel(lockcode, reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
}
|
||||
|
||||
static inline void bcm_kona_gpio_lock_bank(void __iomem *reg_base, int bank_id)
|
||||
static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
|
||||
unsigned gpio)
|
||||
{
|
||||
bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, LOCK_CODE);
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val |= BIT(gpio);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
static inline void bcm_kona_gpio_unlock_bank(void __iomem *reg_base,
|
||||
int bank_id)
|
||||
static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
|
||||
unsigned gpio)
|
||||
{
|
||||
bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, UNLOCK_CODE);
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val &= ~BIT(gpio);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
@@ -110,7 +134,6 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
kona_gpio = to_kona_gpio(chip);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
/* determine the GPIO pin direction */
|
||||
val = readl(reg_base + GPIO_CONTROL(gpio));
|
||||
@@ -127,7 +150,6 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
|
||||
writel(val, reg_base + reg_offset);
|
||||
|
||||
out:
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
@@ -143,7 +165,6 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
|
||||
kona_gpio = to_kona_gpio(chip);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
/* determine the GPIO pin direction */
|
||||
val = readl(reg_base + GPIO_CONTROL(gpio));
|
||||
@@ -154,32 +175,43 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
|
||||
GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
|
||||
val = readl(reg_base + reg_offset);
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
|
||||
/* return the specified bit status */
|
||||
return !!(val & BIT(bit));
|
||||
}
|
||||
|
||||
static int bcm_kona_gpio_request(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = to_kona_gpio(chip);
|
||||
|
||||
bcm_kona_gpio_unlock_gpio(kona_gpio, gpio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_free(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = to_kona_gpio(chip);
|
||||
|
||||
bcm_kona_gpio_lock_gpio(kona_gpio, gpio);
|
||||
}
|
||||
|
||||
static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio;
|
||||
void __iomem *reg_base;
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
|
||||
kona_gpio = to_kona_gpio(chip);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
val = readl(reg_base + GPIO_CONTROL(gpio));
|
||||
val &= ~GPIO_GPCTR0_IOTR_MASK;
|
||||
val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
|
||||
writel(val, reg_base + GPIO_CONTROL(gpio));
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
@@ -198,7 +230,6 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
|
||||
kona_gpio = to_kona_gpio(chip);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
val = readl(reg_base + GPIO_CONTROL(gpio));
|
||||
val &= ~GPIO_GPCTR0_IOTR_MASK;
|
||||
@@ -210,7 +241,6 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
|
||||
val |= BIT(bit);
|
||||
writel(val, reg_base + reg_offset);
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
@@ -233,7 +263,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
|
||||
void __iomem *reg_base;
|
||||
u32 val, res;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
|
||||
kona_gpio = to_kona_gpio(chip);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
@@ -257,7 +286,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
|
||||
|
||||
/* spin lock for read-modify-write of the GPIO register */
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
val = readl(reg_base + GPIO_CONTROL(gpio));
|
||||
val &= ~GPIO_GPCTR0_DBR_MASK;
|
||||
@@ -272,7 +300,6 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
|
||||
|
||||
writel(val, reg_base + GPIO_CONTROL(gpio));
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
@@ -281,6 +308,8 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
|
||||
static struct gpio_chip template_chip = {
|
||||
.label = "bcm-kona-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.request = bcm_kona_gpio_request,
|
||||
.free = bcm_kona_gpio_free,
|
||||
.direction_input = bcm_kona_gpio_direction_input,
|
||||
.get = bcm_kona_gpio_get,
|
||||
.direction_output = bcm_kona_gpio_direction_output,
|
||||
@@ -294,7 +323,7 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio;
|
||||
void __iomem *reg_base;
|
||||
int gpio = d->hwirq;
|
||||
unsigned gpio = d->hwirq;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
int bit = GPIO_BIT(gpio);
|
||||
u32 val;
|
||||
@@ -303,13 +332,11 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d)
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
val = readl(reg_base + GPIO_INT_STATUS(bank_id));
|
||||
val |= BIT(bit);
|
||||
writel(val, reg_base + GPIO_INT_STATUS(bank_id));
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
@@ -317,7 +344,7 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio;
|
||||
void __iomem *reg_base;
|
||||
int gpio = d->hwirq;
|
||||
unsigned gpio = d->hwirq;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
int bit = GPIO_BIT(gpio);
|
||||
u32 val;
|
||||
@@ -326,13 +353,11 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
val = readl(reg_base + GPIO_INT_MASK(bank_id));
|
||||
val |= BIT(bit);
|
||||
writel(val, reg_base + GPIO_INT_MASK(bank_id));
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
@@ -340,7 +365,7 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio;
|
||||
void __iomem *reg_base;
|
||||
int gpio = d->hwirq;
|
||||
unsigned gpio = d->hwirq;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
int bit = GPIO_BIT(gpio);
|
||||
u32 val;
|
||||
@@ -349,13 +374,11 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
|
||||
val |= BIT(bit);
|
||||
writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
@@ -363,11 +386,10 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio;
|
||||
void __iomem *reg_base;
|
||||
int gpio = d->hwirq;
|
||||
unsigned gpio = d->hwirq;
|
||||
u32 lvl_type;
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
@@ -394,14 +416,12 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
val = readl(reg_base + GPIO_CONTROL(gpio));
|
||||
val &= ~GPIO_GPCTR0_ITR_MASK;
|
||||
val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
|
||||
writel(val, reg_base + GPIO_CONTROL(gpio));
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
@@ -424,7 +444,6 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
*/
|
||||
reg_base = bank->kona_gpio->reg_base;
|
||||
bank_id = bank->id;
|
||||
bcm_kona_gpio_unlock_bank(reg_base, bank_id);
|
||||
|
||||
while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
|
||||
(~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
|
||||
@@ -444,28 +463,26 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
}
|
||||
}
|
||||
|
||||
bcm_kona_gpio_lock_bank(reg_base, bank_id);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static unsigned int bcm_kona_gpio_irq_startup(struct irq_data *d)
|
||||
static int bcm_kona_gpio_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
|
||||
if (gpio_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq))
|
||||
if (gpio_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) {
|
||||
dev_err(kona_gpio->gpio_chip.dev,
|
||||
"unable to lock HW IRQ %lu for IRQ\n",
|
||||
d->hwirq);
|
||||
bcm_kona_gpio_irq_unmask(d);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_irq_shutdown(struct irq_data *d)
|
||||
static void bcm_kona_gpio_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
|
||||
bcm_kona_gpio_irq_mask(d);
|
||||
gpio_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq);
|
||||
}
|
||||
|
||||
@@ -475,8 +492,8 @@ static struct irq_chip bcm_gpio_irq_chip = {
|
||||
.irq_mask = bcm_kona_gpio_irq_mask,
|
||||
.irq_unmask = bcm_kona_gpio_irq_unmask,
|
||||
.irq_set_type = bcm_kona_gpio_irq_set_type,
|
||||
.irq_startup = bcm_kona_gpio_irq_startup,
|
||||
.irq_shutdown = bcm_kona_gpio_irq_shutdown,
|
||||
.irq_request_resources = bcm_kona_gpio_irq_reqres,
|
||||
.irq_release_resources = bcm_kona_gpio_irq_relres,
|
||||
};
|
||||
|
||||
static struct __initconst of_device_id bcm_kona_gpio_of_match[] = {
|
||||
@@ -531,10 +548,12 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
|
||||
reg_base = kona_gpio->reg_base;
|
||||
/* disable interrupts and clear status */
|
||||
for (i = 0; i < kona_gpio->num_bank; i++) {
|
||||
bcm_kona_gpio_unlock_bank(reg_base, i);
|
||||
/* Unlock the entire bank first */
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE);
|
||||
writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
|
||||
writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
|
||||
bcm_kona_gpio_lock_bank(reg_base, i);
|
||||
/* Now re-lock the bank */
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ static int clps711x_gpio_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
bgc->gc.base = id * 8;
|
||||
bgc->gc.owner = THIS_MODULE;
|
||||
platform_set_drvdata(pdev, bgc);
|
||||
|
||||
return gpiochip_add(&bgc->gc);
|
||||
|
||||
@@ -37,6 +37,8 @@ struct davinci_gpio_regs {
|
||||
u32 intstat;
|
||||
};
|
||||
|
||||
typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq);
|
||||
|
||||
#define BINTEN 0x8 /* GPIO Interrupt Per-Bank Enable Register */
|
||||
|
||||
#define chip2controller(chip) \
|
||||
@@ -172,6 +174,27 @@ of_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
static int davinci_gpio_of_xlate(struct gpio_chip *gc,
|
||||
const struct of_phandle_args *gpiospec,
|
||||
u32 *flags)
|
||||
{
|
||||
struct davinci_gpio_controller *chips = dev_get_drvdata(gc->dev);
|
||||
struct davinci_gpio_platform_data *pdata = dev_get_platdata(gc->dev);
|
||||
|
||||
if (gpiospec->args[0] > pdata->ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
if (gc != &chips[gpiospec->args[0] / 32].chip)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags)
|
||||
*flags = gpiospec->args[1];
|
||||
|
||||
return gpiospec->args[0] % 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int davinci_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i, base;
|
||||
@@ -236,6 +259,9 @@ static int davinci_gpio_probe(struct platform_device *pdev)
|
||||
chips[i].chip.ngpio = 32;
|
||||
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
chips[i].chip.of_gpio_n_cells = 2;
|
||||
chips[i].chip.of_xlate = davinci_gpio_of_xlate;
|
||||
chips[i].chip.dev = dev;
|
||||
chips[i].chip.of_node = dev->of_node;
|
||||
#endif
|
||||
spin_lock_init(&chips[i].lock);
|
||||
@@ -413,6 +439,26 @@ static const struct irq_domain_ops davinci_gpio_irq_ops = {
|
||||
.xlate = irq_domain_xlate_onetwocell,
|
||||
};
|
||||
|
||||
static struct irq_chip *davinci_gpio_get_irq_chip(unsigned int irq)
|
||||
{
|
||||
static struct irq_chip_type gpio_unbanked;
|
||||
|
||||
gpio_unbanked = *container_of(irq_get_chip(irq),
|
||||
struct irq_chip_type, chip);
|
||||
|
||||
return &gpio_unbanked.chip;
|
||||
};
|
||||
|
||||
static struct irq_chip *keystone_gpio_get_irq_chip(unsigned int irq)
|
||||
{
|
||||
static struct irq_chip gpio_unbanked;
|
||||
|
||||
gpio_unbanked = *irq_get_chip(irq);
|
||||
return &gpio_unbanked;
|
||||
};
|
||||
|
||||
static const struct of_device_id davinci_gpio_ids[];
|
||||
|
||||
/*
|
||||
* NOTE: for suspend/resume, probably best to make a platform_device with
|
||||
* suspend_late/resume_resume calls hooking into results of the set_wake()
|
||||
@@ -423,7 +469,8 @@ static const struct irq_domain_ops davinci_gpio_irq_ops = {
|
||||
|
||||
static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
{
|
||||
unsigned gpio, irq, bank;
|
||||
unsigned gpio, bank;
|
||||
int irq;
|
||||
struct clk *clk;
|
||||
u32 binten = 0;
|
||||
unsigned ngpio, bank_irq;
|
||||
@@ -433,6 +480,18 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
struct davinci_gpio_platform_data *pdata = dev->platform_data;
|
||||
struct davinci_gpio_regs __iomem *g;
|
||||
struct irq_domain *irq_domain = NULL;
|
||||
const struct of_device_id *match;
|
||||
struct irq_chip *irq_chip;
|
||||
gpio_get_irq_chip_cb_t gpio_get_irq_chip;
|
||||
|
||||
/*
|
||||
* Use davinci_gpio_get_irq_chip by default to handle non DT cases
|
||||
*/
|
||||
gpio_get_irq_chip = davinci_gpio_get_irq_chip;
|
||||
match = of_match_device(of_match_ptr(davinci_gpio_ids),
|
||||
dev);
|
||||
if (match)
|
||||
gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data;
|
||||
|
||||
ngpio = pdata->ngpio;
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
@@ -489,8 +548,6 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
* IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
|
||||
*/
|
||||
if (pdata->gpio_unbanked) {
|
||||
static struct irq_chip_type gpio_unbanked;
|
||||
|
||||
/* pass "bank 0" GPIO IRQs to AINTC */
|
||||
chips[0].chip.to_irq = gpio_to_irq_unbanked;
|
||||
chips[0].gpio_irq = bank_irq;
|
||||
@@ -499,10 +556,9 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
|
||||
/* AINTC handles mask/unmask; GPIO handles triggering */
|
||||
irq = bank_irq;
|
||||
gpio_unbanked = *container_of(irq_get_chip(irq),
|
||||
struct irq_chip_type, chip);
|
||||
gpio_unbanked.chip.name = "GPIO-AINTC";
|
||||
gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked;
|
||||
irq_chip = gpio_get_irq_chip(irq);
|
||||
irq_chip->name = "GPIO-AINTC";
|
||||
irq_chip->irq_set_type = gpio_irq_type_unbanked;
|
||||
|
||||
/* default trigger: both edges */
|
||||
g = gpio2regs(0);
|
||||
@@ -511,7 +567,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
|
||||
/* set the direct IRQs up to use that irqchip */
|
||||
for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) {
|
||||
irq_set_chip(irq, &gpio_unbanked.chip);
|
||||
irq_set_chip(irq, irq_chip);
|
||||
irq_set_handler_data(irq, &chips[gpio / 32]);
|
||||
irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
|
||||
}
|
||||
@@ -554,7 +610,8 @@ done:
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id davinci_gpio_ids[] = {
|
||||
{ .compatible = "ti,dm6441-gpio", },
|
||||
{ .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip},
|
||||
{ .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, davinci_gpio_ids);
|
||||
|
||||
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Jamie Iles
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* All enquiries to support@picochip.com
|
||||
*/
|
||||
#include <linux/basic_mmio_gpio.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define GPIO_SWPORTA_DR 0x00
|
||||
#define GPIO_SWPORTA_DDR 0x04
|
||||
#define GPIO_SWPORTB_DR 0x0c
|
||||
#define GPIO_SWPORTB_DDR 0x10
|
||||
#define GPIO_SWPORTC_DR 0x18
|
||||
#define GPIO_SWPORTC_DDR 0x1c
|
||||
#define GPIO_SWPORTD_DR 0x24
|
||||
#define GPIO_SWPORTD_DDR 0x28
|
||||
#define GPIO_INTEN 0x30
|
||||
#define GPIO_INTMASK 0x34
|
||||
#define GPIO_INTTYPE_LEVEL 0x38
|
||||
#define GPIO_INT_POLARITY 0x3c
|
||||
#define GPIO_INTSTATUS 0x40
|
||||
#define GPIO_PORTA_EOI 0x4c
|
||||
#define GPIO_EXT_PORTA 0x50
|
||||
#define GPIO_EXT_PORTB 0x54
|
||||
#define GPIO_EXT_PORTC 0x58
|
||||
#define GPIO_EXT_PORTD 0x5c
|
||||
|
||||
#define DWAPB_MAX_PORTS 4
|
||||
#define GPIO_EXT_PORT_SIZE (GPIO_EXT_PORTB - GPIO_EXT_PORTA)
|
||||
#define GPIO_SWPORT_DR_SIZE (GPIO_SWPORTB_DR - GPIO_SWPORTA_DR)
|
||||
#define GPIO_SWPORT_DDR_SIZE (GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR)
|
||||
|
||||
struct dwapb_gpio;
|
||||
|
||||
struct dwapb_gpio_port {
|
||||
struct bgpio_chip bgc;
|
||||
bool is_registered;
|
||||
struct dwapb_gpio *gpio;
|
||||
};
|
||||
|
||||
struct dwapb_gpio {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
struct dwapb_gpio_port *ports;
|
||||
unsigned int nr_ports;
|
||||
struct irq_domain *domain;
|
||||
};
|
||||
|
||||
static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
struct dwapb_gpio_port *port = container_of(bgc, struct
|
||||
dwapb_gpio_port, bgc);
|
||||
struct dwapb_gpio *gpio = port->gpio;
|
||||
|
||||
return irq_find_mapping(gpio->domain, offset);
|
||||
}
|
||||
|
||||
static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs)
|
||||
{
|
||||
u32 v = readl(gpio->regs + GPIO_INT_POLARITY);
|
||||
|
||||
if (gpio_get_value(gpio->ports[0].bgc.gc.base + offs))
|
||||
v &= ~BIT(offs);
|
||||
else
|
||||
v |= BIT(offs);
|
||||
|
||||
writel(v, gpio->regs + GPIO_INT_POLARITY);
|
||||
}
|
||||
|
||||
static void dwapb_irq_handler(u32 irq, struct irq_desc *desc)
|
||||
{
|
||||
struct dwapb_gpio *gpio = irq_get_handler_data(irq);
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS);
|
||||
|
||||
while (irq_status) {
|
||||
int hwirq = fls(irq_status) - 1;
|
||||
int gpio_irq = irq_find_mapping(gpio->domain, hwirq);
|
||||
|
||||
generic_handle_irq(gpio_irq);
|
||||
irq_status &= ~BIT(hwirq);
|
||||
|
||||
if ((irq_get_trigger_type(gpio_irq) & IRQ_TYPE_SENSE_MASK)
|
||||
== IRQ_TYPE_EDGE_BOTH)
|
||||
dwapb_toggle_trigger(gpio, hwirq);
|
||||
}
|
||||
|
||||
if (chip->irq_eoi)
|
||||
chip->irq_eoi(irq_desc_get_irq_data(desc));
|
||||
}
|
||||
|
||||
static void dwapb_irq_enable(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d);
|
||||
struct dwapb_gpio *gpio = igc->private;
|
||||
struct bgpio_chip *bgc = &gpio->ports[0].bgc;
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&bgc->lock, flags);
|
||||
val = readl(gpio->regs + GPIO_INTEN);
|
||||
val |= BIT(d->hwirq);
|
||||
writel(val, gpio->regs + GPIO_INTEN);
|
||||
spin_unlock_irqrestore(&bgc->lock, flags);
|
||||
}
|
||||
|
||||
static void dwapb_irq_disable(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d);
|
||||
struct dwapb_gpio *gpio = igc->private;
|
||||
struct bgpio_chip *bgc = &gpio->ports[0].bgc;
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&bgc->lock, flags);
|
||||
val = readl(gpio->regs + GPIO_INTEN);
|
||||
val &= ~BIT(d->hwirq);
|
||||
writel(val, gpio->regs + GPIO_INTEN);
|
||||
spin_unlock_irqrestore(&bgc->lock, flags);
|
||||
}
|
||||
|
||||
static int dwapb_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d);
|
||||
struct dwapb_gpio *gpio = igc->private;
|
||||
struct bgpio_chip *bgc = &gpio->ports[0].bgc;
|
||||
|
||||
if (gpio_lock_as_irq(&bgc->gc, irqd_to_hwirq(d))) {
|
||||
dev_err(gpio->dev, "unable to lock HW IRQ %lu for IRQ\n",
|
||||
irqd_to_hwirq(d));
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwapb_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d);
|
||||
struct dwapb_gpio *gpio = igc->private;
|
||||
struct bgpio_chip *bgc = &gpio->ports[0].bgc;
|
||||
|
||||
gpio_unlock_as_irq(&bgc->gc, irqd_to_hwirq(d));
|
||||
}
|
||||
|
||||
static int dwapb_irq_set_type(struct irq_data *d, u32 type)
|
||||
{
|
||||
struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d);
|
||||
struct dwapb_gpio *gpio = igc->private;
|
||||
struct bgpio_chip *bgc = &gpio->ports[0].bgc;
|
||||
int bit = d->hwirq;
|
||||
unsigned long level, polarity, flags;
|
||||
|
||||
if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
|
||||
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&bgc->lock, flags);
|
||||
level = readl(gpio->regs + GPIO_INTTYPE_LEVEL);
|
||||
polarity = readl(gpio->regs + GPIO_INT_POLARITY);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
level |= BIT(bit);
|
||||
dwapb_toggle_trigger(gpio, bit);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
level |= BIT(bit);
|
||||
polarity |= BIT(bit);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
level |= BIT(bit);
|
||||
polarity &= ~BIT(bit);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
level &= ~BIT(bit);
|
||||
polarity |= BIT(bit);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
level &= ~BIT(bit);
|
||||
polarity &= ~BIT(bit);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(level, gpio->regs + GPIO_INTTYPE_LEVEL);
|
||||
writel(polarity, gpio->regs + GPIO_INT_POLARITY);
|
||||
spin_unlock_irqrestore(&bgc->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
|
||||
struct dwapb_gpio_port *port)
|
||||
{
|
||||
struct gpio_chip *gc = &port->bgc.gc;
|
||||
struct device_node *node = gc->of_node;
|
||||
struct irq_chip_generic *irq_gc;
|
||||
unsigned int hwirq, ngpio = gc->ngpio;
|
||||
struct irq_chip_type *ct;
|
||||
int err, irq;
|
||||
|
||||
irq = irq_of_parse_and_map(node, 0);
|
||||
if (!irq) {
|
||||
dev_warn(gpio->dev, "no irq for bank %s\n",
|
||||
port->bgc.gc.of_node->full_name);
|
||||
return;
|
||||
}
|
||||
|
||||
gpio->domain = irq_domain_add_linear(node, ngpio,
|
||||
&irq_generic_chip_ops, gpio);
|
||||
if (!gpio->domain)
|
||||
return;
|
||||
|
||||
err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 1,
|
||||
"gpio-dwapb", handle_level_irq,
|
||||
IRQ_NOREQUEST, 0,
|
||||
IRQ_GC_INIT_NESTED_LOCK);
|
||||
if (err) {
|
||||
dev_info(gpio->dev, "irq_alloc_domain_generic_chips failed\n");
|
||||
irq_domain_remove(gpio->domain);
|
||||
gpio->domain = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
irq_gc = irq_get_domain_generic_chip(gpio->domain, 0);
|
||||
if (!irq_gc) {
|
||||
irq_domain_remove(gpio->domain);
|
||||
gpio->domain = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
irq_gc->reg_base = gpio->regs;
|
||||
irq_gc->private = gpio;
|
||||
|
||||
ct = irq_gc->chip_types;
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_set_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_set_type = dwapb_irq_set_type;
|
||||
ct->chip.irq_enable = dwapb_irq_enable;
|
||||
ct->chip.irq_disable = dwapb_irq_disable;
|
||||
ct->chip.irq_request_resources = dwapb_irq_reqres;
|
||||
ct->chip.irq_release_resources = dwapb_irq_relres;
|
||||
ct->regs.ack = GPIO_PORTA_EOI;
|
||||
ct->regs.mask = GPIO_INTMASK;
|
||||
|
||||
irq_setup_generic_chip(irq_gc, IRQ_MSK(port->bgc.gc.ngpio),
|
||||
IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
|
||||
|
||||
irq_set_chained_handler(irq, dwapb_irq_handler);
|
||||
irq_set_handler_data(irq, gpio);
|
||||
|
||||
for (hwirq = 0 ; hwirq < ngpio ; hwirq++)
|
||||
irq_create_mapping(gpio->domain, hwirq);
|
||||
|
||||
port->bgc.gc.to_irq = dwapb_gpio_to_irq;
|
||||
}
|
||||
|
||||
static void dwapb_irq_teardown(struct dwapb_gpio *gpio)
|
||||
{
|
||||
struct dwapb_gpio_port *port = &gpio->ports[0];
|
||||
struct gpio_chip *gc = &port->bgc.gc;
|
||||
unsigned int ngpio = gc->ngpio;
|
||||
irq_hw_number_t hwirq;
|
||||
|
||||
if (!gpio->domain)
|
||||
return;
|
||||
|
||||
for (hwirq = 0 ; hwirq < ngpio ; hwirq++)
|
||||
irq_dispose_mapping(irq_find_mapping(gpio->domain, hwirq));
|
||||
|
||||
irq_domain_remove(gpio->domain);
|
||||
gpio->domain = NULL;
|
||||
}
|
||||
|
||||
static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
|
||||
struct device_node *port_np,
|
||||
unsigned int offs)
|
||||
{
|
||||
struct dwapb_gpio_port *port;
|
||||
u32 port_idx, ngpio;
|
||||
void __iomem *dat, *set, *dirout;
|
||||
int err;
|
||||
|
||||
if (of_property_read_u32(port_np, "reg", &port_idx) ||
|
||||
port_idx >= DWAPB_MAX_PORTS) {
|
||||
dev_err(gpio->dev, "missing/invalid port index for %s\n",
|
||||
port_np->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
port = &gpio->ports[offs];
|
||||
port->gpio = gpio;
|
||||
|
||||
if (of_property_read_u32(port_np, "snps,nr-gpios", &ngpio)) {
|
||||
dev_info(gpio->dev, "failed to get number of gpios for %s\n",
|
||||
port_np->full_name);
|
||||
ngpio = 32;
|
||||
}
|
||||
|
||||
dat = gpio->regs + GPIO_EXT_PORTA + (port_idx * GPIO_EXT_PORT_SIZE);
|
||||
set = gpio->regs + GPIO_SWPORTA_DR + (port_idx * GPIO_SWPORT_DR_SIZE);
|
||||
dirout = gpio->regs + GPIO_SWPORTA_DDR +
|
||||
(port_idx * GPIO_SWPORT_DDR_SIZE);
|
||||
|
||||
err = bgpio_init(&port->bgc, gpio->dev, 4, dat, set, NULL, dirout,
|
||||
NULL, false);
|
||||
if (err) {
|
||||
dev_err(gpio->dev, "failed to init gpio chip for %s\n",
|
||||
port_np->full_name);
|
||||
return err;
|
||||
}
|
||||
|
||||
port->bgc.gc.ngpio = ngpio;
|
||||
port->bgc.gc.of_node = port_np;
|
||||
|
||||
/*
|
||||
* Only port A can provide interrupts in all configurations of the IP.
|
||||
*/
|
||||
if (port_idx == 0 &&
|
||||
of_property_read_bool(port_np, "interrupt-controller"))
|
||||
dwapb_configure_irqs(gpio, port);
|
||||
|
||||
err = gpiochip_add(&port->bgc.gc);
|
||||
if (err)
|
||||
dev_err(gpio->dev, "failed to register gpiochip for %s\n",
|
||||
port_np->full_name);
|
||||
else
|
||||
port->is_registered = true;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void dwapb_gpio_unregister(struct dwapb_gpio *gpio)
|
||||
{
|
||||
unsigned int m;
|
||||
|
||||
for (m = 0; m < gpio->nr_ports; ++m)
|
||||
if (gpio->ports[m].is_registered)
|
||||
WARN_ON(gpiochip_remove(&gpio->ports[m].bgc.gc));
|
||||
}
|
||||
|
||||
static int dwapb_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct dwapb_gpio *gpio;
|
||||
struct device_node *np;
|
||||
int err;
|
||||
unsigned int offs = 0;
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
if (!gpio)
|
||||
return -ENOMEM;
|
||||
gpio->dev = &pdev->dev;
|
||||
|
||||
gpio->nr_ports = of_get_child_count(pdev->dev.of_node);
|
||||
if (!gpio->nr_ports) {
|
||||
err = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
gpio->ports = devm_kzalloc(&pdev->dev, gpio->nr_ports *
|
||||
sizeof(*gpio->ports), GFP_KERNEL);
|
||||
if (!gpio->ports) {
|
||||
err = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
gpio->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(gpio->regs)) {
|
||||
err = PTR_ERR(gpio->regs);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
for_each_child_of_node(pdev->dev.of_node, np) {
|
||||
err = dwapb_gpio_add_port(gpio, np, offs++);
|
||||
if (err)
|
||||
goto out_unregister;
|
||||
}
|
||||
platform_set_drvdata(pdev, gpio);
|
||||
|
||||
return 0;
|
||||
|
||||
out_unregister:
|
||||
dwapb_gpio_unregister(gpio);
|
||||
dwapb_irq_teardown(gpio);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dwapb_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dwapb_gpio *gpio = platform_get_drvdata(pdev);
|
||||
|
||||
dwapb_gpio_unregister(gpio);
|
||||
dwapb_irq_teardown(gpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id dwapb_of_match[] = {
|
||||
{ .compatible = "snps,dw-apb-gpio" },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, dwapb_of_match);
|
||||
|
||||
static struct platform_driver dwapb_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "gpio-dwapb",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(dwapb_of_match),
|
||||
},
|
||||
.probe = dwapb_gpio_probe,
|
||||
.remove = dwapb_gpio_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(dwapb_gpio_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jamie Iles");
|
||||
MODULE_DESCRIPTION("Synopsys DesignWare APB GPIO driver");
|
||||
@@ -99,23 +99,23 @@ static void em_gio_irq_enable(struct irq_data *d)
|
||||
em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));
|
||||
}
|
||||
|
||||
static unsigned int em_gio_irq_startup(struct irq_data *d)
|
||||
static int em_gio_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
|
||||
|
||||
if (gpio_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d)))
|
||||
if (gpio_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d))) {
|
||||
dev_err(p->gpio_chip.dev,
|
||||
"unable to lock HW IRQ %lu for IRQ\n",
|
||||
irqd_to_hwirq(d));
|
||||
em_gio_irq_enable(d);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void em_gio_irq_shutdown(struct irq_data *d)
|
||||
static void em_gio_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
|
||||
|
||||
em_gio_irq_disable(d);
|
||||
gpio_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
|
||||
}
|
||||
|
||||
@@ -359,8 +359,8 @@ static int em_gio_probe(struct platform_device *pdev)
|
||||
irq_chip->irq_mask = em_gio_irq_disable;
|
||||
irq_chip->irq_unmask = em_gio_irq_enable;
|
||||
irq_chip->irq_set_type = em_gio_irq_set_type;
|
||||
irq_chip->irq_startup = em_gio_irq_startup;
|
||||
irq_chip->irq_shutdown = em_gio_irq_shutdown;
|
||||
irq_chip->irq_request_resources = em_gio_irq_reqres;
|
||||
irq_chip->irq_release_resources = em_gio_irq_relres;
|
||||
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
|
||||
|
||||
p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
|
||||
|
||||
@@ -139,7 +139,7 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
struct bgpio_chip *bgc = to_bgpio_chip(gc);
|
||||
|
||||
return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio);
|
||||
return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio));
|
||||
}
|
||||
|
||||
static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
@@ -488,7 +488,7 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
|
||||
void __iomem *dirout;
|
||||
void __iomem *dirin;
|
||||
unsigned long sz;
|
||||
unsigned long flags = 0;
|
||||
unsigned long flags = pdev->id_entry->driver_data;
|
||||
int err;
|
||||
struct bgpio_chip *bgc;
|
||||
struct bgpio_pdata *pdata = dev_get_platdata(dev);
|
||||
@@ -519,9 +519,6 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be"))
|
||||
flags |= BGPIOF_BIG_ENDIAN;
|
||||
|
||||
bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);
|
||||
if (!bgc)
|
||||
return -ENOMEM;
|
||||
@@ -531,6 +528,8 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
|
||||
if (pdata) {
|
||||
if (pdata->label)
|
||||
bgc->gc.label = pdata->label;
|
||||
bgc->gc.base = pdata->base;
|
||||
if (pdata->ngpio > 0)
|
||||
bgc->gc.ngpio = pdata->ngpio;
|
||||
@@ -549,9 +548,14 @@ static int bgpio_pdev_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static const struct platform_device_id bgpio_id_table[] = {
|
||||
{ "basic-mmio-gpio", },
|
||||
{ "basic-mmio-gpio-be", },
|
||||
{},
|
||||
{
|
||||
.name = "basic-mmio-gpio",
|
||||
.driver_data = 0,
|
||||
}, {
|
||||
.name = "basic-mmio-gpio-be",
|
||||
.driver_data = BGPIOF_BIG_ENDIAN,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bgpio_id_table);
|
||||
|
||||
|
||||
+57
-13
@@ -62,6 +62,13 @@ struct ichx_desc {
|
||||
/* Max GPIO pins the chipset can have */
|
||||
uint ngpio;
|
||||
|
||||
/* chipset registers */
|
||||
const u8 (*regs)[3];
|
||||
const u8 *reglen;
|
||||
|
||||
/* GPO_BLINK is available on this chipset */
|
||||
bool have_blink;
|
||||
|
||||
/* Whether the chipset has GPIO in GPE0_STS in the PM IO region */
|
||||
bool uses_gpe0;
|
||||
|
||||
@@ -71,6 +78,12 @@ struct ichx_desc {
|
||||
/* Some chipsets have quirks, let these use their own request/get */
|
||||
int (*request)(struct gpio_chip *chip, unsigned offset);
|
||||
int (*get)(struct gpio_chip *chip, unsigned offset);
|
||||
|
||||
/*
|
||||
* Some chipsets don't let reading output values on GPIO_LVL register
|
||||
* this option allows driver caching written output values
|
||||
*/
|
||||
bool use_outlvl_cache;
|
||||
};
|
||||
|
||||
static struct {
|
||||
@@ -82,6 +95,7 @@ static struct {
|
||||
struct ichx_desc *desc; /* Pointer to chipset-specific description */
|
||||
u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */
|
||||
u8 use_gpio; /* Which GPIO groups are usable */
|
||||
int outlvl_cache[3]; /* cached output values */
|
||||
} ichx_priv;
|
||||
|
||||
static int modparam_gpiobase = -1; /* dynamic */
|
||||
@@ -99,13 +113,23 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||
data = ichx_priv.outlvl_cache[reg_nr];
|
||||
else
|
||||
data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
|
||||
if (val)
|
||||
data |= 1 << bit;
|
||||
else
|
||||
data &= ~(1 << bit);
|
||||
ICHX_WRITE(data, ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
tmp = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||
ichx_priv.outlvl_cache[reg_nr] = data;
|
||||
|
||||
tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
if (verify && data != tmp)
|
||||
ret = -EPERM;
|
||||
|
||||
@@ -123,7 +147,11 @@ static int ichx_read_bit(int reg, unsigned nr)
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base);
|
||||
data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
|
||||
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||
data = ichx_priv.outlvl_cache[reg_nr] | data;
|
||||
|
||||
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||
|
||||
@@ -151,7 +179,7 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
|
||||
int val)
|
||||
{
|
||||
/* Disable blink hardware which is available for GPIOs from 0 to 31. */
|
||||
if (nr < 32)
|
||||
if (nr < 32 && ichx_priv.desc->have_blink)
|
||||
ichx_write_bit(GPO_BLINK, nr, 0, 0);
|
||||
|
||||
/* Set GPIO output value. */
|
||||
@@ -266,6 +294,7 @@ static struct ichx_desc ich6_desc = {
|
||||
.uses_gpe0 = true,
|
||||
|
||||
.ngpio = 50,
|
||||
.have_blink = true,
|
||||
};
|
||||
|
||||
/* Intel 3100 */
|
||||
@@ -290,24 +319,38 @@ static struct ichx_desc i3100_desc = {
|
||||
/* ICH7 and ICH8-based */
|
||||
static struct ichx_desc ich7_desc = {
|
||||
.ngpio = 50,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* ICH9-based */
|
||||
static struct ichx_desc ich9_desc = {
|
||||
.ngpio = 61,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* ICH10-based - Consumer/corporate versions have different amount of GPIO */
|
||||
static struct ichx_desc ich10_cons_desc = {
|
||||
.ngpio = 61,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
static struct ichx_desc ich10_corp_desc = {
|
||||
.ngpio = 72,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* Intel 5 series, 6 series, 3400 series, and C200 series */
|
||||
static struct ichx_desc intel5_desc = {
|
||||
.ngpio = 76,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
static int ichx_gpio_request_regions(struct resource *res_base,
|
||||
@@ -318,11 +361,12 @@ static int ichx_gpio_request_regions(struct resource *res_base,
|
||||
if (!res_base || !res_base->start || !res_base->end)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
|
||||
if (!(use_gpio & (1 << i)))
|
||||
continue;
|
||||
if (!request_region(res_base->start + ichx_regs[0][i],
|
||||
ichx_reglen[i], name))
|
||||
if (!request_region(
|
||||
res_base->start + ichx_priv.desc->regs[0][i],
|
||||
ichx_priv.desc->reglen[i], name))
|
||||
goto request_err;
|
||||
}
|
||||
return 0;
|
||||
@@ -332,8 +376,8 @@ request_err:
|
||||
for (i--; i >= 0; i--) {
|
||||
if (!(use_gpio & (1 << i)))
|
||||
continue;
|
||||
release_region(res_base->start + ichx_regs[0][i],
|
||||
ichx_reglen[i]);
|
||||
release_region(res_base->start + ichx_priv.desc->regs[0][i],
|
||||
ichx_priv.desc->reglen[i]);
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -342,11 +386,11 @@ static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
|
||||
if (!(use_gpio & (1 << i)))
|
||||
continue;
|
||||
release_region(res_base->start + ichx_regs[0][i],
|
||||
ichx_reglen[i]);
|
||||
release_region(res_base->start + ichx_priv.desc->regs[0][i],
|
||||
ichx_priv.desc->reglen[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Moorestown platform Langwell chip GPIO driver
|
||||
* Intel MID GPIO driver
|
||||
*
|
||||
* Copyright (c) 2008, 2009, 2013, Intel Corporation.
|
||||
* Copyright (c) 2008-2014 Intel Corporation.
|
||||
*
|
||||
* 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
|
||||
@@ -11,10 +11,6 @@
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* Supports:
|
||||
@@ -235,23 +231,23 @@ static void intel_mid_irq_mask(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static unsigned int intel_mid_irq_startup(struct irq_data *d)
|
||||
static int intel_mid_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
|
||||
|
||||
if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d)))
|
||||
if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) {
|
||||
dev_err(priv->chip.dev,
|
||||
"unable to lock HW IRQ %lu for IRQ\n",
|
||||
irqd_to_hwirq(d));
|
||||
intel_mid_irq_unmask(d);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_mid_irq_shutdown(struct irq_data *d)
|
||||
static void intel_mid_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
|
||||
|
||||
intel_mid_irq_mask(d);
|
||||
gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d));
|
||||
}
|
||||
|
||||
@@ -260,8 +256,8 @@ static struct irq_chip intel_mid_irqchip = {
|
||||
.irq_mask = intel_mid_irq_mask,
|
||||
.irq_unmask = intel_mid_irq_unmask,
|
||||
.irq_set_type = intel_mid_irq_type,
|
||||
.irq_startup = intel_mid_irq_startup,
|
||||
.irq_shutdown = intel_mid_irq_shutdown,
|
||||
.irq_request_resources = intel_mid_irq_reqres,
|
||||
.irq_release_resources = intel_mid_irq_relres,
|
||||
};
|
||||
|
||||
static const struct intel_mid_gpio_ddata gpio_lincroft = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user