Commit 980f3c34 authored by Linus Torvalds's avatar Linus Torvalds

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
  ..
parents 7d22286f 170680ab
* 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>;
};
...@@ -57,6 +57,8 @@ Optional device specific properties: ...@@ -57,6 +57,8 @@ Optional device specific properties:
occurred on. If it is not set, the interrupt are only generated for the occurred on. If it is not set, the interrupt are only generated for the
bank they belong to. bank they belong to.
On devices with only one interrupt output this property is useless. 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): Example I2C (with interrupt):
gpiom1: gpio@20 { gpiom1: gpio@20 {
......
* 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>;
};
...@@ -13,13 +13,22 @@ properties, each containing a 'gpio-list': ...@@ -13,13 +13,22 @@ properties, each containing a 'gpio-list':
gpio-specifier : Array of #gpio-cells specifying specific gpio gpio-specifier : Array of #gpio-cells specifying specific gpio
(controller specific) (controller specific)
GPIO properties should be named "[<name>-]gpios". The exact GPIO properties should be named "[<name>-]gpios", with <name> being the purpose
meaning of each gpios property must be documented in the device tree of this GPIO for the device. While a non-existent <name> is considered valid
binding for each device. 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 GPIO properties can contain one or more GPIO phandles, but only in exceptional
as chip select lines; with chip selects 0, 1 and 3 populated, and chip cases should they contain more than one. If your device uses several GPIOs with
select 2 left empty: 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 { gpio1: gpio1 {
gpio-controller gpio-controller
...@@ -30,10 +39,12 @@ select 2 left empty: ...@@ -30,10 +39,12 @@ select 2 left empty:
#gpio-cells = <1>; #gpio-cells = <1>;
}; };
[...] [...]
chipsel-gpios = <&gpio1 12 0>,
enable-gpios = <&gpio2 2>;
data-gpios = <&gpio1 12 0>,
<&gpio1 13 0>, <&gpio1 13 0>,
<0>, /* holes are permitted, means no GPIO 2 */ <&gpio1 14 0>,
<&gpio2 2>; <&gpio1 15 0>;
Note that gpio-specifier length is controller dependent. In the Note that gpio-specifier length is controller dependent. In the
above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2 above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
...@@ -42,16 +53,17 @@ only uses one. ...@@ -42,16 +53,17 @@ only uses one.
gpio-specifier may encode: bank, pin position inside the bank, gpio-specifier may encode: bank, pin position inside the bank,
whether pin is open-drain and whether pin is logically inverted. whether pin is open-drain and whether pin is logically inverted.
Exact meaning of each specifier cell is controller specific, and must 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: Example of a node using GPIOs:
node { 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, GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes
and GPIO flags as accepted by the "qe_pio_e" gpio-controller. GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
1.1) GPIO specifier best practices 1.1) GPIO specifier best practices
---------------------------------- ----------------------------------
......
...@@ -7,4 +7,4 @@ Required properties: ...@@ -7,4 +7,4 @@ Required properties:
- bit 0 specifies polarity (0 for normal, 1 for inverted) - bit 0 specifies polarity (0 for normal, 1 for inverted)
- gpio-controller : Marks the device node as a GPIO controller. - gpio-controller : Marks the device node as a GPIO controller.
- interrupts : Interrupt mapping for GPIO IRQ. - interrupts : Interrupt mapping for GPIO IRQ.
- gpio-ranges : Interaction with the PINCTRL subsystem.
...@@ -6,7 +6,9 @@ Required Properties: ...@@ -6,7 +6,9 @@ Required Properties:
- "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller. - "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller.
- "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) 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-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. - "renesas,gpio-rcar": for generic R-Car GPIO controller.
- reg: Base address and length of each memory resource used by the GPIO - reg: Base address and length of each memory resource used by the GPIO
......
...@@ -199,6 +199,33 @@ The active-low state of a GPIO can also be queried using the following call: ...@@ -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 Note that these functions should only be used with great moderation ; a driver
should not have to care about the physical line level. 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 GPIOs mapped to IRQs
-------------------- --------------------
GPIO lines can quite often be used as IRQs. You can get the IRQ number GPIO lines can quite often be used as IRQs. You can get the IRQ number
......
...@@ -158,12 +158,12 @@ Locking IRQ usage ...@@ -158,12 +158,12 @@ Locking IRQ usage
Input GPIOs can be used as IRQ signals. When this happens, a driver is requested 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: 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 This will prevent the use of non-irq related GPIO APIs until the GPIO IRQ lock
is released: 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 When implementing an irqchip inside a GPIO driver, these two functions should
typically be called in the .startup() and .shutdown() callbacks from the typically be called in the .startup() and .shutdown() callbacks from the
......
...@@ -112,6 +112,20 @@ config GPIO_MAX730X ...@@ -112,6 +112,20 @@ config GPIO_MAX730X
comment "Memory mapped GPIO drivers:" 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 config GPIO_CLPS711X
tristate "CLPS711X GPIO support" tristate "CLPS711X GPIO support"
depends on ARCH_CLPS711X || COMPILE_TEST depends on ARCH_CLPS711X || COMPILE_TEST
...@@ -134,6 +148,8 @@ config GPIO_GENERIC_PLATFORM ...@@ -134,6 +148,8 @@ config GPIO_GENERIC_PLATFORM
config GPIO_DWAPB config GPIO_DWAPB
tristate "Synopsys DesignWare APB GPIO driver" tristate "Synopsys DesignWare APB GPIO driver"
depends on ARM
depends on OF_GPIO
select GPIO_GENERIC select GPIO_GENERIC
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
help help
...@@ -333,6 +349,13 @@ config GPIO_TZ1090_PDC ...@@ -333,6 +349,13 @@ config GPIO_TZ1090_PDC
help help
Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs. 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 config GPIO_XGENE
bool "APM X-Gene GPIO controller support" bool "APM X-Gene GPIO controller support"
depends on ARM64 && OF_GPIO depends on ARM64 && OF_GPIO
......
...@@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o ...@@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.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_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
...@@ -96,6 +97,7 @@ obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o ...@@ -96,6 +97,7 @@ obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o
obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.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_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
......
/*
* 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");
...@@ -223,6 +223,7 @@ static int __init amd_gpio_init(void) ...@@ -223,6 +223,7 @@ static int __init amd_gpio_init(void)
if (err) { if (err) {
printk(KERN_ERR "GPIO registering failed (%d)\n", printk(KERN_ERR "GPIO registering failed (%d)\n",
err); err);
ioport_unmap(gp.pm);
release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
goto out; goto out;
} }
......
...@@ -470,7 +470,7 @@ static int bcm_kona_gpio_irq_reqres(struct irq_data *d) ...@@ -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); 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, dev_err(kona_gpio->gpio_chip.dev,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
d->hwirq); d->hwirq);
...@@ -483,7 +483,7 @@ static void bcm_kona_gpio_irq_relres(struct irq_data *d) ...@@ -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); 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 = { static struct irq_chip bcm_gpio_irq_chip = {
......
...@@ -322,7 +322,8 @@ static int cs5535_gpio_probe(struct platform_device *pdev) ...@@ -322,7 +322,8 @@ static int cs5535_gpio_probe(struct platform_device *pdev)
goto done; 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"); dev_err(&pdev->dev, "can't request region\n");
goto done; goto done;
} }
...@@ -348,24 +349,18 @@ static int cs5535_gpio_probe(struct platform_device *pdev) ...@@ -348,24 +349,18 @@ static int cs5535_gpio_probe(struct platform_device *pdev)
/* finally, register with the generic GPIO API */ /* finally, register with the generic GPIO API */
err = gpiochip_add(&cs5535_gpio_chip.chip); err = gpiochip_add(&cs5535_gpio_chip.chip);
if (err) if (err)
goto release_region; goto done;
return 0; return 0;
release_region:
release_region(res->start, resource_size(res));
done: done:
return err; return err;
} }
static int cs5535_gpio_remove(struct platform_device *pdev) static int cs5535_gpio_remove(struct platform_device *pdev)
{ {
struct resource *r;
gpiochip_remove(&cs5535_gpio_chip.chip); gpiochip_remove(&cs5535_gpio_chip.chip);
r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));
return 0; return 0;
} }
......
...@@ -234,11 +234,6 @@ static int davinci_gpio_probe(struct platform_device *pdev) ...@@ -234,11 +234,6 @@ static int davinci_gpio_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 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); gpio_base = devm_ioremap_resource(dev, res);
if (IS_ERR(gpio_base)) if (IS_ERR(gpio_base))
return PTR_ERR(gpio_base); return PTR_ERR(gpio_base);
......
...@@ -194,7 +194,7 @@ static int dwapb_irq_reqres(struct irq_data *d) ...@@ -194,7 +194,7 @@ static int dwapb_irq_reqres(struct irq_data *d)
struct dwapb_gpio *gpio = igc->private; struct dwapb_gpio *gpio = igc->private;
struct bgpio_chip *bgc = &gpio->ports[0].bgc; 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", dev_err(gpio->dev, "unable to lock HW IRQ %lu for IRQ\n",
irqd_to_hwirq(d)); irqd_to_hwirq(d));
return -EINVAL; return -EINVAL;
...@@ -208,7 +208,7 @@ static void dwapb_irq_relres(struct irq_data *d) ...@@ -208,7 +208,7 @@ static void dwapb_irq_relres(struct irq_data *d)
struct dwapb_gpio *gpio = igc->private; struct dwapb_gpio *gpio = igc->private;
struct bgpio_chip *bgc = &gpio->ports[0].bgc; 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) static int dwapb_irq_set_type(struct irq_data *d, u32 type)
......
...@@ -103,7 +103,7 @@ static int em_gio_irq_reqres(struct irq_data *d) ...@@ -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); 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, dev_err(p->gpio_chip.dev,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
irqd_to_hwirq(d)); irqd_to_hwirq(d));
...@@ -116,7 +116,7 @@ static void em_gio_irq_relres(struct irq_data *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); 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) ...@@ -330,12 +330,7 @@ static int em_gio_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
ret = of_alias_get_id(pdev->dev.of_node, "gpio"); pdata->gpio_base = -1;
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't get OF id\n");
goto err0;
}
pdata->gpio_base = ret * 32; /* 32 GPIOs per instance */
} }
gpio_chip = &p->gpio_chip; gpio_chip = &p->gpio_chip;
......
...@@ -441,6 +441,7 @@ static int grgpio_probe(struct platform_device *ofdev) ...@@ -441,6 +441,7 @@ static int grgpio_probe(struct platform_device *ofdev)
err = gpiochip_add(gc); err = gpiochip_add(gc);
if (err) { if (err) {
dev_err(&ofdev->dev, "Could not add gpiochip\n"); dev_err(&ofdev->dev, "Could not add gpiochip\n");
irq_domain_remove(priv->domain);
return err; return err;
} }
......
...@@ -65,6 +65,7 @@ struct mcp23s08_ops { ...@@ -65,6 +65,7 @@ struct mcp23s08_ops {
struct mcp23s08 { struct mcp23s08 {
u8 addr; u8 addr;
bool irq_active_high;
u16 cache[11]; u16 cache[11];
u16 irq_rise; u16 irq_rise;
...@@ -444,7 +445,7 @@ static int mcp23s08_irq_reqres(struct irq_data *data) ...@@ -444,7 +445,7 @@ static int mcp23s08_irq_reqres(struct irq_data *data)
{ {
struct mcp23s08 *mcp = irq_data_get_irq_chip_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, dev_err(mcp->chip.dev,
"unable to lock HW IRQ %lu for IRQ usage\n", "unable to lock HW IRQ %lu for IRQ usage\n",
data->hwirq); data->hwirq);
...@@ -458,7 +459,7 @@ static void mcp23s08_irq_relres(struct irq_data *data) ...@@ -458,7 +459,7 @@ static void mcp23s08_irq_relres(struct irq_data *data)
{ {
struct mcp23s08 *mcp = irq_data_get_irq_chip_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 = { static struct irq_chip mcp23s08_irq_chip = {
...@@ -476,6 +477,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) ...@@ -476,6 +477,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
{ {
struct gpio_chip *chip = &mcp->chip; struct gpio_chip *chip = &mcp->chip;
int err, irq, j; int err, irq, j;
unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED;
mutex_init(&mcp->irq_lock); mutex_init(&mcp->irq_lock);
...@@ -484,9 +486,13 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) ...@@ -484,9 +486,13 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
if (!mcp->irq_domain) if (!mcp->irq_domain)
return -ENODEV; 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, err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, irqflags, dev_name(chip->dev), mcp);
dev_name(chip->dev), mcp);
if (err != 0) { if (err != 0) {
dev_err(chip->dev, "unable to request IRQ#%d: %d\n", dev_err(chip->dev, "unable to request IRQ#%d: %d\n",
mcp->irq, err); mcp->irq, err);
...@@ -514,8 +520,6 @@ static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) ...@@ -514,8 +520,6 @@ static void mcp23s08_irq_teardown(struct mcp23s08 *mcp)
{ {
unsigned int irq, i; unsigned int irq, i;
free_irq(mcp->irq, mcp);
for (i = 0; i < mcp->chip.ngpio; i++) { for (i = 0; i < mcp->chip.ngpio; i++) {
irq = irq_find_mapping(mcp->irq_domain, i); irq = irq_find_mapping(mcp->irq_domain, i);
if (irq > 0) if (irq > 0)
...@@ -590,6 +594,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, ...@@ -590,6 +594,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
mcp->data = data; mcp->data = data;
mcp->addr = addr; mcp->addr = addr;
mcp->irq_active_high = false;
mcp->chip.direction_input = mcp23s08_direction_input; mcp->chip.direction_input = mcp23s08_direction_input;
mcp->chip.get = mcp23s08_get; mcp->chip.get = mcp23s08_get;
...@@ -649,14 +654,25 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, ...@@ -649,14 +654,25 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
goto fail; goto fail;
mcp->irq_controller = pdata->irq_controller; mcp->irq_controller = pdata->irq_controller;
if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) if (mcp->irq && mcp->irq_controller) {
mcp->irq_active_high =
of_property_read_bool(mcp->chip.dev->of_node,
"microchip,irq-active-high");
if (type == MCP_TYPE_017)
mirror = pdata->mirror; mirror = pdata->mirror;
}
if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) { if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror ||
mcp->irq_active_high) {
/* mcp23s17 has IOCON twice, make sure they are in sync */ /* mcp23s17 has IOCON twice, make sure they are in sync */
status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8)); status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
status |= IOCON_HAEN | (IOCON_HAEN << 8); status |= IOCON_HAEN | (IOCON_HAEN << 8);
if (mcp->irq_active_high)
status |= IOCON_INTPOL | (IOCON_INTPOL << 8);
else
status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
if (mirror) if (mirror)
status |= IOCON_MIRROR | (IOCON_MIRROR << 8); status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
...@@ -936,11 +952,14 @@ static int mcp23s08_probe(struct spi_device *spi) ...@@ -936,11 +952,14 @@ static int mcp23s08_probe(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
spi_set_drvdata(spi, data); 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++) { for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
if (!(spi_present_mask & (1 << addr))) if (!(spi_present_mask & (1 << addr)))
continue; continue;
chips--; chips--;
data->mcp[addr] = &data->chip[chips]; data->mcp[addr] = &data->chip[chips];
data->mcp[addr]->irq = spi->irq;
status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
0x40 | (addr << 1), type, pdata, 0x40 | (addr << 1), type, pdata,
addr); addr);
...@@ -981,6 +1000,8 @@ static int mcp23s08_remove(struct spi_device *spi) ...@@ -981,6 +1000,8 @@ static int mcp23s08_remove(struct spi_device *spi)
if (!data->mcp[addr]) if (!data->mcp[addr])
continue; continue;
if (spi->irq && data->mcp[addr]->irq_controller)
mcp23s08_irq_teardown(data->mcp[addr]);
gpiochip_remove(&data->mcp[addr]->chip); gpiochip_remove(&data->mcp[addr]->chip);
} }
kfree(data); kfree(data);
......
...@@ -105,6 +105,32 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -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); 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) 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); 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) ...@@ -344,6 +370,7 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ? gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
mpc8572_gpio_get : mpc8xxx_gpio_get; mpc8572_gpio_get : mpc8xxx_gpio_get;
gc->set = mpc8xxx_gpio_set; gc->set = mpc8xxx_gpio_set;
gc->set_multiple = mpc8xxx_gpio_set_multiple;
gc->to_irq = mpc8xxx_gpio_to_irq; gc->to_irq = mpc8xxx_gpio_to_irq;
ret = of_mm_gpiochip_add(np, mm_gc); ret = of_mm_gpiochip_add(np, mm_gc);
......
...@@ -83,6 +83,14 @@ struct mvebu_gpio_chip { ...@@ -83,6 +83,14 @@ struct mvebu_gpio_chip {
int irqbase; int irqbase;
struct irq_domain *domain; struct irq_domain *domain;
int soc_variant; 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[] = { ...@@ -554,6 +562,93 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, 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) static int mvebu_gpio_probe(struct platform_device *pdev)
{ {
struct mvebu_gpio_chip *mvchip; struct mvebu_gpio_chip *mvchip;
...@@ -577,6 +672,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ...@@ -577,6 +672,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
if (!mvchip) if (!mvchip)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, mvchip);
if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
dev_err(&pdev->dev, "Missing ngpios OF property\n"); dev_err(&pdev->dev, "Missing ngpios OF property\n");
return -ENODEV; return -ENODEV;
...@@ -735,5 +832,7 @@ static struct platform_driver mvebu_gpio_driver = { ...@@ -735,5 +832,7 @@ static struct platform_driver mvebu_gpio_driver = {
.of_match_table = mvebu_gpio_of_match, .of_match_table = mvebu_gpio_of_match,
}, },
.probe = mvebu_gpio_probe, .probe = mvebu_gpio_probe,
.suspend = mvebu_gpio_suspend,
.resume = mvebu_gpio_resume,
}; };
module_platform_driver(mvebu_gpio_driver); module_platform_driver(mvebu_gpio_driver);
...@@ -227,6 +227,18 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) ...@@ -227,6 +227,18 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return irq_find_mapping(port->domain, 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[] = { static struct platform_device_id mxs_gpio_ids[] = {
{ {
.name = "imx23-gpio", .name = "imx23-gpio",
...@@ -320,6 +332,7 @@ static int mxs_gpio_probe(struct platform_device *pdev) ...@@ -320,6 +332,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
goto out_irqdesc_free; goto out_irqdesc_free;
port->bgc.gc.to_irq = mxs_gpio_to_irq; 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; port->bgc.gc.base = port->id * 32;
err = gpiochip_add(&port->bgc.gc); err = gpiochip_add(&port->bgc.gc);
......
...@@ -800,7 +800,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) ...@@ -800,7 +800,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
unsigned offset = GPIO_INDEX(bank, gpio); unsigned offset = GPIO_INDEX(bank, gpio);
spin_lock_irqsave(&bank->lock, flags); 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)); bank->irq_usage &= ~(BIT(offset));
omap_disable_gpio_module(bank, offset); omap_disable_gpio_module(bank, offset);
omap_reset_gpio(bank, gpio); omap_reset_gpio(bank, gpio);
......
...@@ -52,27 +52,33 @@ struct pl061_gpio { ...@@ -52,27 +52,33 @@ struct pl061_gpio {
void __iomem *base; void __iomem *base;
struct gpio_chip gc; struct gpio_chip gc;
bool uses_pinctrl;
#ifdef CONFIG_PM #ifdef CONFIG_PM
struct pl061_context_save_regs csave_regs; struct pl061_context_save_regs csave_regs;
#endif #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 * Map back to global GPIO space and request muxing, the direction
* parameter does not matter for this controller. * 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;
if (chip->uses_pinctrl)
return pinctrl_request_gpio(gpio); 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;
if (chip->uses_pinctrl)
pinctrl_free_gpio(gpio); pinctrl_free_gpio(gpio);
} }
...@@ -263,6 +269,8 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -263,6 +269,8 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(chip->base); return PTR_ERR(chip->base);
spin_lock_init(&chip->lock); 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.request = pl061_gpio_request;
chip->gc.free = pl061_gpio_free; chip->gc.free = pl061_gpio_free;
......
/* /*
* Renesas R-Car GPIO Support * Renesas R-Car GPIO Support
* *
* Copyright (C) 2014 Renesas Electronics Corporation
* Copyright (C) 2013 Magnus Damm * Copyright (C) 2013 Magnus Damm
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -291,22 +292,30 @@ struct gpio_rcar_info { ...@@ -291,22 +292,30 @@ struct gpio_rcar_info {
bool has_both_edge_trigger; 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[] = { static const struct of_device_id gpio_rcar_of_table[] = {
{ {
.compatible = "renesas,gpio-r8a7790", .compatible = "renesas,gpio-r8a7790",
.data = (void *)&(const struct gpio_rcar_info) { .data = &gpio_rcar_info_gen2,
.has_both_edge_trigger = true,
},
}, { }, {
.compatible = "renesas,gpio-r8a7791", .compatible = "renesas,gpio-r8a7791",
.data = (void *)&(const struct gpio_rcar_info) { .data = &gpio_rcar_info_gen2,
.has_both_edge_trigger = true, }, {
}, .compatible = "renesas,gpio-r8a7793",
.data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-r8a7794",
.data = &gpio_rcar_info_gen2,
}, { }, {
.compatible = "renesas,gpio-rcar", .compatible = "renesas,gpio-rcar",
.data = (void *)&(const struct gpio_rcar_info) { .data = &gpio_rcar_info_gen1,
.has_both_edge_trigger = false,
},
}, { }, {
/* Terminator */ /* Terminator */
}, },
......
...@@ -199,21 +199,17 @@ static int xway_stp_hw_init(struct xway_stp *chip) ...@@ -199,21 +199,17 @@ static int xway_stp_hw_init(struct xway_stp *chip)
static int xway_stp_probe(struct platform_device *pdev) 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; const __be32 *shadow, *groups, *dsl, *phy;
struct xway_stp *chip; struct xway_stp *chip;
struct clk *clk; struct clk *clk;
int ret = 0; 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); chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip) if (!chip)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
chip->virt = devm_ioremap_resource(&pdev->dev, res); chip->virt = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(chip->virt)) if (IS_ERR(chip->virt))
return PTR_ERR(chip->virt); return PTR_ERR(chip->virt);
......
...@@ -195,18 +195,13 @@ static int tb10x_gpio_probe(struct platform_device *pdev) ...@@ -195,18 +195,13 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
if (of_property_read_u32(dn, "abilis,ngpio", &ngpio)) if (of_property_read_u32(dn, "abilis,ngpio", &ngpio))
return -EINVAL; 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); tb10x_gpio = devm_kzalloc(&pdev->dev, sizeof(*tb10x_gpio), GFP_KERNEL);
if (tb10x_gpio == NULL) if (tb10x_gpio == NULL)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&tb10x_gpio->spinlock); spin_lock_init(&tb10x_gpio->spinlock);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tb10x_gpio->base = devm_ioremap_resource(&pdev->dev, mem); tb10x_gpio->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(tb10x_gpio->base)) if (IS_ERR(tb10x_gpio->base))
return PTR_ERR(tb10x_gpio->base); return PTR_ERR(tb10x_gpio->base);
......
...@@ -233,7 +233,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -233,7 +233,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL; return -EINVAL;
} }
ret = gpio_lock_as_irq(&tegra_gpio_chip, gpio); ret = gpiochip_lock_as_irq(&tegra_gpio_chip, gpio);
if (ret) { if (ret) {
dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio); dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio);
return ret; return ret;
...@@ -263,7 +263,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d) ...@@ -263,7 +263,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d)
{ {
int gpio = d->hwirq; 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) static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
......
/*
* 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");
...@@ -138,7 +138,7 @@ static void unmask_giuint_low(struct irq_data *d) ...@@ -138,7 +138,7 @@ static void unmask_giuint_low(struct irq_data *d)
static unsigned int startup_giuint(struct irq_data *data) 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, dev_err(vr41xx_gpio_chip.dev,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
data->hwirq); data->hwirq);
...@@ -150,7 +150,7 @@ static unsigned int startup_giuint(struct irq_data *data) ...@@ -150,7 +150,7 @@ static unsigned int startup_giuint(struct irq_data *data)
static void shutdown_giuint(struct irq_data *data) static void shutdown_giuint(struct irq_data *data)
{ {
mask_giuint_low(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 = { static struct irq_chip giuint_low_irq_chip = {
......
...@@ -209,7 +209,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, ...@@ -209,7 +209,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
gpiod_direction_input(desc); gpiod_direction_input(desc);
ret = gpio_lock_as_irq(chip, pin); ret = gpiochip_lock_as_irq(chip, pin);
if (ret) { if (ret) {
dev_err(chip->dev, "Failed to lock GPIO as interrupt\n"); dev_err(chip->dev, "Failed to lock GPIO as interrupt\n");
goto fail_free_desc; goto fail_free_desc;
...@@ -265,7 +265,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, ...@@ -265,7 +265,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
fail_free_event: fail_free_event:
kfree(event); kfree(event);
fail_unlock_irq: fail_unlock_irq:
gpio_unlock_as_irq(chip, pin); gpiochip_unlock_as_irq(chip, pin);
fail_free_desc: fail_free_desc:
gpiochip_free_own_desc(desc); gpiochip_free_own_desc(desc);
...@@ -336,7 +336,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) ...@@ -336,7 +336,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
desc = event->desc; desc = event->desc;
if (WARN_ON(IS_ERR(desc))) if (WARN_ON(IS_ERR(desc)))
continue; continue;
gpio_unlock_as_irq(chip, event->pin); gpiochip_unlock_as_irq(chip, event->pin);
gpiochip_free_own_desc(desc); gpiochip_free_own_desc(desc);
list_del(&event->node); list_del(&event->node);
kfree(event); kfree(event);
......
...@@ -24,6 +24,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) ...@@ -24,6 +24,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
desc = gpio_to_desc(gpio); 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); err = gpiod_request(desc, label);
if (err) if (err)
return err; return err;
...@@ -62,7 +66,13 @@ EXPORT_SYMBOL_GPL(gpio_request_one); ...@@ -62,7 +66,13 @@ EXPORT_SYMBOL_GPL(gpio_request_one);
int gpio_request(unsigned gpio, const char *label) 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); EXPORT_SYMBOL_GPL(gpio_request);
......
...@@ -41,7 +41,7 @@ static DEFINE_MUTEX(sysfs_lock); ...@@ -41,7 +41,7 @@ static DEFINE_MUTEX(sysfs_lock);
static ssize_t gpio_direction_show(struct device *dev, static ssize_t gpio_direction_show(struct device *dev,
struct device_attribute *attr, char *buf) 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; ssize_t status;
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -161,7 +161,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, ...@@ -161,7 +161,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
desc->flags &= ~GPIO_TRIGGER_MASK; desc->flags &= ~GPIO_TRIGGER_MASK;
if (!gpio_flags) { 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; ret = 0;
goto free_id; goto free_id;
} }
...@@ -200,7 +200,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, ...@@ -200,7 +200,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
if (ret < 0) if (ret < 0)
goto free_id; 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) { if (ret < 0) {
gpiod_warn(desc, "failed to flag the GPIO for IRQ\n"); gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
goto free_id; goto free_id;
......
This diff is collapsed.
...@@ -14,13 +14,13 @@ ...@@ -14,13 +14,13 @@
#include <linux/mdio-mux.h> #include <linux/mdio-mux.h>
#include <linux/of_gpio.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 DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
#define MDIO_MUX_GPIO_MAX_BITS 8 #define MDIO_MUX_GPIO_MAX_BITS 8
struct mdio_mux_gpio_state { 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; unsigned int num_gpios;
void *mux_handle; void *mux_handle;
}; };
...@@ -28,29 +28,23 @@ struct mdio_mux_gpio_state { ...@@ -28,29 +28,23 @@ struct mdio_mux_gpio_state {
static int mdio_mux_gpio_switch_fn(int current_child, int desired_child, static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
void *data) void *data)
{ {
int change; int values[MDIO_MUX_GPIO_MAX_BITS];
unsigned int n; unsigned int n;
struct mdio_mux_gpio_state *s = data; struct mdio_mux_gpio_state *s = data;
if (current_child == desired_child) if (current_child == desired_child)
return 0; return 0;
change = current_child == -1 ? -1 : current_child ^ desired_child;
for (n = 0; n < s->num_gpios; n++) { for (n = 0; n < s->num_gpios; n++) {
if (change & 1) values[n] = (desired_child >> n) & 1;
gpio_set_value_cansleep(s->gpio[n],
(desired_child & 1) != 0);
change >>= 1;
desired_child >>= 1;
} }
gpiod_set_array_cansleep(s->num_gpios, s->gpio, values);
return 0; return 0;
} }
static int mdio_mux_gpio_probe(struct platform_device *pdev) static int mdio_mux_gpio_probe(struct platform_device *pdev)
{ {
enum of_gpio_flags f;
struct mdio_mux_gpio_state *s; struct mdio_mux_gpio_state *s;
int num_gpios; int num_gpios;
unsigned int n; unsigned int n;
...@@ -70,22 +64,14 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev) ...@@ -70,22 +64,14 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev)
s->num_gpios = num_gpios; s->num_gpios = num_gpios;
for (n = 0; n < num_gpios; ) { for (n = 0; n < num_gpios; ) {
int gpio = of_get_gpio_flags(pdev->dev.of_node, n, &f); struct gpio_desc *gpio = gpiod_get_index(&pdev->dev, NULL, n,
if (gpio < 0) { GPIOD_OUT_LOW);
r = (gpio == -ENODEV) ? -EPROBE_DEFER : gpio; if (IS_ERR(gpio)) {
r = PTR_ERR(gpio);
goto err; goto err;
} }
s->gpio[n] = gpio; s->gpio[n] = gpio;
n++; 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, r = mdio_mux_init(&pdev->dev,
...@@ -98,15 +84,18 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev) ...@@ -98,15 +84,18 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev)
err: err:
while (n) { while (n) {
n--; n--;
gpio_free(s->gpio[n]); gpiod_put(s->gpio[n]);
} }
return r; return r;
} }
static int mdio_mux_gpio_remove(struct platform_device *pdev) static int mdio_mux_gpio_remove(struct platform_device *pdev)
{ {
unsigned int n;
struct mdio_mux_gpio_state *s = dev_get_platdata(&pdev->dev); struct mdio_mux_gpio_state *s = dev_get_platdata(&pdev->dev);
mdio_mux_uninit(s->mux_handle); mdio_mux_uninit(s->mux_handle);
for (n = 0; n < s->num_gpios; n++)
gpiod_put(s->gpio[n]);
return 0; return 0;
} }
......
...@@ -1471,7 +1471,7 @@ static unsigned int gpio_irq_startup(struct irq_data *d) ...@@ -1471,7 +1471,7 @@ static unsigned int gpio_irq_startup(struct irq_data *d)
unsigned pin = d->hwirq; unsigned pin = d->hwirq;
int ret; int ret;
ret = gpio_lock_as_irq(&at91_gpio->chip, pin); ret = gpiochip_lock_as_irq(&at91_gpio->chip, pin);
if (ret) { if (ret) {
dev_err(at91_gpio->chip.dev, "unable to lock pind %lu IRQ\n", dev_err(at91_gpio->chip.dev, "unable to lock pind %lu IRQ\n",
d->hwirq); d->hwirq);
...@@ -1487,7 +1487,7 @@ static void gpio_irq_shutdown(struct irq_data *d) ...@@ -1487,7 +1487,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
unsigned pin = d->hwirq; unsigned pin = d->hwirq;
gpio_irq_mask(d); gpio_irq_mask(d);
gpio_unlock_as_irq(&at91_gpio->chip, pin); gpiochip_unlock_as_irq(&at91_gpio->chip, pin);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -174,7 +174,7 @@ static int exynos_irq_request_resources(struct irq_data *irqd) ...@@ -174,7 +174,7 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
unsigned int con; unsigned int con;
int ret; int ret;
ret = gpio_lock_as_irq(&bank->gpio_chip, irqd->hwirq); ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
if (ret) { if (ret) {
dev_err(bank->gpio_chip.dev, "unable to lock pin %s-%lu IRQ\n", dev_err(bank->gpio_chip.dev, "unable to lock pin %s-%lu IRQ\n",
bank->name, irqd->hwirq); bank->name, irqd->hwirq);
...@@ -227,7 +227,7 @@ static void exynos_irq_release_resources(struct irq_data *irqd) ...@@ -227,7 +227,7 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
spin_unlock_irqrestore(&bank->slock, flags); spin_unlock_irqrestore(&bank->slock, flags);
gpio_unlock_as_irq(&bank->gpio_chip, irqd->hwirq); gpiochip_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
} }
/* /*
......
...@@ -553,7 +553,7 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d) ...@@ -553,7 +553,7 @@ static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
if (!func) if (!func)
return -EINVAL; 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); pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
if (ret) { if (ret) {
dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n", dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
...@@ -571,7 +571,7 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d) ...@@ -571,7 +571,7 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
{ {
struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(pctl->chip, gpiochip_unlock_as_irq(pctl->chip,
pctl->irq_array[d->hwirq] - pctl->desc->pin_base); pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
} }
......
...@@ -44,15 +44,21 @@ static const struct { ...@@ -44,15 +44,21 @@ static const struct {
void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
{ {
enum mctrl_gpio_idx i; 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)) if (IS_ERR_OR_NULL(gpios))
return; return;
for (i = 0; i < UART_GPIO_MAX; i++) for (i = 0; i < UART_GPIO_MAX; i++)
if (!IS_ERR_OR_NULL(gpios->gpio[i]) && if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
mctrl_gpios_desc[i].dir_out) mctrl_gpios_desc[i].dir_out) {
gpiod_set_value(gpios->gpio[i], desc_array[count] = gpios->gpio[i];
!!(mctrl & mctrl_gpios_desc[i].mctrl)); value_array[count] = !!(mctrl & mctrl_gpios_desc[i].mctrl);
count++;
}
gpiod_set_array(count, desc_array, value_array);
} }
EXPORT_SYMBOL_GPL(mctrl_gpio_set); EXPORT_SYMBOL_GPL(mctrl_gpio_set);
......
...@@ -216,13 +216,14 @@ static inline int gpio_to_irq(unsigned gpio) ...@@ -216,13 +216,14 @@ static inline int gpio_to_irq(unsigned gpio)
return -EINVAL; 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); WARN_ON(1);
return -EINVAL; return -EINVAL;
} }
static inline void gpio_unlock_as_irq(struct gpio_chip *chip, static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip,
unsigned int offset) unsigned int offset)
{ {
WARN_ON(1); WARN_ON(1);
......
...@@ -66,7 +66,7 @@ __devm_gpiod_get_index_optional(struct device *dev, const char *con_id, ...@@ -66,7 +66,7 @@ __devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags); unsigned int index, enum gpiod_flags flags);
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc); 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_input(struct gpio_desc *desc);
int gpiod_direction_output(struct gpio_desc *desc, int value); int gpiod_direction_output(struct gpio_desc *desc, int value);
int gpiod_direction_output_raw(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); ...@@ -74,14 +74,24 @@ int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
/* Value get/set from non-sleeping context */ /* Value get/set from non-sleeping context */
int gpiod_get_value(const struct gpio_desc *desc); int gpiod_get_value(const struct gpio_desc *desc);
void gpiod_set_value(struct gpio_desc *desc, int value); 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); 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_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 */ /* Value get/set from sleeping context */
int gpiod_get_value_cansleep(const struct gpio_desc *desc); int gpiod_get_value_cansleep(const struct gpio_desc *desc);
void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); 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); 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_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); 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) ...@@ -217,6 +227,13 @@ static inline void gpiod_set_value(struct gpio_desc *desc, int value)
/* GPIO can never have been requested */ /* GPIO can never have been requested */
WARN_ON(1); 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) static inline int gpiod_get_raw_value(const struct gpio_desc *desc)
{ {
/* GPIO can never have been requested */ /* GPIO can never have been requested */
...@@ -228,6 +245,13 @@ static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) ...@@ -228,6 +245,13 @@ static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value)
/* GPIO can never have been requested */ /* GPIO can never have been requested */
WARN_ON(1); 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) 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) ...@@ -240,6 +264,13 @@ static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
/* GPIO can never have been requested */ /* GPIO can never have been requested */
WARN_ON(1); 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) static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
{ {
/* GPIO can never have been requested */ /* GPIO can never have been requested */
...@@ -252,6 +283,13 @@ static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, ...@@ -252,6 +283,13 @@ static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc,
/* GPIO can never have been requested */ /* GPIO can never have been requested */
WARN_ON(1); 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) static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
{ {
......
...@@ -32,6 +32,7 @@ struct seq_file; ...@@ -32,6 +32,7 @@ struct seq_file;
* @get: returns value for signal "offset"; for output signals this * @get: returns value for signal "offset"; for output signals this
* returns either the value actually sensed, or zero * returns either the value actually sensed, or zero
* @set: assigns output value for signal "offset" * @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 * @set_debounce: optional hook for setting debounce time for specified gpio in
* interrupt triggered gpio chips * interrupt triggered gpio chips
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings; * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
...@@ -89,6 +90,9 @@ struct gpio_chip { ...@@ -89,6 +90,9 @@ struct gpio_chip {
unsigned offset); unsigned offset);
void (*set)(struct gpio_chip *chip, void (*set)(struct gpio_chip *chip,
unsigned offset, int value); unsigned offset, int value);
void (*set_multiple)(struct gpio_chip *chip,
unsigned long *mask,
unsigned long *bits);
int (*set_debounce)(struct gpio_chip *chip, int (*set_debounce)(struct gpio_chip *chip,
unsigned offset, unsigned offset,
unsigned debounce); unsigned debounce);
...@@ -149,8 +153,8 @@ extern struct gpio_chip *gpiochip_find(void *data, ...@@ -149,8 +153,8 @@ extern struct gpio_chip *gpiochip_find(void *data,
int (*match)(struct gpio_chip *chip, void *data)); int (*match)(struct gpio_chip *chip, void *data));
/* lock/unlock as IRQ */ /* lock/unlock as 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);
void gpio_unlock_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); struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment