2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-17 09:43:59 +08:00

This is the bulk of GPIO changes for the v3.19 series:

- A new API that allows setting more than one GPIO at the
   time. This is implemented for the new descriptor-based
   API only and makes it possible to e.g. toggle a clock and
   data line at the same time, if the hardware can do this
   with a single register write. Both consumers and drivers
   need new calls, and the core will fall back to driving
   individual lines where needed. Implemented for the MPC8xxx
   driver initially.
 - Patched the mdio-mux-gpio and the serial mctrl driver
   that drives modems to use the new multiple-setting API
   to set several signals simultaneously.
 - Get rid of the global GPIO descriptor array, and instead
   allocate descriptors dynamically for each GPIO on a certain
   GPIO chip. This moves us closer to getting rid of the
   limitation of using the global, static GPIO numberspace.
 - New driver and device tree bindings for 74xx ICs.
 - New driver and device tree bindings for the VF610 Vybrid.
 - Support the RCAR r8a7793 and r8a7794.
 - Guidelines for GPIO device tree bindings trying to get
   things a bit more strict with the advent of combined
   device properties.
 - Suspend/resume support for the MVEBU driver.
 - A slew of minor fixes and improvements.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJUjgQ7AAoJEEEQszewGV1zuJ8P+wamlDNhJbsgqXPcSCZZFgeP
 1O22VRYqoo/i8mAzNCRi2h6NogO9Da6rCRhHdH35TsuNzIbusHE+btMukj248qJ7
 WYOf25I0ImyUP8kulogW4/+7lYibRLHnN2BSLuAkApofmxDvODPS1KNWHulcOcxl
 VaVsA8wvFzQO1s1Wjv94ctVfs5rqk7mBfPwk61zHuLeETecmKg0e52p0Uzqlq6gi
 UKi9uK3sjQ7kI/+xa+qDrF9GRwRR22oJfD/9zNj8g94iU9iMs5Oh+Zp3RJcvYUSD
 y5BIb+IY2ATy20ZkijWmeP8LJz6pja+C9Ne7lKM0jkv7geGeHGAoavz0n3oUq4oz
 IvUNz6hCAP9PcxWc5a9FFqqORLWrRew6GmZmJvIkmC9K+3UQcWhkzO3vLpfl6Q9h
 S728XexkIlhxG9NcER21bFXV2dw3z/X9dm5mQ473TqJm+wQmRuYcPRg053NbqMcx
 juvkweCksx8qlpnjo/1QXQcVwFM8kuR7xAlVo7zdMDOU5F8pdxRnsTl0cUdx5cPv
 DKeMRg8+FYcHmIoe/EodemIh7cAZtEpijZNNAr9cDmAjifeBjWhCb+zri5SIc96x
 0jKVTXyY4jnHXBVoA0FIl1d2t54yVjh3PYiu0MjeLJ9tyB+Px/nOxW8FrdlFnPJ/
 oP5WK13c8h3bMkxUzsvL
 =ZAhA
 -----END PGP SIGNATURE-----

Merge tag 'gpio-v3.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull take two of the GPIO updates:
 "Same stuff as last time, now with a fixup patch for the previous
  compile error plus I ran a few extra rounds of compile-testing.

  This is the bulk of GPIO changes for the v3.19 series:

   - A new API that allows setting more than one GPIO at the time.  This
     is implemented for the new descriptor-based API only and makes it
     possible to e.g. toggle a clock and data line at the same time, if
     the hardware can do this with a single register write.  Both
     consumers and drivers need new calls, and the core will fall back
     to driving individual lines where needed.  Implemented for the
     MPC8xxx driver initially

   - Patched the mdio-mux-gpio and the serial mctrl driver that drives
     modems to use the new multiple-setting API to set several signals
     simultaneously

   - Get rid of the global GPIO descriptor array, and instead allocate
     descriptors dynamically for each GPIO on a certain GPIO chip.  This
     moves us closer to getting rid of the limitation of using the
     global, static GPIO numberspace

   - New driver and device tree bindings for 74xx ICs

   - New driver and device tree bindings for the VF610 Vybrid

   - Support the RCAR r8a7793 and r8a7794

   - Guidelines for GPIO device tree bindings trying to get things a bit
     more strict with the advent of combined device properties

   - Suspend/resume support for the MVEBU driver

   - A slew of minor fixes and improvements"

* tag 'gpio-v3.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (33 commits)
  gpio: mcp23s08: fix up compilation error
  gpio: pl061: document gpio-ranges property for bindings file
  gpio: pl061: hook request if gpio-ranges avaiable
  gpio: mcp23s08: Add option to configure IRQ output polarity as active high
  gpio: fix deferred probe detection for legacy API
  serial: mctrl_gpio: use gpiod_set_array function
  mdio-mux-gpio: Use GPIO descriptor interface and new gpiod_set_array function
  gpio: remove const modifier from gpiod_get_direction()
  gpio: remove gpio_descs global array
  gpio: mxs: implement get_direction callback
  gpio: em: Use dynamic allocation of GPIOs
  gpio: Check if base is positive before calling gpio_is_valid()
  gpio: mcp23s08: Add simple IRQ support for SPI devices
  gpio: mcp23s08: request a shared interrupt
  gpio: mcp23s08: Do not free unrequested interrupt
  gpio: rcar: Add r8a7793 and r8a7794 support
  gpio-mpc8xxx: add mpc8xxx_gpio_set_multiple function
  gpiolib: allow simultaneous setting of multiple GPIO outputs
  gpio: mvebu: add suspend/resume support
  gpio: gpio-davinci: remove duplicate check on resource
  ..
This commit is contained in:
Linus Torvalds 2014-12-14 14:05:05 -08:00
commit 980f3c344f
42 changed files with 1165 additions and 161 deletions

View File

@ -0,0 +1,30 @@
* 74XX MMIO GPIO driver
Required properties:
- compatible: Should contain one of the following:
"ti,741g125": for 741G125 (1-bit Input),
"ti,741g174": for 741G74 (1-bit Output),
"ti,742g125": for 742G125 (2-bit Input),
"ti,7474" : for 7474 (2-bit Output),
"ti,74125" : for 74125 (4-bit Input),
"ti,74175" : for 74175 (4-bit Output),
"ti,74365" : for 74365 (6-bit Input),
"ti,74174" : for 74174 (6-bit Output),
"ti,74244" : for 74244 (8-bit Input),
"ti,74273" : for 74273 (8-bit Output),
"ti,741624" : for 741624 (16-bit Input),
"ti,7416374": for 7416374 (16-bit Output).
- reg: Physical base address and length where IC resides.
- 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:
ctrl: gpio@30008004 {
compatible = "ti,74174";
reg = <0x30008004 0x1>;
gpio-controller;
#gpio-cells = <2>;
};

View File

@ -57,6 +57,8 @@ Optional device specific properties:
occurred on. If it is not set, the interrupt are only generated for the
bank they belong to.
On devices with only one interrupt output this property is useless.
- microchip,irq-active-high: Sets the INTPOL flag in the IOCON register. This
configures the IRQ output polarity as active high.
Example I2C (with interrupt):
gpiom1: gpio@20 {

View File

@ -0,0 +1,55 @@
* Freescale VF610 PORT/GPIO module
The Freescale PORT/GPIO modules are two adjacent modules providing GPIO
functionality. Each pair serves 32 GPIOs. The VF610 has 5 instances of
each, and each PORT module has its own interrupt.
Required properties for GPIO node:
- compatible : Should be "fsl,<soc>-gpio", currently "fsl,vf610-gpio"
- reg : The first reg tuple represents the PORT module, the second tuple
the GPIO module.
- interrupts : Should be the port interrupt shared by all 32 pins.
- 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
- interrupt-controller: Marks the device node as an interrupt controller.
- #interrupt-cells : Should be 2. The first cell is the GPIO number.
The second cell bits[3:0] is used to specify trigger type and level flags:
1 = low-to-high edge triggered.
2 = high-to-low edge triggered.
4 = active high level-sensitive.
8 = active low level-sensitive.
Note: Each GPIO port should have an alias correctly numbered in "aliases"
node.
Examples:
aliases {
gpio0 = &gpio1;
gpio1 = &gpio2;
};
gpio1: gpio@40049000 {
compatible = "fsl,vf610-gpio";
reg = <0x40049000 0x1000 0x400ff000 0x40>;
interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-ranges = <&iomuxc 0 0 32>;
};
gpio2: gpio@4004a000 {
compatible = "fsl,vf610-gpio";
reg = <0x4004a000 0x1000 0x400ff040 0x40>;
interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-ranges = <&iomuxc 0 32 32>;
};

View File

@ -13,13 +13,22 @@ properties, each containing a 'gpio-list':
gpio-specifier : Array of #gpio-cells specifying specific gpio
(controller specific)
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.
GPIO properties should be named "[<name>-]gpios", with <name> being the purpose
of this GPIO for the device. While a non-existent <name> is considered valid
for compatibility reasons (resolving to the "gpios" property), it is not allowed
for new bindings.
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:
GPIO properties can contain one or more GPIO phandles, but only in exceptional
cases should they contain more than one. If your device uses several GPIOs with
distinct functions, reference each of them under its own property, giving it a
meaningful name. The only case where an array of GPIOs is accepted is when
several GPIOs serve the same function (e.g. a parallel data line).
The exact purpose of each gpios property must be documented in the device tree
binding of the device.
The following example could be used to describe GPIO pins used as device enable
and bit-banged data signals:
gpio1: gpio1 {
gpio-controller
@ -30,10 +39,12 @@ select 2 left empty:
#gpio-cells = <1>;
};
[...]
chipsel-gpios = <&gpio1 12 0>,
<&gpio1 13 0>,
<0>, /* holes are permitted, means no GPIO 2 */
<&gpio2 2>;
enable-gpios = <&gpio2 2>;
data-gpios = <&gpio1 12 0>,
<&gpio1 13 0>,
<&gpio1 14 0>,
<&gpio1 15 0>;
Note that gpio-specifier length is controller dependent. In the
above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
@ -42,16 +53,17 @@ only uses one.
gpio-specifier may encode: bank, pin position inside the bank,
whether pin is open-drain and whether pin is logically inverted.
Exact meaning of each specifier cell is controller specific, and must
be documented in the device tree binding for the device.
be documented in the device tree binding for the device. Use the macros
defined in include/dt-bindings/gpio/gpio.h whenever possible:
Example of a node using GPIOs:
node {
gpios = <&qe_pio_e 18 0>;
enable-gpios = <&qe_pio_e 18 GPIO_ACTIVE_HIGH>;
};
In this example gpio-specifier is "18 0" and encodes GPIO pin number,
and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes
GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
1.1) GPIO specifier best practices
----------------------------------

View File

@ -7,4 +7,4 @@ Required properties:
- bit 0 specifies polarity (0 for normal, 1 for inverted)
- gpio-controller : Marks the device node as a GPIO controller.
- interrupts : Interrupt mapping for GPIO IRQ.
- gpio-ranges : Interaction with the PINCTRL subsystem.

View File

@ -6,7 +6,9 @@ Required Properties:
- "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller.
- "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller.
- "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller.
- "renesas,gpio-r8a7791": for R8A7791 (R-Car M2) compatible GPIO controller.
- "renesas,gpio-r8a7791": for R8A7791 (R-Car M2-W) compatible GPIO controller.
- "renesas,gpio-r8a7793": for R8A7793 (R-Car M2-N) compatible GPIO controller.
- "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller.
- "renesas,gpio-rcar": for generic R-Car GPIO controller.
- reg: Base address and length of each memory resource used by the GPIO

View File

@ -199,6 +199,33 @@ The active-low state of a GPIO can also be queried using the following call:
Note that these functions should only be used with great moderation ; a driver
should not have to care about the physical line level.
Set multiple GPIO outputs with a single function call
-----------------------------------------------------
The following functions set the output values of an array of GPIOs:
void gpiod_set_array(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
void gpiod_set_raw_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
The array can be an arbitrary set of GPIOs. The functions will try to set
GPIOs belonging to the same bank or chip simultaneously if supported by the
corresponding chip driver. In that case a significantly improved performance
can be expected. If simultaneous setting is not possible the GPIOs will be set
sequentially.
Note that for optimal performance GPIOs belonging to the same chip should be
contiguous within the array of descriptors.
GPIOs mapped to IRQs
--------------------
GPIO lines can quite often be used as IRQs. You can get the IRQ number

View File

@ -158,12 +158,12 @@ Locking IRQ usage
Input GPIOs can be used as IRQ signals. When this happens, a driver is requested
to mark the GPIO as being used as an IRQ:
int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
is released:
void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
When implementing an irqchip inside a GPIO driver, these two functions should
typically be called in the .startup() and .shutdown() callbacks from the

View File

@ -112,6 +112,20 @@ config GPIO_MAX730X
comment "Memory mapped GPIO drivers:"
config GPIO_74XX_MMIO
tristate "GPIO driver for 74xx-ICs with MMIO access"
depends on OF_GPIO
select GPIO_GENERIC
help
Say yes here to support GPIO functionality for 74xx-compatible ICs
with MMIO access. Compatible models include:
1 bit: 741G125 (Input), 741G74 (Output)
2 bits: 742G125 (Input), 7474 (Output)
4 bits: 74125 (Input), 74175 (Output)
6 bits: 74365 (Input), 74174 (Output)
8 bits: 74244 (Input), 74273 (Output)
16 bits: 741624 (Input), 7416374 (Output)
config GPIO_CLPS711X
tristate "CLPS711X GPIO support"
depends on ARCH_CLPS711X || COMPILE_TEST
@ -134,6 +148,8 @@ config GPIO_GENERIC_PLATFORM
config GPIO_DWAPB
tristate "Synopsys DesignWare APB GPIO driver"
depends on ARM
depends on OF_GPIO
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
help
@ -333,6 +349,13 @@ config GPIO_TZ1090_PDC
help
Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
config GPIO_VF610
def_bool y
depends on ARCH_MXC && SOC_VF610
select GPIOLIB_IRQCHIP
help
Say yes here to support Vybrid vf610 GPIOs.
config GPIO_XGENE
bool "APM X-Gene GPIO controller support"
depends on ARM64 && OF_GPIO

View File

@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
@ -96,6 +97,7 @@ obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o
obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o

View File

@ -0,0 +1,170 @@
/*
* 74xx MMIO GPIO driver
*
* Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/basic_mmio_gpio.h>
#include <linux/platform_device.h>
#define MMIO_74XX_DIR_IN (0 << 8)
#define MMIO_74XX_DIR_OUT (1 << 8)
#define MMIO_74XX_BIT_CNT(x) ((x) & 0xff)
struct mmio_74xx_gpio_priv {
struct bgpio_chip bgc;
unsigned flags;
};
static const struct of_device_id mmio_74xx_gpio_ids[] = {
{
.compatible = "ti,741g125",
.data = (const void *)(MMIO_74XX_DIR_IN | 1),
},
{
.compatible = "ti,742g125",
.data = (const void *)(MMIO_74XX_DIR_IN | 2),
},
{
.compatible = "ti,74125",
.data = (const void *)(MMIO_74XX_DIR_IN | 4),
},
{
.compatible = "ti,74365",
.data = (const void *)(MMIO_74XX_DIR_IN | 6),
},
{
.compatible = "ti,74244",
.data = (const void *)(MMIO_74XX_DIR_IN | 8),
},
{
.compatible = "ti,741624",
.data = (const void *)(MMIO_74XX_DIR_IN | 16),
},
{
.compatible = "ti,741g74",
.data = (const void *)(MMIO_74XX_DIR_OUT | 1),
},
{
.compatible = "ti,7474",
.data = (const void *)(MMIO_74XX_DIR_OUT | 2),
},
{
.compatible = "ti,74175",
.data = (const void *)(MMIO_74XX_DIR_OUT | 4),
},
{
.compatible = "ti,74174",
.data = (const void *)(MMIO_74XX_DIR_OUT | 6),
},
{
.compatible = "ti,74273",
.data = (const void *)(MMIO_74XX_DIR_OUT | 8),
},
{
.compatible = "ti,7416374",
.data = (const void *)(MMIO_74XX_DIR_OUT | 16),
},
{ }
};
MODULE_DEVICE_TABLE(of, mmio_74xx_gpio_ids);
static inline struct mmio_74xx_gpio_priv *to_74xx_gpio(struct gpio_chip *gc)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
return container_of(bgc, struct mmio_74xx_gpio_priv, bgc);
}
static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned offset)
{
struct mmio_74xx_gpio_priv *priv = to_74xx_gpio(gc);
return (priv->flags & MMIO_74XX_DIR_OUT) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
}
static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
struct mmio_74xx_gpio_priv *priv = to_74xx_gpio(gc);
return (priv->flags & MMIO_74XX_DIR_OUT) ? -ENOTSUPP : 0;
}
static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct mmio_74xx_gpio_priv *priv = to_74xx_gpio(gc);
if (priv->flags & MMIO_74XX_DIR_OUT) {
gc->set(gc, gpio, val);
return 0;
}
return -ENOTSUPP;
}
static int mmio_74xx_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mmio_74xx_gpio_ids, &pdev->dev);
struct mmio_74xx_gpio_priv *priv;
struct resource *res;
void __iomem *dat;
int err;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dat = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dat))
return PTR_ERR(dat);
priv->flags = (unsigned)of_id->data;
err = bgpio_init(&priv->bgc, &pdev->dev,
DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
dat, NULL, NULL, NULL, NULL, 0);
if (err)
return err;
priv->bgc.gc.direction_input = mmio_74xx_dir_in;
priv->bgc.gc.direction_output = mmio_74xx_dir_out;
priv->bgc.gc.get_direction = mmio_74xx_get_direction;
priv->bgc.gc.ngpio = MMIO_74XX_BIT_CNT(priv->flags);
priv->bgc.gc.owner = THIS_MODULE;
platform_set_drvdata(pdev, priv);
return gpiochip_add(&priv->bgc.gc);
}
static int mmio_74xx_gpio_remove(struct platform_device *pdev)
{
struct mmio_74xx_gpio_priv *priv = platform_get_drvdata(pdev);
return bgpio_remove(&priv->bgc);
}
static struct platform_driver mmio_74xx_gpio_driver = {
.driver = {
.name = "74xx-mmio-gpio",
.of_match_table = mmio_74xx_gpio_ids,
},
.probe = mmio_74xx_gpio_probe,
.remove = mmio_74xx_gpio_remove,
};
module_platform_driver(mmio_74xx_gpio_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
MODULE_DESCRIPTION("74xx MMIO GPIO driver");

View File

@ -223,6 +223,7 @@ found:
if (err) {
printk(KERN_ERR "GPIO registering failed (%d)\n",
err);
ioport_unmap(gp.pm);
release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
goto out;
}

View File

@ -470,7 +470,7 @@ 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 (gpiochip_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);
@ -483,7 +483,7 @@ static void bcm_kona_gpio_irq_relres(struct irq_data *d)
{
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq);
gpiochip_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq);
}
static struct irq_chip bcm_gpio_irq_chip = {

View File

@ -322,7 +322,8 @@ static int cs5535_gpio_probe(struct platform_device *pdev)
goto done;
}
if (!request_region(res->start, resource_size(res), pdev->name)) {
if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
pdev->name)) {
dev_err(&pdev->dev, "can't request region\n");
goto done;
}
@ -348,24 +349,18 @@ static int cs5535_gpio_probe(struct platform_device *pdev)
/* finally, register with the generic GPIO API */
err = gpiochip_add(&cs5535_gpio_chip.chip);
if (err)
goto release_region;
goto done;
return 0;
release_region:
release_region(res->start, resource_size(res));
done:
return err;
}
static int cs5535_gpio_remove(struct platform_device *pdev)
{
struct resource *r;
gpiochip_remove(&cs5535_gpio_chip.chip);
r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));
return 0;
}

View File

@ -234,11 +234,6 @@ static int davinci_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "Invalid memory resource\n");
return -EBUSY;
}
gpio_base = devm_ioremap_resource(dev, res);
if (IS_ERR(gpio_base))
return PTR_ERR(gpio_base);

View File

@ -194,7 +194,7 @@ static int dwapb_irq_reqres(struct irq_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))) {
if (gpiochip_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;
@ -208,7 +208,7 @@ static void dwapb_irq_relres(struct irq_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));
gpiochip_unlock_as_irq(&bgc->gc, irqd_to_hwirq(d));
}
static int dwapb_irq_set_type(struct irq_data *d, u32 type)

View File

@ -103,7 +103,7 @@ 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 (gpiochip_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));
@ -116,7 +116,7 @@ static void em_gio_irq_relres(struct irq_data *d)
{
struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
gpiochip_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d));
}
@ -330,12 +330,7 @@ static int em_gio_probe(struct platform_device *pdev)
goto err0;
}
ret = of_alias_get_id(pdev->dev.of_node, "gpio");
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't get OF id\n");
goto err0;
}
pdata->gpio_base = ret * 32; /* 32 GPIOs per instance */
pdata->gpio_base = -1;
}
gpio_chip = &p->gpio_chip;

View File

@ -441,6 +441,7 @@ static int grgpio_probe(struct platform_device *ofdev)
err = gpiochip_add(gc);
if (err) {
dev_err(&ofdev->dev, "Could not add gpiochip\n");
irq_domain_remove(priv->domain);
return err;
}

View File

@ -65,6 +65,7 @@ struct mcp23s08_ops {
struct mcp23s08 {
u8 addr;
bool irq_active_high;
u16 cache[11];
u16 irq_rise;
@ -444,7 +445,7 @@ static int mcp23s08_irq_reqres(struct irq_data *data)
{
struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
if (gpio_lock_as_irq(&mcp->chip, data->hwirq)) {
if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) {
dev_err(mcp->chip.dev,
"unable to lock HW IRQ %lu for IRQ usage\n",
data->hwirq);
@ -458,7 +459,7 @@ static void mcp23s08_irq_relres(struct irq_data *data)
{
struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
gpio_unlock_as_irq(&mcp->chip, data->hwirq);
gpiochip_unlock_as_irq(&mcp->chip, data->hwirq);
}
static struct irq_chip mcp23s08_irq_chip = {
@ -476,6 +477,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
{
struct gpio_chip *chip = &mcp->chip;
int err, irq, j;
unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED;
mutex_init(&mcp->irq_lock);
@ -484,9 +486,13 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
if (!mcp->irq_domain)
return -ENODEV;
if (mcp->irq_active_high)
irqflags |= IRQF_TRIGGER_HIGH;
else
irqflags |= IRQF_TRIGGER_LOW;
err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
dev_name(chip->dev), mcp);
irqflags, dev_name(chip->dev), mcp);
if (err != 0) {
dev_err(chip->dev, "unable to request IRQ#%d: %d\n",
mcp->irq, err);
@ -514,8 +520,6 @@ static void mcp23s08_irq_teardown(struct mcp23s08 *mcp)
{
unsigned int irq, i;
free_irq(mcp->irq, mcp);
for (i = 0; i < mcp->chip.ngpio; i++) {
irq = irq_find_mapping(mcp->irq_domain, i);
if (irq > 0)
@ -590,6 +594,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
mcp->data = data;
mcp->addr = addr;
mcp->irq_active_high = false;
mcp->chip.direction_input = mcp23s08_direction_input;
mcp->chip.get = mcp23s08_get;
@ -649,14 +654,25 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
goto fail;
mcp->irq_controller = pdata->irq_controller;
if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017))
mirror = pdata->mirror;
if (mcp->irq && mcp->irq_controller) {
mcp->irq_active_high =
of_property_read_bool(mcp->chip.dev->of_node,
"microchip,irq-active-high");
if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) {
if (type == MCP_TYPE_017)
mirror = pdata->mirror;
}
if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror ||
mcp->irq_active_high) {
/* mcp23s17 has IOCON twice, make sure they are in sync */
status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
status |= IOCON_HAEN | (IOCON_HAEN << 8);
status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
if (mcp->irq_active_high)
status |= IOCON_INTPOL | (IOCON_INTPOL << 8);
else
status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
if (mirror)
status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
@ -936,11 +952,14 @@ static int mcp23s08_probe(struct spi_device *spi)
return -ENOMEM;
spi_set_drvdata(spi, data);
spi->irq = irq_of_parse_and_map(spi->dev.of_node, 0);
for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
if (!(spi_present_mask & (1 << addr)))
continue;
chips--;
data->mcp[addr] = &data->chip[chips];
data->mcp[addr]->irq = spi->irq;
status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
0x40 | (addr << 1), type, pdata,
addr);
@ -981,6 +1000,8 @@ static int mcp23s08_remove(struct spi_device *spi)
if (!data->mcp[addr])
continue;
if (spi->irq && data->mcp[addr]->irq_controller)
mcp23s08_irq_teardown(data->mcp[addr]);
gpiochip_remove(&data->mcp[addr]->chip);
}
kfree(data);

View File

@ -105,6 +105,32 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
unsigned long flags;
int i;
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
for (i = 0; i < gc->ngpio; i++) {
if (*mask == 0)
break;
if (__test_and_clear_bit(i, mask)) {
if (test_bit(i, bits))
mpc8xxx_gc->data |= mpc8xxx_gpio2mask(i);
else
mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(i);
}
}
out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
}
static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
@ -344,6 +370,7 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
mpc8572_gpio_get : mpc8xxx_gpio_get;
gc->set = mpc8xxx_gpio_set;
gc->set_multiple = mpc8xxx_gpio_set_multiple;
gc->to_irq = mpc8xxx_gpio_to_irq;
ret = of_mm_gpiochip_add(np, mm_gc);

View File

@ -83,6 +83,14 @@ struct mvebu_gpio_chip {
int irqbase;
struct irq_domain *domain;
int soc_variant;
/* Used to preserve GPIO registers accross suspend/resume */
u32 out_reg;
u32 io_conf_reg;
u32 blink_en_reg;
u32 in_pol_reg;
u32 edge_mask_regs[4];
u32 level_mask_regs[4];
};
/*
@ -554,6 +562,93 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
};
MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
{
struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
int i;
mvchip->out_reg = readl(mvebu_gpioreg_out(mvchip));
mvchip->io_conf_reg = readl(mvebu_gpioreg_io_conf(mvchip));
mvchip->blink_en_reg = readl(mvebu_gpioreg_blink(mvchip));
mvchip->in_pol_reg = readl(mvebu_gpioreg_in_pol(mvchip));
switch (mvchip->soc_variant) {
case MVEBU_GPIO_SOC_VARIANT_ORION:
mvchip->edge_mask_regs[0] =
readl(mvchip->membase + GPIO_EDGE_MASK_OFF);
mvchip->level_mask_regs[0] =
readl(mvchip->membase + GPIO_LEVEL_MASK_OFF);
break;
case MVEBU_GPIO_SOC_VARIANT_MV78200:
for (i = 0; i < 2; i++) {
mvchip->edge_mask_regs[i] =
readl(mvchip->membase +
GPIO_EDGE_MASK_MV78200_OFF(i));
mvchip->level_mask_regs[i] =
readl(mvchip->membase +
GPIO_LEVEL_MASK_MV78200_OFF(i));
}
break;
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
for (i = 0; i < 4; i++) {
mvchip->edge_mask_regs[i] =
readl(mvchip->membase +
GPIO_EDGE_MASK_ARMADAXP_OFF(i));
mvchip->level_mask_regs[i] =
readl(mvchip->membase +
GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
}
break;
default:
BUG();
}
return 0;
}
static int mvebu_gpio_resume(struct platform_device *pdev)
{
struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev);
int i;
writel(mvchip->out_reg, mvebu_gpioreg_out(mvchip));
writel(mvchip->io_conf_reg, mvebu_gpioreg_io_conf(mvchip));
writel(mvchip->blink_en_reg, mvebu_gpioreg_blink(mvchip));
writel(mvchip->in_pol_reg, mvebu_gpioreg_in_pol(mvchip));
switch (mvchip->soc_variant) {
case MVEBU_GPIO_SOC_VARIANT_ORION:
writel(mvchip->edge_mask_regs[0],
mvchip->membase + GPIO_EDGE_MASK_OFF);
writel(mvchip->level_mask_regs[0],
mvchip->membase + GPIO_LEVEL_MASK_OFF);
break;
case MVEBU_GPIO_SOC_VARIANT_MV78200:
for (i = 0; i < 2; i++) {
writel(mvchip->edge_mask_regs[i],
mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(i));
writel(mvchip->level_mask_regs[i],
mvchip->membase +
GPIO_LEVEL_MASK_MV78200_OFF(i));
}
break;
case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
for (i = 0; i < 4; i++) {
writel(mvchip->edge_mask_regs[i],
mvchip->membase +
GPIO_EDGE_MASK_ARMADAXP_OFF(i));
writel(mvchip->level_mask_regs[i],
mvchip->membase +
GPIO_LEVEL_MASK_ARMADAXP_OFF(i));
}
break;
default:
BUG();
}
return 0;
}
static int mvebu_gpio_probe(struct platform_device *pdev)
{
struct mvebu_gpio_chip *mvchip;
@ -577,6 +672,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
if (!mvchip)
return -ENOMEM;
platform_set_drvdata(pdev, mvchip);
if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
dev_err(&pdev->dev, "Missing ngpios OF property\n");
return -ENODEV;
@ -735,5 +832,7 @@ static struct platform_driver mvebu_gpio_driver = {
.of_match_table = mvebu_gpio_of_match,
},
.probe = mvebu_gpio_probe,
.suspend = mvebu_gpio_suspend,
.resume = mvebu_gpio_resume,
};
module_platform_driver(mvebu_gpio_driver);

View File

@ -227,6 +227,18 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return irq_find_mapping(port->domain, offset);
}
static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
struct mxs_gpio_port *port =
container_of(bgc, struct mxs_gpio_port, bgc);
u32 mask = 1 << offset;
u32 dir;
dir = readl(port->base + PINCTRL_DOE(port));
return !(dir & mask);
}
static struct platform_device_id mxs_gpio_ids[] = {
{
.name = "imx23-gpio",
@ -320,6 +332,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
goto out_irqdesc_free;
port->bgc.gc.to_irq = mxs_gpio_to_irq;
port->bgc.gc.get_direction = mxs_gpio_get_direction;
port->bgc.gc.base = port->id * 32;
err = gpiochip_add(&port->bgc.gc);

View File

@ -800,7 +800,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
unsigned offset = GPIO_INDEX(bank, gpio);
spin_lock_irqsave(&bank->lock, flags);
gpio_unlock_as_irq(&bank->chip, offset);
gpiochip_unlock_as_irq(&bank->chip, offset);
bank->irq_usage &= ~(BIT(offset));
omap_disable_gpio_module(bank, offset);
omap_reset_gpio(bank, gpio);

View File

@ -52,28 +52,34 @@ struct pl061_gpio {
void __iomem *base;
struct gpio_chip gc;
bool uses_pinctrl;
#ifdef CONFIG_PM
struct pl061_context_save_regs csave_regs;
#endif
};
static int pl061_gpio_request(struct gpio_chip *chip, unsigned offset)
static int pl061_gpio_request(struct gpio_chip *gc, unsigned offset)
{
/*
* Map back to global GPIO space and request muxing, the direction
* parameter does not matter for this controller.
*/
int gpio = chip->base + offset;
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
int gpio = gc->base + offset;
return pinctrl_request_gpio(gpio);
if (chip->uses_pinctrl)
return pinctrl_request_gpio(gpio);
return 0;
}
static void pl061_gpio_free(struct gpio_chip *chip, unsigned offset)
static void pl061_gpio_free(struct gpio_chip *gc, unsigned offset)
{
int gpio = chip->base + offset;
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
int gpio = gc->base + offset;
pinctrl_free_gpio(gpio);
if (chip->uses_pinctrl)
pinctrl_free_gpio(gpio);
}
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
@ -263,6 +269,8 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(chip->base);
spin_lock_init(&chip->lock);
if (of_property_read_bool(dev->of_node, "gpio-ranges"))
chip->uses_pinctrl = true;
chip->gc.request = pl061_gpio_request;
chip->gc.free = pl061_gpio_free;

View File

@ -1,6 +1,7 @@
/*
* Renesas R-Car GPIO Support
*
* Copyright (C) 2014 Renesas Electronics Corporation
* Copyright (C) 2013 Magnus Damm
*
* This program is free software; you can redistribute it and/or modify
@ -291,22 +292,30 @@ struct gpio_rcar_info {
bool has_both_edge_trigger;
};
static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
.has_both_edge_trigger = false,
};
static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
.has_both_edge_trigger = true,
};
static const struct of_device_id gpio_rcar_of_table[] = {
{
.compatible = "renesas,gpio-r8a7790",
.data = (void *)&(const struct gpio_rcar_info) {
.has_both_edge_trigger = true,
},
.data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-r8a7791",
.data = (void *)&(const struct gpio_rcar_info) {
.has_both_edge_trigger = true,
},
.data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-r8a7793",
.data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-r8a7794",
.data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-rcar",
.data = (void *)&(const struct gpio_rcar_info) {
.has_both_edge_trigger = false,
},
.data = &gpio_rcar_info_gen1,
}, {
/* Terminator */
},

View File

@ -199,21 +199,17 @@ static int xway_stp_hw_init(struct xway_stp *chip)
static int xway_stp_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *res;
const __be32 *shadow, *groups, *dsl, *phy;
struct xway_stp *chip;
struct clk *clk;
int ret = 0;
if (!res) {
dev_err(&pdev->dev, "failed to request STP resource\n");
return -ENOENT;
}
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
chip->virt = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(chip->virt))
return PTR_ERR(chip->virt);

View File

@ -195,18 +195,13 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
if (of_property_read_u32(dn, "abilis,ngpio", &ngpio))
return -EINVAL;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "No memory resource defined.\n");
return -EINVAL;
}
tb10x_gpio = devm_kzalloc(&pdev->dev, sizeof(*tb10x_gpio), GFP_KERNEL);
if (tb10x_gpio == NULL)
return -ENOMEM;
spin_lock_init(&tb10x_gpio->spinlock);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tb10x_gpio->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(tb10x_gpio->base))
return PTR_ERR(tb10x_gpio->base);

View File

@ -233,7 +233,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
ret = gpio_lock_as_irq(&tegra_gpio_chip, gpio);
ret = gpiochip_lock_as_irq(&tegra_gpio_chip, gpio);
if (ret) {
dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio);
return ret;
@ -263,7 +263,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d)
{
int gpio = d->hwirq;
gpio_unlock_as_irq(&tegra_gpio_chip, gpio);
gpiochip_unlock_as_irq(&tegra_gpio_chip, gpio);
}
static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)

295
drivers/gpio/gpio-vf610.c Normal file
View File

@ -0,0 +1,295 @@
/*
* vf610 GPIO support through PORT and GPIO module
*
* Copyright (c) 2014 Toradex AG.
*
* Author: Stefan Agner <stefan@agner.ch>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#define VF610_GPIO_PER_PORT 32
struct vf610_gpio_port {
struct gpio_chip gc;
void __iomem *base;
void __iomem *gpio_base;
u8 irqc[VF610_GPIO_PER_PORT];
int irq;
};
#define GPIO_PDOR 0x00
#define GPIO_PSOR 0x04
#define GPIO_PCOR 0x08
#define GPIO_PTOR 0x0c
#define GPIO_PDIR 0x10
#define PORT_PCR(n) ((n) * 0x4)
#define PORT_PCR_IRQC_OFFSET 16
#define PORT_ISFR 0xa0
#define PORT_DFER 0xc0
#define PORT_DFCR 0xc4
#define PORT_DFWR 0xc8
#define PORT_INT_OFF 0x0
#define PORT_INT_LOGIC_ZERO 0x8
#define PORT_INT_RISING_EDGE 0x9
#define PORT_INT_FALLING_EDGE 0xa
#define PORT_INT_EITHER_EDGE 0xb
#define PORT_INT_LOGIC_ONE 0xc
static const struct of_device_id vf610_gpio_dt_ids[] = {
{ .compatible = "fsl,vf610-gpio" },
{ /* sentinel */ }
};
static inline void vf610_gpio_writel(u32 val, void __iomem *reg)
{
writel_relaxed(val, reg);
}
static inline u32 vf610_gpio_readl(void __iomem *reg)
{
return readl_relaxed(reg);
}
static int vf610_gpio_request(struct gpio_chip *chip, unsigned offset)
{
return pinctrl_request_gpio(chip->base + offset);
}
static void vf610_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(chip->base + offset);
}
static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct vf610_gpio_port *port =
container_of(gc, struct vf610_gpio_port, gc);
return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio));
}
static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct vf610_gpio_port *port =
container_of(gc, struct vf610_gpio_port, gc);
unsigned long mask = BIT(gpio);
if (val)
vf610_gpio_writel(mask, port->gpio_base + GPIO_PSOR);
else
vf610_gpio_writel(mask, port->gpio_base + GPIO_PCOR);
}
static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
return pinctrl_gpio_direction_input(chip->base + gpio);
}
static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
int value)
{
vf610_gpio_set(chip, gpio, value);
return pinctrl_gpio_direction_output(chip->base + gpio);
}
static void vf610_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
struct vf610_gpio_port *port = irq_get_handler_data(irq);
struct irq_chip *chip = irq_desc_get_chip(desc);
int pin;
unsigned long irq_isfr;
chained_irq_enter(chip, desc);
irq_isfr = vf610_gpio_readl(port->base + PORT_ISFR);
for_each_set_bit(pin, &irq_isfr, VF610_GPIO_PER_PORT) {
vf610_gpio_writel(BIT(pin), port->base + PORT_ISFR);
generic_handle_irq(irq_find_mapping(port->gc.irqdomain, pin));
}
chained_irq_exit(chip, desc);
}
static void vf610_gpio_irq_ack(struct irq_data *d)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
int gpio = d->hwirq;
vf610_gpio_writel(BIT(gpio), port->base + PORT_ISFR);
}
static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
u8 irqc;
switch (type) {
case IRQ_TYPE_EDGE_RISING:
irqc = PORT_INT_RISING_EDGE;
break;
case IRQ_TYPE_EDGE_FALLING:
irqc = PORT_INT_FALLING_EDGE;
break;
case IRQ_TYPE_EDGE_BOTH:
irqc = PORT_INT_EITHER_EDGE;
break;
case IRQ_TYPE_LEVEL_LOW:
irqc = PORT_INT_LOGIC_ZERO;
break;
case IRQ_TYPE_LEVEL_HIGH:
irqc = PORT_INT_LOGIC_ONE;
break;
default:
return -EINVAL;
}
port->irqc[d->hwirq] = irqc;
return 0;
}
static void vf610_gpio_irq_mask(struct irq_data *d)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
vf610_gpio_writel(0, pcr_base);
}
static void vf610_gpio_irq_unmask(struct irq_data *d)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
vf610_gpio_writel(port->irqc[d->hwirq] << PORT_PCR_IRQC_OFFSET,
pcr_base);
}
static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable)
{
struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
if (enable)
enable_irq_wake(port->irq);
else
disable_irq_wake(port->irq);
return 0;
}
static struct irq_chip vf610_gpio_irq_chip = {
.name = "gpio-vf610",
.irq_ack = vf610_gpio_irq_ack,
.irq_mask = vf610_gpio_irq_mask,
.irq_unmask = vf610_gpio_irq_unmask,
.irq_set_type = vf610_gpio_irq_set_type,
.irq_set_wake = vf610_gpio_irq_set_wake,
};
static int vf610_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct vf610_gpio_port *port;
struct resource *iores;
struct gpio_chip *gc;
int ret;
port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->base = devm_ioremap_resource(dev, iores);
if (IS_ERR(port->base))
return PTR_ERR(port->base);
iores = platform_get_resource(pdev, IORESOURCE_MEM, 1);
port->gpio_base = devm_ioremap_resource(dev, iores);
if (IS_ERR(port->gpio_base))
return PTR_ERR(port->gpio_base);
port->irq = platform_get_irq(pdev, 0);
if (port->irq < 0)
return port->irq;
gc = &port->gc;
gc->of_node = np;
gc->dev = dev;
gc->label = "vf610-gpio",
gc->ngpio = VF610_GPIO_PER_PORT,
gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT;
gc->request = vf610_gpio_request,
gc->free = vf610_gpio_free,
gc->direction_input = vf610_gpio_direction_input,
gc->get = vf610_gpio_get,
gc->direction_output = vf610_gpio_direction_output,
gc->set = vf610_gpio_set,
ret = gpiochip_add(gc);
if (ret < 0)
return ret;
/* Clear the interrupt status register for all GPIO's */
vf610_gpio_writel(~0, port->base + PORT_ISFR);
ret = gpiochip_irqchip_add(gc, &vf610_gpio_irq_chip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "failed to add irqchip\n");
gpiochip_remove(gc);
return ret;
}
gpiochip_set_chained_irqchip(gc, &vf610_gpio_irq_chip, port->irq,
vf610_gpio_irq_handler);
return 0;
}
static struct platform_driver vf610_gpio_driver = {
.driver = {
.name = "gpio-vf610",
.owner = THIS_MODULE,
.of_match_table = vf610_gpio_dt_ids,
},
.probe = vf610_gpio_probe,
};
static int __init gpio_vf610_init(void)
{
return platform_driver_register(&vf610_gpio_driver);
}
device_initcall(gpio_vf610_init);
MODULE_AUTHOR("Stefan Agner <stefan@agner.ch>");
MODULE_DESCRIPTION("Freescale VF610 GPIO");
MODULE_LICENSE("GPL v2");

View File

@ -138,7 +138,7 @@ static void unmask_giuint_low(struct irq_data *d)
static unsigned int startup_giuint(struct irq_data *data)
{
if (gpio_lock_as_irq(&vr41xx_gpio_chip, data->hwirq))
if (gpiochip_lock_as_irq(&vr41xx_gpio_chip, data->hwirq))
dev_err(vr41xx_gpio_chip.dev,
"unable to lock HW IRQ %lu for IRQ\n",
data->hwirq);
@ -150,7 +150,7 @@ static unsigned int startup_giuint(struct irq_data *data)
static void shutdown_giuint(struct irq_data *data)
{
mask_giuint_low(data);
gpio_unlock_as_irq(&vr41xx_gpio_chip, data->hwirq);
gpiochip_unlock_as_irq(&vr41xx_gpio_chip, data->hwirq);
}
static struct irq_chip giuint_low_irq_chip = {

View File

@ -209,7 +209,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
gpiod_direction_input(desc);
ret = gpio_lock_as_irq(chip, pin);
ret = gpiochip_lock_as_irq(chip, pin);
if (ret) {
dev_err(chip->dev, "Failed to lock GPIO as interrupt\n");
goto fail_free_desc;
@ -265,7 +265,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
fail_free_event:
kfree(event);
fail_unlock_irq:
gpio_unlock_as_irq(chip, pin);
gpiochip_unlock_as_irq(chip, pin);
fail_free_desc:
gpiochip_free_own_desc(desc);
@ -336,7 +336,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
desc = event->desc;
if (WARN_ON(IS_ERR(desc)))
continue;
gpio_unlock_as_irq(chip, event->pin);
gpiochip_unlock_as_irq(chip, event->pin);
gpiochip_free_own_desc(desc);
list_del(&event->node);
kfree(event);

View File

@ -24,6 +24,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
desc = gpio_to_desc(gpio);
/* Compatibility: assume unavailable "valid" GPIOs will appear later */
if (!desc && gpio_is_valid(gpio))
return -EPROBE_DEFER;
err = gpiod_request(desc, label);
if (err)
return err;
@ -62,7 +66,13 @@ EXPORT_SYMBOL_GPL(gpio_request_one);
int gpio_request(unsigned gpio, const char *label)
{
return gpiod_request(gpio_to_desc(gpio), label);
struct gpio_desc *desc = gpio_to_desc(gpio);
/* Compatibility: assume unavailable "valid" GPIOs will appear later */
if (!desc && gpio_is_valid(gpio))
return -EPROBE_DEFER;
return gpiod_request(desc, label);
}
EXPORT_SYMBOL_GPL(gpio_request);

View File

@ -41,7 +41,7 @@ static DEFINE_MUTEX(sysfs_lock);
static ssize_t gpio_direction_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
@ -161,7 +161,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
desc->flags &= ~GPIO_TRIGGER_MASK;
if (!gpio_flags) {
gpio_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
ret = 0;
goto free_id;
}
@ -200,7 +200,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
if (ret < 0)
goto free_id;
ret = gpio_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
ret = gpiochip_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
if (ret < 0) {
gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
goto free_id;

View File

@ -47,8 +47,6 @@
*/
DEFINE_SPINLOCK(gpio_lock);
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
#define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
static DEFINE_MUTEX(gpio_lookup_lock);
@ -65,10 +63,24 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
*/
struct gpio_desc *gpio_to_desc(unsigned gpio)
{
if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))
return NULL;
else
return &gpio_desc[gpio];
struct gpio_chip *chip;
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(chip, &gpio_chips, list) {
if (chip->base <= gpio && chip->base + chip->ngpio > gpio) {
spin_unlock_irqrestore(&gpio_lock, flags);
return &chip->desc[gpio - chip->base];
}
}
spin_unlock_irqrestore(&gpio_lock, flags);
if (!gpio_is_valid(gpio))
WARN(1, "invalid GPIO %d\n", gpio);
return NULL;
}
EXPORT_SYMBOL_GPL(gpio_to_desc);
@ -91,7 +103,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
*/
int desc_to_gpio(const struct gpio_desc *desc)
{
return desc - &gpio_desc[0];
return desc->chip->base + (desc - &desc->chip->desc[0]);
}
EXPORT_SYMBOL_GPL(desc_to_gpio);
@ -138,7 +150,7 @@ static int gpiochip_find_base(int ngpio)
*
* This function may sleep if gpiod_cansleep() is true.
*/
int gpiod_get_direction(const struct gpio_desc *desc)
int gpiod_get_direction(struct gpio_desc *desc)
{
struct gpio_chip *chip;
unsigned offset;
@ -154,13 +166,11 @@ int gpiod_get_direction(const struct gpio_desc *desc)
if (status > 0) {
/* GPIOF_DIR_IN, or other positive */
status = 1;
/* FLAG_IS_OUT is just a cache of the result of get_direction(),
* so it does not affect constness per se */
clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
clear_bit(FLAG_IS_OUT, &desc->flags);
}
if (status == 0) {
/* GPIOF_DIR_OUT */
set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
set_bit(FLAG_IS_OUT, &desc->flags);
}
return status;
}
@ -206,7 +216,7 @@ static int gpiochip_add_to_list(struct gpio_chip *chip)
/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
* Context: potentially before irqs or kmalloc will work
* Context: potentially before irqs will work
*
* Returns a negative errno if the chip can't be registered, such as
* because the chip->base is invalid or already associated with a
@ -226,12 +236,11 @@ int gpiochip_add(struct gpio_chip *chip)
int status = 0;
unsigned id;
int base = chip->base;
struct gpio_desc *descs;
if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
&& base >= 0) {
status = -EINVAL;
goto fail;
}
descs = kcalloc(chip->ngpio, sizeof(descs[0]), GFP_KERNEL);
if (!descs)
return -ENOMEM;
spin_lock_irqsave(&gpio_lock, flags);
@ -247,10 +256,8 @@ int gpiochip_add(struct gpio_chip *chip)
status = gpiochip_add_to_list(chip);
if (status == 0) {
chip->desc = &gpio_desc[chip->base];
for (id = 0; id < chip->ngpio; id++) {
struct gpio_desc *desc = &chip->desc[id];
struct gpio_desc *desc = &descs[id];
desc->chip = chip;
/* REVISIT: most hardware initializes GPIOs as
@ -266,6 +273,8 @@ int gpiochip_add(struct gpio_chip *chip)
}
}
chip->desc = descs;
spin_unlock_irqrestore(&gpio_lock, flags);
#ifdef CONFIG_PINCTRL
@ -291,6 +300,9 @@ int gpiochip_add(struct gpio_chip *chip)
unlock:
spin_unlock_irqrestore(&gpio_lock, flags);
fail:
kfree(descs);
chip->desc = NULL;
/* failures here can mean systems won't boot... */
pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__,
chip->base, chip->base + chip->ngpio - 1,
@ -331,6 +343,9 @@ void gpiochip_remove(struct gpio_chip *chip)
list_del(&chip->list);
spin_unlock_irqrestore(&gpio_lock, flags);
gpiochip_unexport(chip);
kfree(chip->desc);
chip->desc = NULL;
}
EXPORT_SYMBOL_GPL(gpiochip_remove);
@ -495,7 +510,7 @@ static int gpiochip_irq_reqres(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
if (gpio_lock_as_irq(chip, d->hwirq)) {
if (gpiochip_lock_as_irq(chip, d->hwirq)) {
chip_err(chip,
"unable to lock HW IRQ %lu for IRQ\n",
d->hwirq);
@ -508,7 +523,7 @@ static void gpiochip_irq_relres(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(chip, d->hwirq);
gpiochip_unlock_as_irq(chip, d->hwirq);
}
static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
@ -1254,6 +1269,88 @@ static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value)
chip->set(chip, gpio_chip_hwgpio(desc), value);
}
/*
* set multiple outputs on the same chip;
* use the chip's set_multiple function if available;
* otherwise set the outputs sequentially;
* @mask: bit mask array; one bit per output; BITS_PER_LONG bits per word
* defines which outputs are to be changed
* @bits: bit value array; one bit per output; BITS_PER_LONG bits per word
* defines the values the outputs specified by mask are to be set to
*/
static void gpio_chip_set_multiple(struct gpio_chip *chip,
unsigned long *mask, unsigned long *bits)
{
if (chip->set_multiple) {
chip->set_multiple(chip, mask, bits);
} else {
int i;
for (i = 0; i < chip->ngpio; i++) {
if (mask[BIT_WORD(i)] == 0) {
/* no more set bits in this mask word;
* skip ahead to the next word */
i = (BIT_WORD(i) + 1) * BITS_PER_LONG - 1;
continue;
}
/* set outputs if the corresponding mask bit is set */
if (__test_and_clear_bit(i, mask)) {
chip->set(chip, i, test_bit(i, bits));
}
}
}
}
static void gpiod_set_array_priv(bool raw, bool can_sleep,
unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
{
int i = 0;
while (i < array_size) {
struct gpio_chip *chip = desc_array[i]->chip;
unsigned long mask[BITS_TO_LONGS(chip->ngpio)];
unsigned long bits[BITS_TO_LONGS(chip->ngpio)];
int count = 0;
if (!can_sleep) {
WARN_ON(chip->can_sleep);
}
memset(mask, 0, sizeof(mask));
do {
struct gpio_desc *desc = desc_array[i];
int hwgpio = gpio_chip_hwgpio(desc);
int value = value_array[i];
if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;
trace_gpio_value(desc_to_gpio(desc), 0, value);
/*
* collect all normal outputs belonging to the same chip
* open drain and open source outputs are set individually
*/
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
_gpio_set_open_drain_value(desc,value);
} else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
_gpio_set_open_source_value(desc, value);
} else {
__set_bit(hwgpio, mask);
if (value) {
__set_bit(hwgpio, bits);
} else {
__clear_bit(hwgpio, bits);
}
count++;
}
i++;
} while ((i < array_size) && (desc_array[i]->chip == chip));
/* push collected bits to outputs */
if (count != 0) {
gpio_chip_set_multiple(chip, mask, bits);
}
}
}
/**
* gpiod_set_raw_value() - assign a gpio's raw value
* @desc: gpio whose value will be assigned
@ -1298,6 +1395,48 @@ void gpiod_set_value(struct gpio_desc *desc, int value)
}
EXPORT_SYMBOL_GPL(gpiod_set_value);
/**
* gpiod_set_raw_array() - assign values to an array of GPIOs
* @array_size: number of elements in the descriptor / value arrays
* @desc_array: array of GPIO descriptors whose values will be assigned
* @value_array: array of values to assign
*
* Set the raw values of the GPIOs, i.e. the values of the physical lines
* without regard for their ACTIVE_LOW status.
*
* This function should be called from contexts where we cannot sleep, and will
* complain if the GPIO chip functions potentially sleep.
*/
void gpiod_set_raw_array(unsigned int array_size,
struct gpio_desc **desc_array, int *value_array)
{
if (!desc_array)
return;
gpiod_set_array_priv(true, false, array_size, desc_array, value_array);
}
EXPORT_SYMBOL_GPL(gpiod_set_raw_array);
/**
* gpiod_set_array() - assign values to an array of GPIOs
* @array_size: number of elements in the descriptor / value arrays
* @desc_array: array of GPIO descriptors whose values will be assigned
* @value_array: array of values to assign
*
* Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
* into account.
*
* This function should be called from contexts where we cannot sleep, and will
* complain if the GPIO chip functions potentially sleep.
*/
void gpiod_set_array(unsigned int array_size,
struct gpio_desc **desc_array, int *value_array)
{
if (!desc_array)
return;
gpiod_set_array_priv(false, false, array_size, desc_array, value_array);
}
EXPORT_SYMBOL_GPL(gpiod_set_array);
/**
* gpiod_cansleep() - report whether gpio value access may sleep
* @desc: gpio to check
@ -1332,14 +1471,14 @@ int gpiod_to_irq(const struct gpio_desc *desc)
EXPORT_SYMBOL_GPL(gpiod_to_irq);
/**
* gpio_lock_as_irq() - lock a GPIO to be used as IRQ
* gpiochip_lock_as_irq() - lock a GPIO to be used as IRQ
* @chip: the chip the GPIO to lock belongs to
* @offset: the offset of the GPIO to lock as IRQ
*
* This is used directly by GPIO drivers that want to lock down
* a certain GPIO line to be used for IRQs.
*/
int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
{
if (offset >= chip->ngpio)
return -EINVAL;
@ -1354,24 +1493,24 @@ int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
set_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
return 0;
}
EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
/**
* gpio_unlock_as_irq() - unlock a GPIO used as IRQ
* gpiochip_unlock_as_irq() - unlock a GPIO used as IRQ
* @chip: the chip the GPIO to lock belongs to
* @offset: the offset of the GPIO to lock as IRQ
*
* This is used directly by GPIO drivers that want to indicate
* that a certain GPIO is no longer used exclusively for IRQ.
*/
void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
{
if (offset >= chip->ngpio)
return;
clear_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
}
EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
/**
* gpiod_get_raw_value_cansleep() - return a gpio's raw value
@ -1457,6 +1596,50 @@ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
}
EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
/**
* gpiod_set_raw_array_cansleep() - assign values to an array of GPIOs
* @array_size: number of elements in the descriptor / value arrays
* @desc_array: array of GPIO descriptors whose values will be assigned
* @value_array: array of values to assign
*
* Set the raw values of the GPIOs, i.e. the values of the physical lines
* without regard for their ACTIVE_LOW status.
*
* This function is to be called from contexts that can sleep.
*/
void gpiod_set_raw_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
{
might_sleep_if(extra_checks);
if (!desc_array)
return;
gpiod_set_array_priv(true, true, array_size, desc_array, value_array);
}
EXPORT_SYMBOL_GPL(gpiod_set_raw_array_cansleep);
/**
* gpiod_set_array_cansleep() - assign values to an array of GPIOs
* @array_size: number of elements in the descriptor / value arrays
* @desc_array: array of GPIO descriptors whose values will be assigned
* @value_array: array of values to assign
*
* Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
* into account.
*
* This function is to be called from contexts that can sleep.
*/
void gpiod_set_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
{
might_sleep_if(extra_checks);
if (!desc_array)
return;
gpiod_set_array_priv(false, true, array_size, desc_array, value_array);
}
EXPORT_SYMBOL_GPL(gpiod_set_array_cansleep);
/**
* gpiod_add_lookup_table() - register GPIO device consumers
* @table: table of consumers to register

View File

@ -14,13 +14,13 @@
#include <linux/mdio-mux.h>
#include <linux/of_gpio.h>
#define DRV_VERSION "1.0"
#define DRV_VERSION "1.1"
#define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
#define MDIO_MUX_GPIO_MAX_BITS 8
struct mdio_mux_gpio_state {
int gpio[MDIO_MUX_GPIO_MAX_BITS];
struct gpio_desc *gpio[MDIO_MUX_GPIO_MAX_BITS];
unsigned int num_gpios;
void *mux_handle;
};
@ -28,29 +28,23 @@ struct mdio_mux_gpio_state {
static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
void *data)
{
int change;
int values[MDIO_MUX_GPIO_MAX_BITS];
unsigned int n;
struct mdio_mux_gpio_state *s = data;
if (current_child == desired_child)
return 0;
change = current_child == -1 ? -1 : current_child ^ desired_child;
for (n = 0; n < s->num_gpios; n++) {
if (change & 1)
gpio_set_value_cansleep(s->gpio[n],
(desired_child & 1) != 0);
change >>= 1;
desired_child >>= 1;
values[n] = (desired_child >> n) & 1;
}
gpiod_set_array_cansleep(s->num_gpios, s->gpio, values);
return 0;
}
static int mdio_mux_gpio_probe(struct platform_device *pdev)
{
enum of_gpio_flags f;
struct mdio_mux_gpio_state *s;
int num_gpios;
unsigned int n;
@ -70,22 +64,14 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev)
s->num_gpios = num_gpios;
for (n = 0; n < num_gpios; ) {
int gpio = of_get_gpio_flags(pdev->dev.of_node, n, &f);
if (gpio < 0) {
r = (gpio == -ENODEV) ? -EPROBE_DEFER : gpio;
struct gpio_desc *gpio = gpiod_get_index(&pdev->dev, NULL, n,
GPIOD_OUT_LOW);
if (IS_ERR(gpio)) {
r = PTR_ERR(gpio);
goto err;
}
s->gpio[n] = gpio;
n++;
r = gpio_request(gpio, "mdio_mux_gpio");
if (r)
goto err;
r = gpio_direction_output(gpio, 0);
if (r)
goto err;
}
r = mdio_mux_init(&pdev->dev,
@ -98,15 +84,18 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev)
err:
while (n) {
n--;
gpio_free(s->gpio[n]);
gpiod_put(s->gpio[n]);
}
return r;
}
static int mdio_mux_gpio_remove(struct platform_device *pdev)
{
unsigned int n;
struct mdio_mux_gpio_state *s = dev_get_platdata(&pdev->dev);
mdio_mux_uninit(s->mux_handle);
for (n = 0; n < s->num_gpios; n++)
gpiod_put(s->gpio[n]);
return 0;
}

View File

@ -1471,7 +1471,7 @@ static unsigned int gpio_irq_startup(struct irq_data *d)
unsigned pin = d->hwirq;
int ret;
ret = gpio_lock_as_irq(&at91_gpio->chip, pin);
ret = gpiochip_lock_as_irq(&at91_gpio->chip, pin);
if (ret) {
dev_err(at91_gpio->chip.dev, "unable to lock pind %lu IRQ\n",
d->hwirq);
@ -1487,7 +1487,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
unsigned pin = d->hwirq;
gpio_irq_mask(d);
gpio_unlock_as_irq(&at91_gpio->chip, pin);
gpiochip_unlock_as_irq(&at91_gpio->chip, pin);
}
#ifdef CONFIG_PM

View File

@ -174,7 +174,7 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
unsigned int con;
int ret;
ret = gpio_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
if (ret) {
dev_err(bank->gpio_chip.dev, "unable to lock pin %s-%lu IRQ\n",
bank->name, irqd->hwirq);
@ -227,7 +227,7 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
spin_unlock_irqrestore(&bank->slock, flags);
gpio_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
}
/*

View File

@ -553,7 +553,7 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
if (!func)
return -EINVAL;
ret = gpio_lock_as_irq(pctl->chip,
ret = gpiochip_lock_as_irq(pctl->chip,
pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
if (ret) {
dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
@ -571,8 +571,8 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
{
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(pctl->chip,
pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
gpiochip_unlock_as_irq(pctl->chip,
pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
}
static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)

View File

@ -44,15 +44,21 @@ static const struct {
void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
{
enum mctrl_gpio_idx i;
struct gpio_desc *desc_array[UART_GPIO_MAX];
int value_array[UART_GPIO_MAX];
unsigned int count = 0;
if (IS_ERR_OR_NULL(gpios))
return;
for (i = 0; i < UART_GPIO_MAX; i++)
if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
mctrl_gpios_desc[i].dir_out)
gpiod_set_value(gpios->gpio[i],
!!(mctrl & mctrl_gpios_desc[i].mctrl));
mctrl_gpios_desc[i].dir_out) {
desc_array[count] = gpios->gpio[i];
value_array[count] = !!(mctrl & mctrl_gpios_desc[i].mctrl);
count++;
}
gpiod_set_array(count, desc_array, value_array);
}
EXPORT_SYMBOL_GPL(mctrl_gpio_set);

View File

@ -216,14 +216,15 @@ static inline int gpio_to_irq(unsigned gpio)
return -EINVAL;
}
static inline int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
static inline int gpiochip_lock_as_irq(struct gpio_chip *chip,
unsigned int offset)
{
WARN_ON(1);
return -EINVAL;
}
static inline void gpio_unlock_as_irq(struct gpio_chip *chip,
unsigned int offset)
static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip,
unsigned int offset)
{
WARN_ON(1);
}

View File

@ -66,7 +66,7 @@ __devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags);
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
int gpiod_get_direction(const struct gpio_desc *desc);
int gpiod_get_direction(struct gpio_desc *desc);
int gpiod_direction_input(struct gpio_desc *desc);
int gpiod_direction_output(struct gpio_desc *desc, int value);
int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
@ -74,14 +74,24 @@ int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
/* Value get/set from non-sleeping context */
int gpiod_get_value(const struct gpio_desc *desc);
void gpiod_set_value(struct gpio_desc *desc, int value);
void gpiod_set_array(unsigned int array_size,
struct gpio_desc **desc_array, int *value_array);
int gpiod_get_raw_value(const struct gpio_desc *desc);
void gpiod_set_raw_value(struct gpio_desc *desc, int value);
void gpiod_set_raw_array(unsigned int array_size,
struct gpio_desc **desc_array, int *value_array);
/* Value get/set from sleeping context */
int gpiod_get_value_cansleep(const struct gpio_desc *desc);
void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
void gpiod_set_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array);
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc);
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value);
void gpiod_set_raw_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
@ -217,6 +227,13 @@ static inline void gpiod_set_value(struct gpio_desc *desc, int value)
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline void gpiod_set_array(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
{
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline int gpiod_get_raw_value(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
@ -228,6 +245,13 @@ static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value)
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline void gpiod_set_raw_array(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
{
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc)
{
@ -240,6 +264,13 @@ static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline void gpiod_set_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
{
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
{
/* GPIO can never have been requested */
@ -252,6 +283,13 @@ static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc,
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline void gpiod_set_raw_array_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
int *value_array)
{
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{

View File

@ -32,6 +32,7 @@ struct seq_file;
* @get: returns value for signal "offset"; for output signals this
* returns either the value actually sensed, or zero
* @set: assigns output value for signal "offset"
* @set_multiple: assigns output values for multiple signals defined by "mask"
* @set_debounce: optional hook for setting debounce time for specified gpio in
* interrupt triggered gpio chips
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
@ -89,6 +90,9 @@ struct gpio_chip {
unsigned offset);
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
void (*set_multiple)(struct gpio_chip *chip,
unsigned long *mask,
unsigned long *bits);
int (*set_debounce)(struct gpio_chip *chip,
unsigned offset,
unsigned debounce);
@ -149,8 +153,8 @@ extern struct gpio_chip *gpiochip_find(void *data,
int (*match)(struct gpio_chip *chip, void *data));
/* lock/unlock as IRQ */
int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);