1
0
Fork 0

This is the bulk of GPIO changes for the v3.17 development

cycle, and this time we got a lot of action going on and
 it will continue:
 
 - The core GPIO library implementation has been split up in
   three different files:
   - gpiolib.c for the latest and greatest and shiny GPIO
     library code using GPIO descriptors only
   - gpiolib-legacy.c for the old integer number space API
     that we are phasing out gradually
   - gpiolib-sysfs.c for the sysfs interface that we are
     not entirely happy with, but has to live on for
     ABI compatibility
 
 - Add a flags argument to *gpiod_get* functions, with some
   backward-compatibility macros to ease transitions. We
   should have had the flags there from the beginning it
   seems, now we need to clean up the mess. There is a plan
   on how to move forward here devised by Alexandre Courbot
   and Mark Brown.
 
 - Split off a special <linux/gpio/machine.h> header for the
   board gpio table registration, as per example from the
   regulator subsystem.
 
 - Start to kill off the return value from gpiochip_remove()
   by removing the __must_check attribute and removing all
   checks inside the drivers/gpio directory. The rationale
   is: well what were we supposed to do if there is an error
   code? Not much: print an error message. And gpiolib already
   does that. So make this function return void eventually.
 
 - Some cleanups of hairy gpiolib code, make some functions
   not to be used outside the library private and make sure
   they are not exported, remove gpiod_lock/unlock_as_irq()
   as the existing function is for driver-internal use and
   fine as it is, delete gpio_ensure_requested() as it is
   not meaningful anymore.
 
 - Support the GPIOF_ACTIVE_LOW flag from gpio_request_one()
   function calls, which is logical since this is already
   supported when referencing GPIOs from e.g. device trees.
 
 - Switch STMPE, intel-mid, lynxpoint and ACPI (!) to use
   the gpiolib irqchip helpers cutting down on GPIO irqchip
   boilerplate a bit more.
 
 - New driver for the Zynq GPIO block.
 
 - The usual incremental improvements around a bunch of
   drivers.
 
 - Janitorial syntactic and semantic cleanups by Jingoo Han,
   and Rickard Strandqvist especially.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJT5Ji9AAoJEEEQszewGV1zch8QAKp67+8ScxRBf/7RCSV6U/dy
 i7kt+nP4au/TScwtjbX264DM8hroW7BzN+GqF10NEFeGkYDR+42lMav9PrNjtKtk
 ojQPWdoGWzwwL0wa4j9rsuG/pRnbAEgDWPb+EkFdHQsLl6h71fyVoLOK+gKwJFyn
 aPYGXyNbT1FN38oj1rarENiOUxM7VMXvcJFfvDYFdDDhCS4PLYPOMw0lrsGtsHMZ
 epDa4z3yt4zHgYiUIT578nQ7EkIbGN3goywk3NQ+9WDQG+sLFHh4BdqcRKg6b9VM
 I64+47uNQxkyvWCvcLma5ziqvtNQk113986g+cv5YeTh18Ajyio1kxEIZM181eBk
 ITUPGrAorWHPLGNbe3psLmtK3+/BwmWIurPmHpckuW8d2JWWSVe0oepkUuqDwu/w
 lUB5KtM0joFOr5k61fj5tCKxH344jc1zvHJ/N+bVYilbOMvunWzuMJlc4hADIGC2
 1uxUAcPbYUAphGaxhdMBca9ellm0lWG19Gj5TtdGbRtNgp6R2qrwI66DDzk+1kLR
 8Szx6KHQdEHFTlCLKSIAMv33p1ClfmNikhdicT3urwR8PeXmmTR1pD7kGmVTDDZa
 gXSU5EilgGpak+77j/GZ2Ivp0Qt5M97UwWlZ7zTp++T1ZY+wwTHJI/09qcoWYjdz
 IpZRIqrQchalbscpn3LY
 =e+d6
 -----END PGP SIGNATURE-----

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

Pull GPIO update from Linus Walleij:
 "This is the bulk of GPIO changes for the v3.17 development cycle, and
  this time we got a lot of action going on and it will continue:

   - The core GPIO library implementation has been split up in three
     different files:
     - gpiolib.c for the latest and greatest and shiny GPIO library code
       using GPIO descriptors only
     - gpiolib-legacy.c for the old integer number space API that we are
       phasing out gradually
     - gpiolib-sysfs.c for the sysfs interface that we are not entirely
       happy with, but has to live on for ABI compatibility

   - Add a flags argument to *gpiod_get* functions, with some
     backward-compatibility macros to ease transitions.  We should have
     had the flags there from the beginning it seems, now we need to
     clean up the mess.  There is a plan on how to move forward here
     devised by Alexandre Courbot and Mark Brown

   - Split off a special <linux/gpio/machine.h> header for the board
     gpio table registration, as per example from the regulator
     subsystem

   - Start to kill off the return value from gpiochip_remove() by
     removing the __must_check attribute and removing all checks inside
     the drivers/gpio directory.  The rationale is: well what were we
     supposed to do if there is an error code? Not much: print an error
     message.  And gpiolib already does that.  So make this function
     return void eventually

   - Some cleanups of hairy gpiolib code, make some functions not to be
     used outside the library private and make sure they are not
     exported, remove gpiod_lock/unlock_as_irq() as the existing
     function is for driver-internal use and fine as it is, delete
     gpio_ensure_requested() as it is not meaningful anymore

   - Support the GPIOF_ACTIVE_LOW flag from gpio_request_one() function
     calls, which is logical since this is already supported when
     referencing GPIOs from e.g. device trees

   - Switch STMPE, intel-mid, lynxpoint and ACPI (!) to use the gpiolib
     irqchip helpers cutting down on GPIO irqchip boilerplate a bit more

   - New driver for the Zynq GPIO block

   - The usual incremental improvements around a bunch of drivers

   - Janitorial syntactic and semantic cleanups by Jingoo Han, and
     Rickard Strandqvist especially"

* tag 'gpio-v3.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (37 commits)
  MAINTAINERS: update GPIO include files
  gpio: add missing includes in machine.h
  gpio: add flags argument to gpiod_get*() functions
  MAINTAINERS: Update Samsung pin control entry
  gpio / ACPI: Move event handling registration to gpiolib irqchip helpers
  gpio: lynxpoint: Convert to use gpiolib irqchip
  gpio: split gpiod board registration into machine header
  gpio: remove gpio_ensure_requested()
  gpio: remove useless check in gpiolib_sysfs_init()
  gpiolib: Export gpiochip_request_own_desc and gpiochip_free_own_desc
  gpio: move gpio_ensure_requested() into legacy C file
  gpio: remove gpiod_lock/unlock_as_irq()
  gpio: make gpiochip_get_desc() gpiolib-private
  gpio: simplify gpiochip_export()
  gpio: remove export of private of_get_named_gpio_flags()
  gpio: Add support for GPIOF_ACTIVE_LOW to gpio_request_one functions
  gpio: zynq: Clear pending interrupt when enabling a IRQ
  gpio: drop retval check enforcing from gpiochip_remove()
  gpio: remove all usage of gpio_remove retval in driver/gpio
  devicetree: Add Zynq GPIO devicetree bindings documentation
  ...
hifive-unleashed-5.1
Linus Torvalds 2014-08-08 18:00:35 -07:00
commit 06b49ea43c
84 changed files with 2413 additions and 1931 deletions

View File

@ -0,0 +1,26 @@
Xilinx Zynq GPIO controller Device Tree Bindings
-------------------------------------------
Required properties:
- #gpio-cells : Should be two
- First cell is the GPIO line number
- Second cell is used to specify optional
parameters (unused)
- compatible : Should be "xlnx,zynq-gpio-1.0"
- clocks : Clock specifier (see clock bindings for details)
- gpio-controller : Marks the device node as a GPIO controller.
- interrupts : Interrupt specifier (see interrupt bindings for
details)
- interrupt-parent : Must be core interrupt controller
- reg : Address and length of the register set for the device
Example:
gpio@e000a000 {
#gpio-cells = <2>;
compatible = "xlnx,zynq-gpio-1.0";
clocks = <&clkc 42>;
gpio-controller;
interrupt-parent = <&intc>;
interrupts = <0 20 4>;
reg = <0xe000a000 0x1000>;
};

View File

@ -60,7 +60,7 @@ Platform Data
Finally, GPIOs can be bound to devices and functions using platform data. Board
files that desire to do so need to include the following header:
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
GPIOs are mapped by the means of tables of lookups, containing instances of the
gpiod_lookup structure. Two macros are defined to help declaring such mappings:

View File

@ -29,13 +29,24 @@ gpiod_get() functions. Like many other kernel subsystems, gpiod_get() takes the
device that will use the GPIO and the function the requested GPIO is supposed to
fulfill:
struct gpio_desc *gpiod_get(struct device *dev, const char *con_id)
struct gpio_desc *gpiod_get(struct device *dev, const char *con_id,
enum gpiod_flags flags)
If a function is implemented by using several GPIOs together (e.g. a simple LED
device that displays digits), an additional index argument can be specified:
struct gpio_desc *gpiod_get_index(struct device *dev,
const char *con_id, unsigned int idx)
const char *con_id, unsigned int idx,
enum gpiod_flags flags)
The flags parameter is used to optionally specify a direction and initial value
for the GPIO. Values can be:
* GPIOD_ASIS or 0 to not initialize the GPIO at all. The direction must be set
later with one of the dedicated functions.
* GPIOD_IN to initialize the GPIO as input.
* GPIOD_OUT_LOW to initialize the GPIO as output with a value of 0.
* GPIOD_OUT_HIGH to initialize the GPIO as output with a value of 1.
Both functions return either a valid GPIO descriptor, or an error code checkable
with IS_ERR() (they will never return a NULL pointer). -ENOENT will be returned
@ -46,11 +57,13 @@ errors and an absence of GPIO for optional GPIO parameters.
Device-managed variants of these functions are also defined:
struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id)
struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id,
enum gpiod_flags flags)
struct gpio_desc *devm_gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx)
unsigned int idx,
enum gpiod_flags flags)
A GPIO descriptor can be disposed of using the gpiod_put() function:
@ -67,8 +80,9 @@ Using GPIOs
Setting Direction
-----------------
The first thing a driver must do with a GPIO is setting its direction. This is
done by invoking one of the gpiod_direction_*() functions:
The first thing a driver must do with a GPIO is setting its direction. If no
direction-setting flags have been given to gpiod_get*(), this is done by
invoking one of the gpiod_direction_*() functions:
int gpiod_direction_input(struct gpio_desc *desc)
int gpiod_direction_output(struct gpio_desc *desc, int value)

View File

@ -157,13 +157,34 @@ 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 gpiod_lock_as_irq(struct gpio_desc *desc)
int gpio_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 gpiod_unlock_as_irq(struct gpio_desc *desc)
void gpio_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
irqchip.
Requesting self-owned GPIO pins
-------------------------------
Sometimes it is useful to allow a GPIO chip driver to request its own GPIO
descriptors through the gpiolib API. Using gpio_request() for this purpose
does not help since it pins the module to the kernel forever (it calls
try_module_get()). A GPIO driver can use the following functions instead
to request and free descriptors without being pinned to the kernel forever.
int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label)
void gpiochip_free_own_desc(struct gpio_desc *desc)
Descriptors requested with gpiochip_request_own_desc() must be released with
gpiochip_free_own_desc().
These functions must be used with care since they do not affect module use
count. Do not use the functions to request gpio descriptors not owned by the
calling driver.

View File

@ -4031,7 +4031,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
S: Maintained
F: Documentation/gpio/
F: drivers/gpio/
F: include/linux/gpio*
F: include/linux/gpio/
F: include/linux/gpio.h
F: include/asm-generic/gpio.h
GRE DEMULTIPLEXER DRIVER
@ -7002,9 +7003,7 @@ M: Thomas Abraham <thomas.abraham@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
F: drivers/pinctrl/pinctrl-exynos.*
F: drivers/pinctrl/pinctrl-s3c*
F: drivers/pinctrl/pinctrl-samsung.*
F: drivers/pinctrl/samsung/
PIN CONTROLLER - ST SPEAR
M: Viresh Kumar <viresh.linux@gmail.com>

View File

@ -15,7 +15,7 @@
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>

View File

@ -17,7 +17,7 @@
*
*/
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/rfkill-gpio.h>

View File

@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>

View File

@ -340,6 +340,13 @@ config GPIO_XILINX
help
Say yes here to support the Xilinx FPGA GPIO device
config GPIO_ZYNQ
tristate "Xilinx Zynq GPIO support"
depends on ARCH_ZYNQ
select GPIOLIB_IRQCHIP
help
Say yes here to support Xilinx Zynq GPIO controller.
config GPIO_XTENSA
bool "Xtensa GPIO32 support"
depends on XTENSA
@ -423,7 +430,7 @@ config GPIO_GE_FPGA
config GPIO_LYNXPOINT
tristate "Intel Lynxpoint GPIO support"
depends on ACPI && X86
select IRQ_DOMAIN
select GPIOLIB_IRQCHIP
help
driver for GPIO functionality on Intel Lynxpoint PCH chipset
Requires ACPI device enumeration code to set up a platform device.
@ -586,6 +593,7 @@ config GPIO_SX150X
config GPIO_STMPE
bool "STMPE GPIOs"
depends on MFD_STMPE
select GPIOLIB_IRQCHIP
help
This enables support for the GPIOs found on the STMPE I/O
Expanders.

View File

@ -4,7 +4,9 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIO_DEVRES) += devres.o
obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
# Device drivers. Generally keep list sorted alphabetically
@ -102,3 +104,4 @@ obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o

View File

@ -39,47 +39,53 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data)
* devm_gpiod_get - Resource-managed gpiod_get()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get() for detailed
* information about behavior and return values.
*/
struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
const char *con_id)
struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
{
return devm_gpiod_get_index(dev, con_id, 0);
return devm_gpiod_get_index(dev, con_id, 0, flags);
}
EXPORT_SYMBOL(devm_gpiod_get);
EXPORT_SYMBOL(__devm_gpiod_get);
/**
* devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get_optional(). GPIO descriptors returned from this function
* are automatically disposed on driver detach. See gpiod_get_optional() for
* detailed information about behavior and return values.
*/
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
const char *con_id)
struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
{
return devm_gpiod_get_index_optional(dev, con_id, 0);
return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
}
EXPORT_SYMBOL(devm_gpiod_get_optional);
EXPORT_SYMBOL(__devm_gpiod_get_optional);
/**
* devm_gpiod_get_index - Resource-managed gpiod_get_index()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @idx: index of the GPIO to obtain in the consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get_index(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get_index() for detailed
* information about behavior and return values.
*/
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx)
unsigned int idx,
enum gpiod_flags flags)
{
struct gpio_desc **dr;
struct gpio_desc *desc;
@ -89,7 +95,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
if (!dr)
return ERR_PTR(-ENOMEM);
desc = gpiod_get_index(dev, con_id, idx);
desc = gpiod_get_index(dev, con_id, idx, flags);
if (IS_ERR(desc)) {
devres_free(dr);
return desc;
@ -100,26 +106,28 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
return desc;
}
EXPORT_SYMBOL(devm_gpiod_get_index);
EXPORT_SYMBOL(__devm_gpiod_get_index);
/**
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @index: index of the GPIO to obtain in the consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get_index_optional(). GPIO descriptors returned from this
* function are automatically disposed on driver detach. See
* gpiod_get_index_optional() for detailed information about behavior and
* return values.
*/
struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *dev,
const char *con_id,
unsigned int index)
unsigned int index,
enum gpiod_flags flags)
{
struct gpio_desc *desc;
desc = devm_gpiod_get_index(dev, con_id, index);
desc = devm_gpiod_get_index(dev, con_id, index, flags);
if (IS_ERR(desc)) {
if (PTR_ERR(desc) == -ENOENT)
return NULL;
@ -127,7 +135,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
return desc;
}
EXPORT_SYMBOL(devm_gpiod_get_index_optional);
EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
/**
* devm_gpiod_put - Resource-managed gpiod_put()

View File

@ -167,13 +167,11 @@ exit_destroy:
static int gen_74x164_remove(struct spi_device *spi)
{
struct gen_74x164_chip *chip = spi_get_drvdata(spi);
int ret;
ret = gpiochip_remove(&chip->gpio_chip);
if (!ret)
mutex_destroy(&chip->lock);
gpiochip_remove(&chip->gpio_chip);
mutex_destroy(&chip->lock);
return ret;
return 0;
}
static const struct of_device_id gen_74x164_dt_ids[] = {

View File

@ -585,15 +585,8 @@ static int adnp_i2c_remove(struct i2c_client *client)
{
struct adnp *adnp = i2c_get_clientdata(client);
struct device_node *np = client->dev.of_node;
int err;
err = gpiochip_remove(&adnp->gpio);
if (err < 0) {
dev_err(&client->dev, "%s failed: %d\n", "gpiochip_remove()",
err);
return err;
}
gpiochip_remove(&adnp->gpio);
if (of_find_property(np, "interrupt-controller", NULL))
adnp_irq_teardown(adnp);

View File

@ -167,15 +167,9 @@ err:
static int adp5520_gpio_remove(struct platform_device *pdev)
{
struct adp5520_gpio *dev;
int ret;
dev = platform_get_drvdata(pdev);
ret = gpiochip_remove(&dev->gpio_chip);
if (ret) {
dev_err(&pdev->dev, "%s failed, %d\n",
"gpiochip_remove()", ret);
return ret;
}
gpiochip_remove(&dev->gpio_chip);
return 0;
}

View File

@ -470,11 +470,7 @@ static int adp5588_gpio_remove(struct i2c_client *client)
if (dev->irq_base)
free_irq(dev->client->irq, dev);
ret = gpiochip_remove(&dev->gpio_chip);
if (ret) {
dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
return ret;
}
gpiochip_remove(&dev->gpio_chip);
kfree(dev);
return 0;

View File

@ -232,8 +232,7 @@ out:
static void __exit amd_gpio_exit(void)
{
int err = gpiochip_remove(&gp.chip);
WARN_ON(err);
gpiochip_remove(&gp.chip);
ioport_unmap(gp.pm);
release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE);
}

View File

@ -149,7 +149,8 @@ static int arizona_gpio_remove(struct platform_device *pdev)
{
struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&arizona_gpio->gpio_chip);
gpiochip_remove(&arizona_gpio->gpio_chip);
return 0;
}
static struct platform_driver arizona_gpio_driver = {

View File

@ -358,14 +358,8 @@ done:
static int cs5535_gpio_remove(struct platform_device *pdev)
{
struct resource *r;
int err;
err = gpiochip_remove(&cs5535_gpio_chip.chip);
if (err) {
/* uhh? */
dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
return err;
}
gpiochip_remove(&cs5535_gpio_chip.chip);
r = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(r->start, resource_size(r));

View File

@ -237,7 +237,8 @@ static int da9052_gpio_remove(struct platform_device *pdev)
{
struct da9052_gpio *gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&gpio->gp);
gpiochip_remove(&gpio->gp);
return 0;
}
static struct platform_driver da9052_gpio_driver = {

View File

@ -174,7 +174,8 @@ static int da9055_gpio_remove(struct platform_device *pdev)
{
struct da9055_gpio *gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&gpio->gp);
gpiochip_remove(&gpio->gp);
return 0;
}
static struct platform_driver da9055_gpio_driver = {

View File

@ -359,7 +359,7 @@ static void dwapb_gpio_unregister(struct dwapb_gpio *gpio)
for (m = 0; m < gpio->nr_ports; ++m)
if (gpio->ports[m].is_registered)
WARN_ON(gpiochip_remove(&gpio->ports[m].bgc.gc));
gpiochip_remove(&gpio->ports[m].bgc.gc);
}
static int dwapb_gpio_probe(struct platform_device *pdev)

View File

@ -409,11 +409,8 @@ err0:
static int em_gio_remove(struct platform_device *pdev)
{
struct em_gio_priv *p = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&p->gpio_chip);
if (ret)
return ret;
gpiochip_remove(&p->gpio_chip);
irq_domain_remove(p->irq_domain);
return 0;

View File

@ -317,13 +317,7 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
err_gpiochip:
for (i = i - 1; i >= 0; i--) {
struct f7188x_gpio_bank *bank = &data->bank[i];
int tmp;
tmp = gpiochip_remove(&bank->chip);
if (tmp < 0)
dev_err(&pdev->dev,
"Failed to remove gpiochip %d: %d\n",
i, tmp);
gpiochip_remove(&bank->chip);
}
return err;
@ -331,20 +325,12 @@ err_gpiochip:
static int f7188x_gpio_remove(struct platform_device *pdev)
{
int err;
int i;
struct f7188x_gpio_data *data = platform_get_drvdata(pdev);
for (i = 0; i < data->nr_bank; i++) {
struct f7188x_gpio_bank *bank = &data->bank[i];
err = gpiochip_remove(&bank->chip);
if (err) {
dev_err(&pdev->dev,
"Failed to remove GPIO gpiochip %d: %d\n",
i, err);
return err;
}
gpiochip_remove(&bank->chip);
}
return 0;

View File

@ -398,7 +398,8 @@ static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
int bgpio_remove(struct bgpio_chip *bgc)
{
return gpiochip_remove(&bgc->gc);
gpiochip_remove(&bgc->gc);
return 0;
}
EXPORT_SYMBOL_GPL(bgpio_remove);

View File

@ -468,9 +468,7 @@ static int grgpio_remove(struct platform_device *ofdev)
}
}
ret = gpiochip_remove(&priv->bgc.gc);
if (ret)
goto out;
gpiochip_remove(&priv->bgc.gc);
if (priv->domain)
irq_domain_remove(priv->domain);

View File

@ -514,14 +514,7 @@ add_err:
static int ichx_gpio_remove(struct platform_device *pdev)
{
int err;
err = gpiochip_remove(&ichx_priv.chip);
if (err) {
dev_err(&pdev->dev, "%s failed, %d\n",
"gpiochip_remove()", err);
return err;
}
gpiochip_remove(&ichx_priv.chip);
ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
if (ichx_priv.pm_base)

View File

@ -28,12 +28,10 @@
#include <linux/stddef.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/irqdomain.h>
#define INTEL_MID_IRQ_TYPE_EDGE (1 << 0)
#define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1)
@ -78,10 +76,12 @@ struct intel_mid_gpio {
void __iomem *reg_base;
spinlock_t lock;
struct pci_dev *pdev;
struct irq_domain *domain;
};
#define to_intel_gpio_priv(chip) container_of(chip, struct intel_mid_gpio, chip)
static inline struct intel_mid_gpio *to_intel_gpio_priv(struct gpio_chip *gc)
{
return container_of(gc, struct intel_mid_gpio, chip);
}
static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
enum GPIO_REG reg_type)
@ -182,15 +182,10 @@ static int intel_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
static int intel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
return irq_create_mapping(priv->domain, offset);
}
static int intel_mid_irq_type(struct irq_data *d, unsigned type)
{
struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct intel_mid_gpio *priv = to_intel_gpio_priv(gc);
u32 gpio = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
@ -231,33 +226,11 @@ static void intel_mid_irq_mask(struct irq_data *d)
{
}
static int intel_mid_irq_reqres(struct irq_data *d)
{
struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) {
dev_err(priv->chip.dev,
"unable to lock HW IRQ %lu for IRQ\n",
irqd_to_hwirq(d));
return -EINVAL;
}
return 0;
}
static void intel_mid_irq_relres(struct irq_data *d)
{
struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d));
}
static struct irq_chip intel_mid_irqchip = {
.name = "INTEL_MID-GPIO",
.irq_mask = intel_mid_irq_mask,
.irq_unmask = intel_mid_irq_unmask,
.irq_set_type = intel_mid_irq_type,
.irq_request_resources = intel_mid_irq_reqres,
.irq_release_resources = intel_mid_irq_relres,
};
static const struct intel_mid_gpio_ddata gpio_lincroft = {
@ -330,8 +303,9 @@ MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct intel_mid_gpio *priv = to_intel_gpio_priv(gc);
struct irq_data *data = irq_desc_get_irq_data(desc);
struct intel_mid_gpio *priv = irq_data_get_irq_handler_data(data);
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, gpio, mask;
unsigned long pending;
@ -345,7 +319,7 @@ static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
mask = BIT(gpio);
/* Clear before handling so we can't lose an edge */
writel(mask, gedr);
generic_handle_irq(irq_find_mapping(priv->domain,
generic_handle_irq(irq_find_mapping(gc->irqdomain,
base + gpio));
}
}
@ -371,23 +345,6 @@ static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv)
}
}
static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct intel_mid_gpio *priv = d->host_data;
irq_set_chip_and_handler(irq, &intel_mid_irqchip, handle_simple_irq);
irq_set_chip_data(irq, priv);
irq_set_irq_type(irq, IRQ_TYPE_NONE);
return 0;
}
static const struct irq_domain_ops intel_gpio_irq_ops = {
.map = intel_gpio_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static int intel_gpio_runtime_idle(struct device *dev)
{
int err = pm_schedule_suspend(dev, 500);
@ -441,7 +398,6 @@ static int intel_gpio_probe(struct pci_dev *pdev,
priv->chip.direction_output = intel_gpio_direction_output;
priv->chip.get = intel_gpio_get;
priv->chip.set = intel_gpio_set;
priv->chip.to_irq = intel_gpio_to_irq;
priv->chip.base = gpio_base;
priv->chip.ngpio = ddata->ngpio;
priv->chip.can_sleep = false;
@ -449,11 +405,6 @@ static int intel_gpio_probe(struct pci_dev *pdev,
spin_lock_init(&priv->lock);
priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
irq_base, &intel_gpio_irq_ops, priv);
if (!priv->domain)
return -ENOMEM;
pci_set_drvdata(pdev, priv);
retval = gpiochip_add(&priv->chip);
if (retval) {
@ -461,10 +412,23 @@ static int intel_gpio_probe(struct pci_dev *pdev,
return retval;
}
retval = gpiochip_irqchip_add(&priv->chip,
&intel_mid_irqchip,
irq_base,
handle_simple_irq,
IRQ_TYPE_NONE);
if (retval) {
dev_err(&pdev->dev,
"could not connect irqchip to gpiochip\n");
return retval;
}
intel_mid_irq_init_hw(priv);
irq_set_handler_data(pdev->irq, priv);
irq_set_chained_handler(pdev->irq, intel_mid_irq_handler);
gpiochip_set_chained_irqchip(&priv->chip,
&intel_mid_irqchip,
pdev->irq,
intel_mid_irq_handler);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);

View File

@ -217,11 +217,7 @@ gpiochip_add_err:
static void __exit it8761e_gpio_exit(void)
{
if (gpio_ba) {
int ret = gpiochip_remove(&it8761e_gpio_chip);
WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n",
__func__, ret);
gpiochip_remove(&it8761e_gpio_chip);
release_region(gpio_ba, GPIO_IOSIZE);
gpio_ba = 0;
}

View File

@ -194,14 +194,8 @@ static int ttl_probe(struct platform_device *pdev)
static int ttl_remove(struct platform_device *pdev)
{
struct ttl_module *mod = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
int ret;
ret = gpiochip_remove(&mod->gpio);
if (ret) {
dev_err(dev, "unable to remove GPIO chip\n");
return ret;
}
gpiochip_remove(&mod->gpio);
return 0;
}

View File

@ -199,7 +199,8 @@ static int kempld_gpio_remove(struct platform_device *pdev)
{
struct kempld_gpio_data *gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&gpio->chip);
gpiochip_remove(&gpio->chip);
return 0;
}
static struct platform_driver kempld_gpio_driver = {

View File

@ -216,7 +216,8 @@ static int lp3943_gpio_remove(struct platform_device *pdev)
{
struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&lp3943_gpio->chip);
gpiochip_remove(&lp3943_gpio->chip);
return 0;
}
static const struct of_device_id lp3943_gpio_of_match[] = {

View File

@ -560,7 +560,7 @@ static int lpc32xx_gpio_probe(struct platform_device *pdev)
}
#ifdef CONFIG_OF
static struct of_device_id lpc32xx_gpio_of_match[] = {
static const struct of_device_id lpc32xx_gpio_of_match[] = {
{ .compatible = "nxp,lpc3220-gpio", },
{ },
};

View File

@ -25,9 +25,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
@ -62,7 +60,6 @@
struct lp_gpio {
struct gpio_chip chip;
struct irq_domain *domain;
struct platform_device *pdev;
spinlock_t lock;
unsigned long reg_base;
@ -151,7 +148,8 @@ static void lp_gpio_free(struct gpio_chip *chip, unsigned offset)
static int lp_irq_type(struct irq_data *d, unsigned type)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
u32 hwirq = irqd_to_hwirq(d);
unsigned long flags;
u32 value;
@ -236,16 +234,11 @@ static int lp_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip);
return irq_create_mapping(lg->domain, offset);
}
static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)
{
struct irq_data *data = irq_desc_get_irq_data(desc);
struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
struct irq_chip *chip = irq_data_get_irq_chip(data);
u32 base, pin, mask;
unsigned long reg, ena, pending;
@ -262,7 +255,7 @@ static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)
mask = BIT(pin);
/* Clear before handling so we don't lose an edge */
outl(mask, reg);
irq = irq_find_mapping(lg->domain, base + pin);
irq = irq_find_mapping(lg->chip.irqdomain, base + pin);
generic_handle_irq(irq);
}
}
@ -279,7 +272,8 @@ static void lp_irq_mask(struct irq_data *d)
static void lp_irq_enable(struct irq_data *d)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
@ -291,7 +285,8 @@ static void lp_irq_enable(struct irq_data *d)
static void lp_irq_disable(struct irq_data *d)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip);
u32 hwirq = irqd_to_hwirq(d);
unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE);
unsigned long flags;
@ -301,26 +296,6 @@ static void lp_irq_disable(struct irq_data *d)
spin_unlock_irqrestore(&lg->lock, flags);
}
static int lp_irq_reqres(struct irq_data *d)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) {
dev_err(lg->chip.dev,
"unable to lock HW IRQ %lu for IRQ\n",
irqd_to_hwirq(d));
return -EINVAL;
}
return 0;
}
static void lp_irq_relres(struct irq_data *d)
{
struct lp_gpio *lg = irq_data_get_irq_chip_data(d);
gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d));
}
static struct irq_chip lp_irqchip = {
.name = "LP-GPIO",
.irq_mask = lp_irq_mask,
@ -328,8 +303,6 @@ static struct irq_chip lp_irqchip = {
.irq_enable = lp_irq_enable,
.irq_disable = lp_irq_disable,
.irq_set_type = lp_irq_type,
.irq_request_resources = lp_irq_reqres,
.irq_release_resources = lp_irq_relres,
.flags = IRQCHIP_SKIP_SET_WAKE,
};
@ -348,22 +321,6 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg)
}
}
static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct lp_gpio *lg = d->host_data;
irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq);
irq_set_chip_data(irq, lg);
irq_set_irq_type(irq, IRQ_TYPE_NONE);
return 0;
}
static const struct irq_domain_ops lp_gpio_irq_ops = {
.map = lp_gpio_irq_map,
};
static int lp_gpio_probe(struct platform_device *pdev)
{
struct lp_gpio *lg;
@ -371,7 +328,6 @@ static int lp_gpio_probe(struct platform_device *pdev)
struct resource *io_rc, *irq_rc;
struct device *dev = &pdev->dev;
unsigned long reg_len;
unsigned hwirq;
int ret = -ENODEV;
lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
@ -414,27 +370,28 @@ static int lp_gpio_probe(struct platform_device *pdev)
gc->can_sleep = false;
gc->dev = dev;
/* set up interrupts */
if (irq_rc && irq_rc->start) {
hwirq = irq_rc->start;
gc->to_irq = lp_gpio_to_irq;
lg->domain = irq_domain_add_linear(NULL, LP_NUM_GPIO,
&lp_gpio_irq_ops, lg);
if (!lg->domain)
return -ENXIO;
lp_gpio_irq_init_hw(lg);
irq_set_handler_data(hwirq, lg);
irq_set_chained_handler(hwirq, lp_gpio_irq_handler);
}
ret = gpiochip_add(gc);
if (ret) {
dev_err(dev, "failed adding lp-gpio chip\n");
return ret;
}
/* set up interrupts */
if (irq_rc && irq_rc->start) {
lp_gpio_irq_init_hw(lg);
ret = gpiochip_irqchip_add(gc, &lp_irqchip, 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, &lp_irqchip,
(unsigned)irq_rc->start,
lp_gpio_irq_handler);
}
pm_runtime_enable(dev);
return 0;
@ -465,11 +422,8 @@ MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match);
static int lp_gpio_remove(struct platform_device *pdev)
{
struct lp_gpio *lg = platform_get_drvdata(pdev);
int err;
pm_runtime_disable(&pdev->dev);
err = gpiochip_remove(&lg->chip);
if (err)
dev_warn(&pdev->dev, "failed to remove gpio_chip.\n");
gpiochip_remove(&lg->chip);
return 0;
}

View File

@ -228,21 +228,16 @@ EXPORT_SYMBOL_GPL(__max730x_probe);
int __max730x_remove(struct device *dev)
{
struct max7301 *ts = dev_get_drvdata(dev);
int ret;
if (ts == NULL)
return -ENODEV;
/* Power down the chip and disable IRQ output */
ts->write(dev, 0x04, 0x00);
ret = gpiochip_remove(&ts->chip);
if (!ret)
mutex_destroy(&ts->lock);
else
dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
return ret;
gpiochip_remove(&ts->chip);
mutex_destroy(&ts->lock);
kfree(ts);
return 0;
}
EXPORT_SYMBOL_GPL(__max730x_remove);

View File

@ -676,12 +676,7 @@ static int max732x_remove(struct i2c_client *client)
}
}
ret = gpiochip_remove(&chip->gpio_chip);
if (ret) {
dev_err(&client->dev, "%s failed, %d\n",
"gpiochip_remove()", ret);
return ret;
}
gpiochip_remove(&chip->gpio_chip);
max732x_irq_teardown(chip);

View File

@ -149,20 +149,15 @@ exit_destroy:
static int mc33880_remove(struct spi_device *spi)
{
struct mc33880 *mc;
int ret;
mc = spi_get_drvdata(spi);
if (mc == NULL)
return -ENODEV;
ret = gpiochip_remove(&mc->chip);
if (!ret)
mutex_destroy(&mc->lock);
else
dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
ret);
gpiochip_remove(&mc->chip);
mutex_destroy(&mc->lock);
return ret;
return 0;
}
static struct spi_driver mc33880_driver = {

View File

@ -118,7 +118,8 @@ static int mc9s08dz60_remove(struct i2c_client *client)
mc9s = i2c_get_clientdata(client);
return gpiochip_remove(&mc9s->chip);
gpiochip_remove(&mc9s->chip);
return 0;
}
static const struct i2c_device_id mc9s08dz60_id[] = {

View File

@ -812,16 +812,14 @@ fail:
static int mcp230xx_remove(struct i2c_client *client)
{
struct mcp23s08 *mcp = i2c_get_clientdata(client);
int status;
if (client->irq && mcp->irq_controller)
mcp23s08_irq_teardown(mcp);
status = gpiochip_remove(&mcp->chip);
if (status == 0)
kfree(mcp);
gpiochip_remove(&mcp->chip);
kfree(mcp);
return status;
return 0;
}
static const struct i2c_device_id mcp230xx_id[] = {
@ -960,13 +958,10 @@ static int mcp23s08_probe(struct spi_device *spi)
fail:
for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
int tmp;
if (!data->mcp[addr])
continue;
tmp = gpiochip_remove(&data->mcp[addr]->chip);
if (tmp < 0)
dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
gpiochip_remove(&data->mcp[addr]->chip);
}
kfree(data);
return status;
@ -976,23 +971,16 @@ static int mcp23s08_remove(struct spi_device *spi)
{
struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
unsigned addr;
int status = 0;
for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
int tmp;
if (!data->mcp[addr])
continue;
tmp = gpiochip_remove(&data->mcp[addr]->chip);
if (tmp < 0) {
dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
status = tmp;
}
gpiochip_remove(&data->mcp[addr]->chip);
}
if (status == 0)
kfree(data);
return status;
kfree(data);
return 0;
}
static const struct spi_device_id mcp23s08_ids[] = {

View File

@ -497,8 +497,7 @@ err_irq_alloc_descs:
err_gpiochip_add:
while (--i >= 0) {
chip--;
if (gpiochip_remove(&chip->gpio))
dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i);
gpiochip_remove(&chip->gpio);
}
kfree(chip_save);
@ -519,7 +518,6 @@ err_pci_enable:
static void ioh_gpio_remove(struct pci_dev *pdev)
{
int err;
int i;
struct ioh_gpio *chip = pci_get_drvdata(pdev);
void *chip_save;
@ -530,9 +528,7 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
for (i = 0; i < 8; i++, chip++) {
irq_free_descs(chip->irq_base, num_ports[i]);
err = gpiochip_remove(&chip->gpio);
if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n");
gpiochip_remove(&chip->gpio);
}
chip = chip_save;

View File

@ -438,10 +438,7 @@ MODULE_DEVICE_TABLE(of, msm_gpio_of_match);
static int msm_gpio_remove(struct platform_device *dev)
{
int ret = gpiochip_remove(&msm_gpio.gpio_chip);
if (ret < 0)
return ret;
gpiochip_remove(&msm_gpio.gpio_chip);
irq_set_handler(msm_gpio.summary_irq, NULL);

View File

@ -485,7 +485,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
out_irqdesc_free:
irq_free_descs(irq_base, 32);
out_gpiochip_remove:
WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
gpiochip_remove(&port->bgc.gc);
out_bgpio_remove:
bgpio_remove(&port->bgc);
out_bgio:

View File

@ -129,7 +129,8 @@ out:
static int octeon_gpio_remove(struct platform_device *pdev)
{
struct gpio_chip *chip = pdev->dev.platform_data;
return gpiochip_remove(chip);
gpiochip_remove(chip);
return 0;
}
static struct of_device_id octeon_gpio_match[] = {

View File

@ -24,7 +24,6 @@
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/gpio.h>
#include <linux/bitops.h>
#include <linux/platform_data/gpio-omap.h>
@ -89,18 +88,19 @@ struct gpio_bank {
#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
#define LINE_USED(line, offset) (line & (BIT(offset)))
static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
static int omap_irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
{
return bank->chip.base + gpio_irq;
}
static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)
static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
return container_of(chip, struct gpio_bank, chip);
}
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio,
int is_input)
{
void __iomem *reg = bank->base;
u32 l;
@ -117,7 +117,8 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
/* set data out value using dedicate set/clear register */
static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, int gpio,
int enable)
{
void __iomem *reg = bank->base;
u32 l = GPIO_BIT(bank, gpio);
@ -134,7 +135,8 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
}
/* set data out value using mask register */
static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
static void omap_set_gpio_dataout_mask(struct gpio_bank *bank, int gpio,
int enable)
{
void __iomem *reg = bank->base + bank->regs->dataout;
u32 gpio_bit = GPIO_BIT(bank, gpio);
@ -149,21 +151,21 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
bank->context.dataout = l;
}
static int _get_gpio_datain(struct gpio_bank *bank, int offset)
static int omap_get_gpio_datain(struct gpio_bank *bank, int offset)
{
void __iomem *reg = bank->base + bank->regs->datain;
return (readl_relaxed(reg) & (BIT(offset))) != 0;
}
static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)
{
void __iomem *reg = bank->base + bank->regs->dataout;
return (readl_relaxed(reg) & (BIT(offset))) != 0;
}
static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
{
int l = readl_relaxed(base + reg);
@ -175,7 +177,7 @@ static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
writel_relaxed(l, base + reg);
}
static inline void _gpio_dbck_enable(struct gpio_bank *bank)
static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
{
if (bank->dbck_enable_mask && !bank->dbck_enabled) {
clk_prepare_enable(bank->dbck);
@ -186,7 +188,7 @@ static inline void _gpio_dbck_enable(struct gpio_bank *bank)
}
}
static inline void _gpio_dbck_disable(struct gpio_bank *bank)
static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
{
if (bank->dbck_enable_mask && bank->dbck_enabled) {
/*
@ -202,7 +204,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
}
/**
* _set_gpio_debounce - low level gpio debounce time
* omap2_set_gpio_debounce - low level gpio debounce time
* @bank: the gpio bank we're acting upon
* @gpio: the gpio number on this @gpio
* @debounce: debounce time to use
@ -210,8 +212,8 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
* OMAP's debounce time is in 31us steps so we need
* to convert and round up to the closest unit.
*/
static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
unsigned debounce)
static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
unsigned debounce)
{
void __iomem *reg;
u32 val;
@ -252,7 +254,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
* used within _gpio_dbck_enable() is still not initialized at
* that point. Therefore we have to enable dbck here.
*/
_gpio_dbck_enable(bank);
omap_gpio_dbck_enable(bank);
if (bank->dbck_enable_mask) {
bank->context.debounce = debounce;
bank->context.debounce_en = val;
@ -260,7 +262,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
}
/**
* _clear_gpio_debounce - clear debounce settings for a gpio
* omap_clear_gpio_debounce - clear debounce settings for a gpio
* @bank: the gpio bank we're acting upon
* @gpio: the gpio number on this @gpio
*
@ -269,7 +271,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
* time too. The debounce clock will also be disabled when calling this function
* if this is the only gpio in the bank using debounce.
*/
static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
{
u32 gpio_bit = GPIO_BIT(bank, gpio);
@ -293,20 +295,20 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
}
}
static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
unsigned trigger)
{
void __iomem *base = bank->base;
u32 gpio_bit = BIT(gpio);
_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
trigger & IRQ_TYPE_LEVEL_LOW);
_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
trigger & IRQ_TYPE_LEVEL_HIGH);
_gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
trigger & IRQ_TYPE_EDGE_RISING);
_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
trigger & IRQ_TYPE_EDGE_FALLING);
omap_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
trigger & IRQ_TYPE_LEVEL_LOW);
omap_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit,
trigger & IRQ_TYPE_LEVEL_HIGH);
omap_gpio_rmw(base, bank->regs->risingdetect, gpio_bit,
trigger & IRQ_TYPE_EDGE_RISING);
omap_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit,
trigger & IRQ_TYPE_EDGE_FALLING);
bank->context.leveldetect0 =
readl_relaxed(bank->base + bank->regs->leveldetect0);
@ -318,7 +320,7 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
readl_relaxed(bank->base + bank->regs->fallingdetect);
if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
}
@ -354,7 +356,7 @@ exit:
* This only applies to chips that can't do both rising and falling edge
* detection at once. For all other chips, this function is a noop.
*/
static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
{
void __iomem *reg = bank->base;
u32 l = 0;
@ -373,18 +375,18 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
writel_relaxed(l, reg);
}
#else
static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {}
#endif
static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
unsigned trigger)
static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio,
unsigned trigger)
{
void __iomem *reg = bank->base;
void __iomem *base = bank->base;
u32 l = 0;
if (bank->regs->leveldetect0 && bank->regs->wkup_en) {
set_gpio_trigger(bank, gpio, trigger);
omap_set_gpio_trigger(bank, gpio, trigger);
} else if (bank->regs->irqctrl) {
reg += bank->regs->irqctrl;
@ -414,7 +416,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
l |= BIT(gpio << 1);
/* Enable wake-up during idle for dynamic tick */
_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
omap_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
writel_relaxed(l, reg);
@ -422,7 +424,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
return 0;
}
static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset)
{
if (bank->regs->pinctrl) {
void __iomem *reg = bank->base + bank->regs->pinctrl;
@ -443,7 +445,7 @@ static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
}
}
static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset)
{
void __iomem *base = bank->base;
@ -451,7 +453,7 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
!LINE_USED(bank->mod_usage, offset) &&
!LINE_USED(bank->irq_usage, offset)) {
/* Disable wake-up during idle for dynamic tick */
_gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
omap_gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
}
@ -468,16 +470,16 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
}
}
static int gpio_is_input(struct gpio_bank *bank, int mask)
static int omap_gpio_is_input(struct gpio_bank *bank, int mask)
{
void __iomem *reg = bank->base + bank->regs->direction;
return readl_relaxed(reg) & mask;
}
static int gpio_irq_type(struct irq_data *d, unsigned type)
static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
{
struct gpio_bank *bank = _irq_data_get_bank(d);
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned gpio = 0;
int retval;
unsigned long flags;
@ -492,7 +494,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
#endif
if (!gpio)
gpio = irq_to_gpio(bank, d->hwirq);
gpio = omap_irq_to_gpio(bank, d->hwirq);
if (type & ~IRQ_TYPE_SENSE_MASK)
return -EINVAL;
@ -503,11 +505,11 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
spin_lock_irqsave(&bank->lock, flags);
offset = GPIO_INDEX(bank, gpio);
retval = _set_gpio_triggering(bank, offset, type);
retval = omap_set_gpio_triggering(bank, offset, type);
if (!LINE_USED(bank->mod_usage, offset)) {
_enable_gpio_module(bank, offset);
_set_gpio_direction(bank, offset, 1);
} else if (!gpio_is_input(bank, BIT(offset))) {
omap_enable_gpio_module(bank, offset);
omap_set_gpio_direction(bank, offset, 1);
} else if (!omap_gpio_is_input(bank, BIT(offset))) {
spin_unlock_irqrestore(&bank->lock, flags);
return -EINVAL;
}
@ -523,7 +525,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
return retval;
}
static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
static void omap_clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
@ -540,12 +542,12 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
readl_relaxed(reg);
}
static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
static inline void omap_clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
{
_clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
omap_clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
}
static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank)
{
void __iomem *reg = bank->base;
u32 l;
@ -559,7 +561,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
return l;
}
static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
u32 l;
@ -581,7 +583,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
writel_relaxed(l, reg);
}
static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
u32 l;
@ -603,12 +605,13 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
writel_relaxed(l, reg);
}
static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
static inline void omap_set_gpio_irqenable(struct gpio_bank *bank, int gpio,
int enable)
{
if (enable)
_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
omap_enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
else
_disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
omap_disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
}
/*
@ -619,7 +622,7 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
* enabled. When system is suspended, only selected GPIO interrupts need
* to have wake-up enabled.
*/
static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
static int omap_set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
{
u32 gpio_bit = GPIO_BIT(bank, gpio);
unsigned long flags;
@ -642,22 +645,22 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
return 0;
}
static void _reset_gpio(struct gpio_bank *bank, int gpio)
static void omap_reset_gpio(struct gpio_bank *bank, int gpio)
{
_set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
_set_gpio_irqenable(bank, gpio, 0);
_clear_gpio_irqstatus(bank, gpio);
_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
_clear_gpio_debounce(bank, gpio);
omap_set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
omap_set_gpio_irqenable(bank, gpio, 0);
omap_clear_gpio_irqstatus(bank, gpio);
omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
omap_clear_gpio_debounce(bank, gpio);
}
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
{
struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
return _set_gpio_wakeup(bank, gpio, enable);
return omap_set_gpio_wakeup(bank, gpio, enable);
}
static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@ -678,8 +681,8 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
* not already been requested.
*/
if (!LINE_USED(bank->irq_usage, offset)) {
_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
_enable_gpio_module(bank, offset);
omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
omap_enable_gpio_module(bank, offset);
}
bank->mod_usage |= BIT(offset);
spin_unlock_irqrestore(&bank->lock, flags);
@ -694,8 +697,8 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
spin_lock_irqsave(&bank->lock, flags);
bank->mod_usage &= ~(BIT(offset));
_disable_gpio_module(bank, offset);
_reset_gpio(bank, bank->chip.base + offset);
omap_disable_gpio_module(bank, offset);
omap_reset_gpio(bank, bank->chip.base + offset);
spin_unlock_irqrestore(&bank->lock, flags);
/*
@ -715,7 +718,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
* line's interrupt handler has been run, we may miss some nested
* interrupts.
*/
static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{
void __iomem *isr_reg = NULL;
u32 isr;
@ -738,7 +741,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
u32 isr_saved, level_mask = 0;
u32 enabled;
enabled = _get_gpio_irqbank_mask(bank);
enabled = omap_get_gpio_irqbank_mask(bank);
isr_saved = isr = readl_relaxed(isr_reg) & enabled;
if (bank->level_mask)
@ -747,9 +750,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
/* clear edge sensitive interrupts before handler(s) are
called so that we don't miss any interrupt occurred while
executing them */
_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask);
omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
/* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */
@ -773,7 +776,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
* This will be indicated in the bank toggle_mask.
*/
if (bank->toggle_mask & (BIT(bit)))
_toggle_gpio_edge_triggering(bank, bit);
omap_toggle_gpio_edge_triggering(bank, bit);
generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
bit));
@ -789,18 +792,18 @@ exit:
pm_runtime_put(bank->dev);
}
static void gpio_irq_shutdown(struct irq_data *d)
static void omap_gpio_irq_shutdown(struct irq_data *d)
{
struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
unsigned long flags;
unsigned offset = GPIO_INDEX(bank, gpio);
spin_lock_irqsave(&bank->lock, flags);
gpio_unlock_as_irq(&bank->chip, offset);
bank->irq_usage &= ~(BIT(offset));
_disable_gpio_module(bank, offset);
_reset_gpio(bank, gpio);
omap_disable_gpio_module(bank, offset);
omap_reset_gpio(bank, gpio);
spin_unlock_irqrestore(&bank->lock, flags);
/*
@ -811,57 +814,57 @@ static void gpio_irq_shutdown(struct irq_data *d)
pm_runtime_put(bank->dev);
}
static void gpio_ack_irq(struct irq_data *d)
static void omap_gpio_ack_irq(struct irq_data *d)
{
struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
_clear_gpio_irqstatus(bank, gpio);
omap_clear_gpio_irqstatus(bank, gpio);
}
static void gpio_mask_irq(struct irq_data *d)
static void omap_gpio_mask_irq(struct irq_data *d)
{
struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
unsigned long flags;
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_irqenable(bank, gpio, 0);
_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
omap_set_gpio_irqenable(bank, gpio, 0);
omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
spin_unlock_irqrestore(&bank->lock, flags);
}
static void gpio_unmask_irq(struct irq_data *d)
static void omap_gpio_unmask_irq(struct irq_data *d)
{
struct gpio_bank *bank = _irq_data_get_bank(d);
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
unsigned int irq_mask = GPIO_BIT(bank, gpio);
u32 trigger = irqd_get_trigger_type(d);
unsigned long flags;
spin_lock_irqsave(&bank->lock, flags);
if (trigger)
_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
omap_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
/* For level-triggered GPIOs, the clearing must be done after
* the HW source is cleared, thus after the handler has run */
if (bank->level_mask & irq_mask) {
_set_gpio_irqenable(bank, gpio, 0);
_clear_gpio_irqstatus(bank, gpio);
omap_set_gpio_irqenable(bank, gpio, 0);
omap_clear_gpio_irqstatus(bank, gpio);
}
_set_gpio_irqenable(bank, gpio, 1);
omap_set_gpio_irqenable(bank, gpio, 1);
spin_unlock_irqrestore(&bank->lock, flags);
}
static struct irq_chip gpio_irq_chip = {
.name = "GPIO",
.irq_shutdown = gpio_irq_shutdown,
.irq_ack = gpio_ack_irq,
.irq_mask = gpio_mask_irq,
.irq_unmask = gpio_unmask_irq,
.irq_set_type = gpio_irq_type,
.irq_set_wake = gpio_wake_enable,
.irq_shutdown = omap_gpio_irq_shutdown,
.irq_ack = omap_gpio_ack_irq,
.irq_mask = omap_gpio_mask_irq,
.irq_unmask = omap_gpio_unmask_irq,
.irq_set_type = omap_gpio_irq_type,
.irq_set_wake = omap_gpio_wake_enable,
};
/*---------------------------------------------------------------------*/
@ -918,7 +921,7 @@ static struct platform_device omap_mpuio_device = {
/* could list the /proc/iomem resources */
};
static inline void mpuio_init(struct gpio_bank *bank)
static inline void omap_mpuio_init(struct gpio_bank *bank)
{
platform_set_drvdata(&omap_mpuio_device, bank);
@ -928,7 +931,7 @@ static inline void mpuio_init(struct gpio_bank *bank)
/*---------------------------------------------------------------------*/
static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
unsigned long flags;
@ -943,19 +946,19 @@ static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
return dir;
}
static int gpio_input(struct gpio_chip *chip, unsigned offset)
static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_direction(bank, offset, 1);
omap_set_gpio_direction(bank, offset, 1);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
static int gpio_get(struct gpio_chip *chip, unsigned offset)
static int omap_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct gpio_bank *bank;
u32 mask;
@ -963,13 +966,13 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
bank = container_of(chip, struct gpio_bank, chip);
mask = (BIT(offset));
if (gpio_is_input(bank, mask))
return _get_gpio_datain(bank, offset);
if (omap_gpio_is_input(bank, mask))
return omap_get_gpio_datain(bank, offset);
else
return _get_gpio_dataout(bank, offset);
return omap_get_gpio_dataout(bank, offset);
}
static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
unsigned long flags;
@ -977,13 +980,13 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
bank->set_dataout(bank, offset, value);
_set_gpio_direction(bank, offset, 0);
omap_set_gpio_direction(bank, offset, 0);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
unsigned debounce)
static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
unsigned debounce)
{
struct gpio_bank *bank;
unsigned long flags;
@ -991,13 +994,13 @@ static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_debounce(bank, offset, debounce);
omap2_set_gpio_debounce(bank, offset, debounce);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_bank *bank;
unsigned long flags;
@ -1025,11 +1028,6 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank)
called = true;
}
/* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
static void omap_gpio_mod_init(struct gpio_bank *bank)
{
void __iomem *base = bank->base;
@ -1043,8 +1041,10 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
return;
}
_gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv);
_gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv);
omap_gpio_rmw(base, bank->regs->irqenable, l,
bank->regs->irqenable_inv);
omap_gpio_rmw(base, bank->regs->irqstatus, l,
!bank->regs->irqenable_inv);
if (bank->regs->debounce_en)
writel_relaxed(0, base + bank->regs->debounce_en);
@ -1078,10 +1078,10 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
/* NOTE: No ack required, reading IRQ status clears it. */
ct->chip.irq_mask = irq_gc_mask_set_bit;
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
ct->chip.irq_set_type = gpio_irq_type;
ct->chip.irq_set_type = omap_gpio_irq_type;
if (bank->regs->wkup_en)
ct->chip.irq_set_wake = gpio_wake_enable;
ct->chip.irq_set_wake = omap_gpio_wake_enable;
ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
@ -1101,12 +1101,12 @@ static int omap_gpio_chip_init(struct gpio_bank *bank)
*/
bank->chip.request = omap_gpio_request;
bank->chip.free = omap_gpio_free;
bank->chip.get_direction = gpio_get_direction;
bank->chip.direction_input = gpio_input;
bank->chip.get = gpio_get;
bank->chip.direction_output = gpio_output;
bank->chip.set_debounce = gpio_debounce;
bank->chip.set = gpio_set;
bank->chip.get_direction = omap_gpio_get_direction;
bank->chip.direction_input = omap_gpio_input;
bank->chip.get = omap_gpio_get;
bank->chip.direction_output = omap_gpio_output;
bank->chip.set_debounce = omap_gpio_debounce;
bank->chip.set = omap_gpio_set;
if (bank->is_mpuio) {
bank->chip.label = "mpuio";
if (bank->regs->wkup_en)
@ -1138,7 +1138,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank)
#endif
ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip,
irq_base, gpio_irq_handler,
irq_base, omap_gpio_irq_handler,
IRQ_TYPE_NONE);
if (ret) {
@ -1148,11 +1148,10 @@ static int omap_gpio_chip_init(struct gpio_bank *bank)
}
gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip,
bank->irq, gpio_irq_handler);
bank->irq, omap_gpio_irq_handler);
for (j = 0; j < bank->width; j++) {
int irq = irq_find_mapping(bank->chip.irqdomain, j);
irq_set_lockdep_class(irq, &gpio_lock_class);
if (bank->is_mpuio) {
omap_mpuio_alloc_gc(bank, irq, bank->width);
irq_set_chip_and_handler(irq, NULL, NULL);
@ -1217,9 +1216,9 @@ static int omap_gpio_probe(struct platform_device *pdev)
}
if (bank->regs->set_dataout && bank->regs->clr_dataout)
bank->set_dataout = _set_gpio_dataout_reg;
bank->set_dataout = omap_set_gpio_dataout_reg;
else
bank->set_dataout = _set_gpio_dataout_mask;
bank->set_dataout = omap_set_gpio_dataout_mask;
spin_lock_init(&bank->lock);
@ -1238,7 +1237,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
pm_runtime_get_sync(bank->dev);
if (bank->is_mpuio)
mpuio_init(bank);
omap_mpuio_init(bank);
omap_gpio_mod_init(bank);
@ -1320,7 +1319,7 @@ update_gpio_context_count:
bank->context_loss_count =
bank->get_context_loss_count(bank->dev);
_gpio_dbck_disable(bank);
omap_gpio_dbck_disable(bank);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
@ -1351,7 +1350,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
bank->get_context_loss_count(bank->dev);
}
_gpio_dbck_enable(bank);
omap_gpio_dbck_enable(bank);
/*
* In ->runtime_suspend(), level-triggered, wakeup-enabled

View File

@ -210,7 +210,8 @@ static int palmas_gpio_remove(struct platform_device *pdev)
{
struct palmas_gpio *palmas_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&palmas_gpio->gpio_chip);
gpiochip_remove(&palmas_gpio->gpio_chip);
return 0;
}
static struct platform_driver palmas_gpio_driver = {

View File

@ -765,12 +765,7 @@ static int pca953x_remove(struct i2c_client *client)
}
}
ret = gpiochip_remove(&chip->gpio_chip);
if (ret) {
dev_err(&client->dev, "%s failed, %d\n",
"gpiochip_remove()", ret);
return ret;
}
gpiochip_remove(&chip->gpio_chip);
return 0;
}

View File

@ -444,9 +444,7 @@ static int pcf857x_remove(struct i2c_client *client)
if (client->irq)
pcf857x_irq_domain_cleanup(gpio);
status = gpiochip_remove(&gpio->chip);
if (status)
dev_err(&client->dev, "%s --> %d\n", "remove", status);
gpiochip_remove(&gpio->chip);
return status;
}

View File

@ -426,9 +426,7 @@ end:
err_request_irq:
irq_free_descs(irq_base, gpio_pins[chip->ioh]);
if (gpiochip_remove(&chip->gpio))
dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
gpiochip_remove(&chip->gpio);
err_gpiochip_add:
pci_iounmap(pdev, chip->base);
@ -447,7 +445,6 @@ err_pci_enable:
static void pch_gpio_remove(struct pci_dev *pdev)
{
int err;
struct pch_gpio *chip = pci_get_drvdata(pdev);
if (chip->irq_base != -1) {
@ -456,10 +453,7 @@ static void pch_gpio_remove(struct pci_dev *pdev)
irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]);
}
err = gpiochip_remove(&chip->gpio);
if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n");
gpiochip_remove(&chip->gpio);
pci_iounmap(pdev, chip->base);
pci_release_regions(pdev);
pci_disable_device(pdev);

View File

@ -498,7 +498,7 @@ static int pxa_gpio_nums(struct platform_device *pdev)
}
#ifdef CONFIG_OF
static struct of_device_id pxa_gpio_dt_ids[] = {
static const struct of_device_id pxa_gpio_dt_ids[] = {
{ .compatible = "intel,pxa25x-gpio", .data = &pxa25x_id, },
{ .compatible = "intel,pxa26x-gpio", .data = &pxa26x_id, },
{ .compatible = "intel,pxa27x-gpio", .data = &pxa27x_id, },
@ -649,6 +649,11 @@ static int pxa_gpio_probe(struct platform_device *pdev)
handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
} else {
if (irq0 > 0)
irq_set_chained_handler(irq0, pxa_gpio_demux_handler);
if (irq1 > 0)
irq_set_chained_handler(irq1, pxa_gpio_demux_handler);
}
irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler);

View File

@ -148,7 +148,8 @@ static int rc5t583_gpio_remove(struct platform_device *pdev)
{
struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&rc5t583_gpio->gpio_chip);
gpiochip_remove(&rc5t583_gpio->gpio_chip);
return 0;
}
static struct platform_driver rc5t583_gpio_driver = {

View File

@ -240,9 +240,9 @@ static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset)
/* testing on r8a7790 shows that INDT does not show correct pin state
* when configured as output, so use OUTDT in case of output pins */
if (gpio_rcar_read(gpio_to_priv(chip), INOUTSEL) & bit)
return (int)(gpio_rcar_read(gpio_to_priv(chip), OUTDT) & bit);
return !!(gpio_rcar_read(gpio_to_priv(chip), OUTDT) & bit);
else
return (int)(gpio_rcar_read(gpio_to_priv(chip), INDT) & bit);
return !!(gpio_rcar_read(gpio_to_priv(chip), INDT) & bit);
}
static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value)
@ -472,11 +472,8 @@ err0:
static int gpio_rcar_remove(struct platform_device *pdev)
{
struct gpio_rcar_priv *p = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&p->gpio_chip);
if (ret)
return ret;
gpiochip_remove(&p->gpio_chip);
irq_domain_remove(p->irq_domain);
pm_runtime_put(&pdev->dev);

View File

@ -199,14 +199,11 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
static int rdc321x_gpio_remove(struct platform_device *pdev)
{
int ret;
struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
if (ret)
dev_err(&pdev->dev, "failed to unregister chip\n");
gpiochip_remove(&rdc321x_gpio_dev->chip);
return ret;
return 0;
}
static struct platform_driver rdc321x_gpio_driver = {

View File

@ -290,8 +290,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
return 0;
err_sch_gpio_resume:
if (gpiochip_remove(&sch_gpio_core))
dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
gpiochip_remove(&sch_gpio_core);
err_sch_gpio_core:
release_region(res->start, resource_size(res));
@ -304,23 +303,14 @@ static int sch_gpio_remove(struct platform_device *pdev)
{
struct resource *res;
if (gpio_ba) {
int err;
err = gpiochip_remove(&sch_gpio_core);
if (err)
dev_err(&pdev->dev, "%s failed, %d\n",
"gpiochip_remove()", err);
err = gpiochip_remove(&sch_gpio_resume);
if (err)
dev_err(&pdev->dev, "%s failed, %d\n",
"gpiochip_remove()", err);
gpiochip_remove(&sch_gpio_core);
gpiochip_remove(&sch_gpio_resume);
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(res->start, resource_size(res));
gpio_ba = 0;
return err;
}
return 0;

View File

@ -291,14 +291,12 @@ static int sch311x_gpio_remove(struct platform_device *pdev)
{
struct sch311x_pdev_data *pdata = pdev->dev.platform_data;
struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev);
int err, i;
int i;
release_region(pdata->runtime_reg + GP1, 6);
for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
err = gpiochip_remove(&priv->blocks[i].chip);
if (err)
return err;
gpiochip_remove(&priv->blocks[i].chip);
dev_info(&pdev->dev,
"SMSC SCH311x GPIO block %d unregistered.\n", i);
}

View File

@ -265,9 +265,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev)
free_irq(pdev->irq, sd);
irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
if (gpiochip_remove(&sd->bgpio.gc))
dev_err(&pdev->dev, "gpiochip_remove() failed.\n");
gpiochip_remove(&sd->bgpio.gc);
pci_release_region(pdev, GPIO_BAR);
iounmap(sd->gpio_pub_base);
pci_disable_device(pdev);

View File

@ -10,8 +10,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/mfd/stmpe.h>
@ -31,9 +29,7 @@ struct stmpe_gpio {
struct stmpe *stmpe;
struct device *dev;
struct mutex irq_lock;
struct irq_domain *domain;
unsigned norequest_mask;
/* Caches of interrupt control registers for bus_lock */
u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
@ -101,13 +97,6 @@ static int stmpe_gpio_direction_input(struct gpio_chip *chip,
return stmpe_set_bits(stmpe, reg, mask, 0);
}
static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
return irq_create_mapping(stmpe_gpio->domain, offset);
}
static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
{
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
@ -126,14 +115,14 @@ static struct gpio_chip template_chip = {
.get = stmpe_gpio_get,
.direction_output = stmpe_gpio_direction_output,
.set = stmpe_gpio_set,
.to_irq = stmpe_gpio_to_irq,
.request = stmpe_gpio_request,
.can_sleep = true,
};
static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@ -160,14 +149,16 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
static void stmpe_gpio_irq_lock(struct irq_data *d)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
mutex_lock(&stmpe_gpio->irq_lock);
}
static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
struct stmpe *stmpe = stmpe_gpio->stmpe;
int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8);
static const u8 regmap[] = {
@ -200,7 +191,8 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
static void stmpe_gpio_irq_mask(struct irq_data *d)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@ -210,7 +202,8 @@ static void stmpe_gpio_irq_mask(struct irq_data *d)
static void stmpe_gpio_irq_unmask(struct irq_data *d)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(gc);
int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@ -253,7 +246,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
while (stat) {
int bit = __ffs(stat);
int line = bank * 8 + bit;
int child_irq = irq_find_mapping(stmpe_gpio->domain,
int child_irq = irq_find_mapping(stmpe_gpio->chip.irqdomain,
line);
handle_nested_irq(child_irq);
@ -271,56 +264,6 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct stmpe_gpio *stmpe_gpio = d->host_data;
if (!stmpe_gpio)
return -EINVAL;
irq_set_chip_data(irq, stmpe_gpio);
irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
handle_simple_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
return 0;
}
static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
{
#ifdef CONFIG_ARM
set_irq_flags(irq, 0);
#endif
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
}
static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
.unmap = stmpe_gpio_irq_unmap,
.map = stmpe_gpio_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,
struct device_node *np)
{
stmpe_gpio->domain = irq_domain_add_simple(np,
stmpe_gpio->chip.ngpio, 0,
&stmpe_gpio_irq_simple_ops, stmpe_gpio);
if (!stmpe_gpio->domain) {
dev_err(stmpe_gpio->dev, "failed to create irqdomain\n");
return -ENOSYS;
}
return 0;
}
static int stmpe_gpio_probe(struct platform_device *pdev)
{
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
@ -358,30 +301,37 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
if (irq < 0)
dev_info(&pdev->dev,
"device configured in no-irq mode; "
"device configured in no-irq mode: "
"irqs are not available\n");
ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
if (ret)
goto out_free;
if (irq >= 0) {
ret = stmpe_gpio_irq_init(stmpe_gpio, np);
if (ret)
goto out_disable;
ret = request_threaded_irq(irq, NULL, stmpe_gpio_irq,
IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
if (irq > 0) {
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
stmpe_gpio_irq, IRQF_ONESHOT,
"stmpe-gpio", stmpe_gpio);
if (ret) {
dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
goto out_disable;
}
ret = gpiochip_irqchip_add(&stmpe_gpio->chip,
&stmpe_gpio_irq_chip,
0,
handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&pdev->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
}
ret = gpiochip_add(&stmpe_gpio->chip);
if (ret) {
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
goto out_freeirq;
goto out_disable;
}
if (pdata && pdata->setup)
@ -391,9 +341,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
return 0;
out_freeirq:
if (irq >= 0)
free_irq(irq, stmpe_gpio);
out_disable:
stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
out_free:
@ -406,24 +353,14 @@ static int stmpe_gpio_remove(struct platform_device *pdev)
struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
struct stmpe *stmpe = stmpe_gpio->stmpe;
struct stmpe_gpio_platform_data *pdata = stmpe->pdata->gpio;
int irq = platform_get_irq(pdev, 0);
int ret;
if (pdata && pdata->remove)
pdata->remove(stmpe, stmpe_gpio->chip.base);
ret = gpiochip_remove(&stmpe_gpio->chip);
if (ret < 0) {
dev_err(stmpe_gpio->dev,
"unable to remove gpiochip: %d\n", ret);
return ret;
}
gpiochip_remove(&stmpe_gpio->chip);
stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
if (irq >= 0)
free_irq(irq, stmpe_gpio);
kfree(stmpe_gpio);
return 0;

View File

@ -615,19 +615,16 @@ static int sx150x_probe(struct i2c_client *client,
return 0;
probe_fail_post_gpiochip_add:
WARN_ON(gpiochip_remove(&chip->gpio_chip) < 0);
gpiochip_remove(&chip->gpio_chip);
return rc;
}
static int sx150x_remove(struct i2c_client *client)
{
struct sx150x_chip *chip;
int rc;
chip = i2c_get_clientdata(client);
rc = gpiochip_remove(&chip->gpio_chip);
if (rc < 0)
return rc;
gpiochip_remove(&chip->gpio_chip);
if (chip->irq_summary >= 0)
sx150x_remove_irq_chip(chip);

View File

@ -172,7 +172,8 @@ static int syscon_gpio_remove(struct platform_device *pdev)
{
struct syscon_gpio_priv *priv = platform_get_drvdata(pdev);
return gpiochip_remove(&priv->chip);
gpiochip_remove(&priv->chip);
return 0;
}
static struct platform_driver syscon_gpio_driver = {

View File

@ -291,7 +291,6 @@ fail_ioremap:
static int __exit tb10x_gpio_remove(struct platform_device *pdev)
{
struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev);
int ret;
if (tb10x_gpio->gc.to_irq) {
irq_remove_generic_chip(tb10x_gpio->domain->gc->gc[0],
@ -300,9 +299,7 @@ static int __exit tb10x_gpio_remove(struct platform_device *pdev)
irq_domain_remove(tb10x_gpio->domain);
free_irq(tb10x_gpio->irq, tb10x_gpio);
}
ret = gpiochip_remove(&tb10x_gpio->gc);
if (ret)
return ret;
gpiochip_remove(&tb10x_gpio->gc);
return 0;
}

View File

@ -313,17 +313,11 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
int ret;
if (pdata && pdata->remove)
pdata->remove(tc3589x, tc3589x_gpio->chip.base);
ret = gpiochip_remove(&tc3589x_gpio->chip);
if (ret < 0) {
dev_err(tc3589x_gpio->dev,
"unable to remove gpiochip: %d\n", ret);
return ret;
}
gpiochip_remove(&tc3589x_gpio->chip);
return 0;
}

View File

@ -307,7 +307,6 @@ static int timbgpio_probe(struct platform_device *pdev)
static int timbgpio_remove(struct platform_device *pdev)
{
int err;
struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct timbgpio *tgpio = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
@ -323,9 +322,7 @@ static int timbgpio_remove(struct platform_device *pdev)
irq_set_handler_data(irq, NULL);
}
err = gpiochip_remove(&tgpio->gpio);
if (err)
printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
gpiochip_remove(&tgpio->gpio);
return 0;
}

View File

@ -137,7 +137,8 @@ static int tps6586x_gpio_remove(struct platform_device *pdev)
{
struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&tps6586x_gpio->gpio_chip);
gpiochip_remove(&tps6586x_gpio->gpio_chip);
return 0;
}
static struct platform_driver tps6586x_gpio_driver = {

View File

@ -190,7 +190,8 @@ static int tps65910_gpio_remove(struct platform_device *pdev)
{
struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&tps65910_gpio->gpio_chip);
gpiochip_remove(&tps65910_gpio->gpio_chip);
return 0;
}
static struct platform_driver tps65910_gpio_driver = {

View File

@ -117,7 +117,8 @@ static int tps65912_gpio_remove(struct platform_device *pdev)
{
struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&tps65912_gpio->gpio_chip);
gpiochip_remove(&tps65912_gpio->gpio_chip);
return 0;
}
static struct platform_driver tps65912_gpio_driver = {

View File

@ -427,8 +427,7 @@ static int ts5500_dio_probe(struct platform_device *pdev)
return 0;
cleanup:
if (gpiochip_remove(&priv->gpio_chip))
dev_err(dev, "failed to remove gpio chip\n");
gpiochip_remove(&priv->gpio_chip);
return ret;
}
@ -437,7 +436,8 @@ static int ts5500_dio_remove(struct platform_device *pdev)
struct ts5500_priv *priv = platform_get_drvdata(pdev);
ts5500_disable_irq(priv);
return gpiochip_remove(&priv->gpio_chip);
gpiochip_remove(&priv->gpio_chip);
return 0;
}
static struct platform_device_id ts5500_dio_ids[] = {

View File

@ -554,7 +554,7 @@ no_irqs:
platform_set_drvdata(pdev, priv);
if (pdata && pdata->setup) {
if (pdata->setup) {
int status;
status = pdata->setup(&pdev->dev, priv->gpio_chip.base,
@ -583,9 +583,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
}
}
status = gpiochip_remove(&priv->gpio_chip);
if (status < 0)
return status;
gpiochip_remove(&priv->gpio_chip);
if (is_module())
return 0;

View File

@ -111,7 +111,8 @@ static int gpo_twl6040_probe(struct platform_device *pdev)
static int gpo_twl6040_remove(struct platform_device *pdev)
{
return gpiochip_remove(&twl6040gpo_chip);
gpiochip_remove(&twl6040gpo_chip);
return 0;
}
/* Note: this hardware lives inside an I2C-based multi-function device. */

View File

@ -70,7 +70,7 @@ static int ucb1400_gpio_probe(struct platform_device *dev)
if (err)
goto err;
if (ucb && ucb->gpio_setup)
if (ucb->gpio_setup)
err = ucb->gpio_setup(&dev->dev, ucb->gc.ngpio);
err:
@ -89,7 +89,7 @@ static int ucb1400_gpio_remove(struct platform_device *dev)
return err;
}
err = gpiochip_remove(&ucb->gc);
gpiochip_remove(&ucb->gc);
return err;
}

View File

@ -446,8 +446,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
return ret;
err_gpiob:
if (gpiochip_remove(&vb_gpio->gpioa))
dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
gpiochip_remove(&vb_gpio->gpioa);
err_gpioa:
return ret;
@ -456,13 +455,10 @@ err_gpioa:
static int vprbrd_gpio_remove(struct platform_device *pdev)
{
struct vprbrd_gpio *vb_gpio = platform_get_drvdata(pdev);
int ret;
ret = gpiochip_remove(&vb_gpio->gpiob);
if (ret == 0)
ret = gpiochip_remove(&vb_gpio->gpioa);
gpiochip_remove(&vb_gpio->gpiob);
return ret;
return 0;
}
static struct platform_driver vprbrd_gpio_driver = {

View File

@ -515,7 +515,7 @@ static int giu_probe(struct platform_device *pdev)
struct resource *res;
unsigned int trigger, i, pin;
struct irq_chip *chip;
int irq, retval;
int irq, ret;
switch (pdev->id) {
case GPIO_50PINS_PULLUPDOWN:
@ -544,7 +544,11 @@ static int giu_probe(struct platform_device *pdev)
vr41xx_gpio_chip.dev = &pdev->dev;
retval = gpiochip_add(&vr41xx_gpio_chip);
ret = gpiochip_add(&vr41xx_gpio_chip);
if (!ret) {
iounmap(giu_base);
return -ENODEV;
}
giu_write(GIUINTENL, 0);
giu_write(GIUINTENH, 0);

View File

@ -288,8 +288,7 @@ static int vx855gpio_remove(struct platform_device *pdev)
struct vx855_gpio *vg = platform_get_drvdata(pdev);
struct resource *res;
if (gpiochip_remove(&vg->gpio))
dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
gpiochip_remove(&vg->gpio);
if (vg->gpi_reserved) {
res = platform_get_resource(pdev, IORESOURCE_IO, 0);

View File

@ -279,7 +279,8 @@ static int wm831x_gpio_remove(struct platform_device *pdev)
{
struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&wm831x_gpio->gpio_chip);
gpiochip_remove(&wm831x_gpio->gpio_chip);
return 0;
}
static struct platform_driver wm831x_gpio_driver = {

View File

@ -145,7 +145,8 @@ static int wm8350_gpio_remove(struct platform_device *pdev)
{
struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&wm8350_gpio->gpio_chip);
gpiochip_remove(&wm8350_gpio->gpio_chip);
return 0;
}
static struct platform_driver wm8350_gpio_driver = {

View File

@ -285,7 +285,8 @@ static int wm8994_gpio_remove(struct platform_device *pdev)
{
struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
return gpiochip_remove(&wm8994_gpio->gpio_chip);
gpiochip_remove(&wm8994_gpio->gpio_chip);
return 0;
}
static struct platform_driver wm8994_gpio_driver = {

View File

@ -0,0 +1,692 @@
/*
* Xilinx Zynq GPIO device driver
*
* Copyright (C) 2009 - 2014 Xilinx, Inc.
*
* 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/bitops.h>
#include <linux/clk.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#define DRIVER_NAME "zynq-gpio"
/* Maximum banks */
#define ZYNQ_GPIO_MAX_BANK 4
#define ZYNQ_GPIO_BANK0_NGPIO 32
#define ZYNQ_GPIO_BANK1_NGPIO 22
#define ZYNQ_GPIO_BANK2_NGPIO 32
#define ZYNQ_GPIO_BANK3_NGPIO 32
#define ZYNQ_GPIO_NR_GPIOS (ZYNQ_GPIO_BANK0_NGPIO + \
ZYNQ_GPIO_BANK1_NGPIO + \
ZYNQ_GPIO_BANK2_NGPIO + \
ZYNQ_GPIO_BANK3_NGPIO)
#define ZYNQ_GPIO_BANK0_PIN_MIN 0
#define ZYNQ_GPIO_BANK0_PIN_MAX (ZYNQ_GPIO_BANK0_PIN_MIN + \
ZYNQ_GPIO_BANK0_NGPIO - 1)
#define ZYNQ_GPIO_BANK1_PIN_MIN (ZYNQ_GPIO_BANK0_PIN_MAX + 1)
#define ZYNQ_GPIO_BANK1_PIN_MAX (ZYNQ_GPIO_BANK1_PIN_MIN + \
ZYNQ_GPIO_BANK1_NGPIO - 1)
#define ZYNQ_GPIO_BANK2_PIN_MIN (ZYNQ_GPIO_BANK1_PIN_MAX + 1)
#define ZYNQ_GPIO_BANK2_PIN_MAX (ZYNQ_GPIO_BANK2_PIN_MIN + \
ZYNQ_GPIO_BANK2_NGPIO - 1)
#define ZYNQ_GPIO_BANK3_PIN_MIN (ZYNQ_GPIO_BANK2_PIN_MAX + 1)
#define ZYNQ_GPIO_BANK3_PIN_MAX (ZYNQ_GPIO_BANK3_PIN_MIN + \
ZYNQ_GPIO_BANK3_NGPIO - 1)
/* Register offsets for the GPIO device */
/* LSW Mask & Data -WO */
#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK))
/* MSW Mask & Data -WO */
#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK) (0x004 + (8 * BANK))
/* Data Register-RW */
#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK) (0x060 + (4 * BANK))
/* Direction mode reg-RW */
#define ZYNQ_GPIO_DIRM_OFFSET(BANK) (0x204 + (0x40 * BANK))
/* Output enable reg-RW */
#define ZYNQ_GPIO_OUTEN_OFFSET(BANK) (0x208 + (0x40 * BANK))
/* Interrupt mask reg-RO */
#define ZYNQ_GPIO_INTMASK_OFFSET(BANK) (0x20C + (0x40 * BANK))
/* Interrupt enable reg-WO */
#define ZYNQ_GPIO_INTEN_OFFSET(BANK) (0x210 + (0x40 * BANK))
/* Interrupt disable reg-WO */
#define ZYNQ_GPIO_INTDIS_OFFSET(BANK) (0x214 + (0x40 * BANK))
/* Interrupt status reg-RO */
#define ZYNQ_GPIO_INTSTS_OFFSET(BANK) (0x218 + (0x40 * BANK))
/* Interrupt type reg-RW */
#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK) (0x21C + (0x40 * BANK))
/* Interrupt polarity reg-RW */
#define ZYNQ_GPIO_INTPOL_OFFSET(BANK) (0x220 + (0x40 * BANK))
/* Interrupt on any, reg-RW */
#define ZYNQ_GPIO_INTANY_OFFSET(BANK) (0x224 + (0x40 * BANK))
/* Disable all interrupts mask */
#define ZYNQ_GPIO_IXR_DISABLE_ALL 0xFFFFFFFF
/* Mid pin number of a bank */
#define ZYNQ_GPIO_MID_PIN_NUM 16
/* GPIO upper 16 bit mask */
#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000
/**
* struct zynq_gpio - gpio device private data structure
* @chip: instance of the gpio_chip
* @base_addr: base address of the GPIO device
* @clk: clock resource for this controller
*/
struct zynq_gpio {
struct gpio_chip chip;
void __iomem *base_addr;
struct clk *clk;
};
/**
* zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
* for a given pin in the GPIO device
* @pin_num: gpio pin number within the device
* @bank_num: an output parameter used to return the bank number of the gpio
* pin
* @bank_pin_num: an output parameter used to return pin number within a bank
* for the given gpio pin
*
* Returns the bank number and pin offset within the bank.
*/
static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
unsigned int *bank_num,
unsigned int *bank_pin_num)
{
switch (pin_num) {
case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
*bank_num = 0;
*bank_pin_num = pin_num;
break;
case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
*bank_num = 1;
*bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
break;
case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
*bank_num = 2;
*bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
break;
case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
*bank_num = 3;
*bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
break;
default:
WARN(true, "invalid GPIO pin number: %u", pin_num);
*bank_num = 0;
*bank_pin_num = 0;
break;
}
}
/**
* zynq_gpio_get_value - Get the state of the specified pin of GPIO device
* @chip: gpio_chip instance to be worked on
* @pin: gpio pin number within the device
*
* This function reads the state of the specified pin of the GPIO device.
*
* Return: 0 if the pin is low, 1 if pin is high.
*/
static int zynq_gpio_get_value(struct gpio_chip *chip, unsigned int pin)
{
u32 data;
unsigned int bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
data = readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
return (data >> bank_pin_num) & 1;
}
/**
* zynq_gpio_set_value - Modify the state of the pin with specified value
* @chip: gpio_chip instance to be worked on
* @pin: gpio pin number within the device
* @state: value used to modify the state of the specified pin
*
* This function calculates the register offset (i.e to lower 16 bits or
* upper 16 bits) based on the given pin number and sets the state of a
* gpio pin to the specified value. The state is either 0 or non-zero.
*/
static void zynq_gpio_set_value(struct gpio_chip *chip, unsigned int pin,
int state)
{
unsigned int reg_offset, bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
/* only 16 data bits in bit maskable reg */
bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
} else {
reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
}
/*
* get the 32 bit value to be written to the mask/data register where
* the upper 16 bits is the mask and lower 16 bits is the data
*/
state = !!state;
state = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
((state << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
writel_relaxed(state, gpio->base_addr + reg_offset);
}
/**
* zynq_gpio_dir_in - Set the direction of the specified GPIO pin as input
* @chip: gpio_chip instance to be worked on
* @pin: gpio pin number within the device
*
* This function uses the read-modify-write sequence to set the direction of
* the gpio pin as input.
*
* Return: 0 always
*/
static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
{
u32 reg;
unsigned int bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
/* bank 0 pins 7 and 8 are special and cannot be used as inputs */
if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
return -EINVAL;
/* clear the bit in direction mode reg to set the pin as input */
reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
reg &= ~BIT(bank_pin_num);
writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
return 0;
}
/**
* zynq_gpio_dir_out - Set the direction of the specified GPIO pin as output
* @chip: gpio_chip instance to be worked on
* @pin: gpio pin number within the device
* @state: value to be written to specified pin
*
* This function sets the direction of specified GPIO pin as output, configures
* the Output Enable register for the pin and uses zynq_gpio_set to set
* the state of the pin to the value specified.
*
* Return: 0 always
*/
static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
int state)
{
u32 reg;
unsigned int bank_num, bank_pin_num;
struct zynq_gpio *gpio = container_of(chip, struct zynq_gpio, chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num);
/* set the GPIO pin as output */
reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
reg |= BIT(bank_pin_num);
writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
/* configure the output enable reg for the pin */
reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
reg |= BIT(bank_pin_num);
writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
/* set the state of the pin */
zynq_gpio_set_value(chip, pin, state);
return 0;
}
/**
* zynq_gpio_irq_mask - Disable the interrupts for a gpio pin
* @irq_data: per irq and chip data passed down to chip functions
*
* This function calculates gpio pin number from irq number and sets the
* bit in the Interrupt Disable register of the corresponding bank to disable
* interrupts for that pin.
*/
static void zynq_gpio_irq_mask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
writel_relaxed(BIT(bank_pin_num),
gpio->base_addr + ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
}
/**
* zynq_gpio_irq_unmask - Enable the interrupts for a gpio pin
* @irq_data: irq data containing irq number of gpio pin for the interrupt
* to enable
*
* This function calculates the gpio pin number from irq number and sets the
* bit in the Interrupt Enable register of the corresponding bank to enable
* interrupts for that pin.
*/
static void zynq_gpio_irq_unmask(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
writel_relaxed(BIT(bank_pin_num),
gpio->base_addr + ZYNQ_GPIO_INTEN_OFFSET(bank_num));
}
/**
* zynq_gpio_irq_ack - Acknowledge the interrupt of a gpio pin
* @irq_data: irq data containing irq number of gpio pin for the interrupt
* to ack
*
* This function calculates gpio pin number from irq number and sets the bit
* in the Interrupt Status Register of the corresponding bank, to ACK the irq.
*/
static void zynq_gpio_irq_ack(struct irq_data *irq_data)
{
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
writel_relaxed(BIT(bank_pin_num),
gpio->base_addr + ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
}
/**
* zynq_gpio_irq_enable - Enable the interrupts for a gpio pin
* @irq_data: irq data containing irq number of gpio pin for the interrupt
* to enable
*
* Clears the INTSTS bit and unmasks the given interrrupt.
*/
static void zynq_gpio_irq_enable(struct irq_data *irq_data)
{
/*
* The Zynq GPIO controller does not disable interrupt detection when
* the interrupt is masked and only disables the propagation of the
* interrupt. This means when the controller detects an interrupt
* condition while the interrupt is logically disabled it will propagate
* that interrupt event once the interrupt is enabled. This will cause
* the interrupt consumer to see spurious interrupts to prevent this
* first make sure that the interrupt is not asserted and then enable
* it.
*/
zynq_gpio_irq_ack(irq_data);
zynq_gpio_irq_unmask(irq_data);
}
/**
* zynq_gpio_set_irq_type - Set the irq type for a gpio pin
* @irq_data: irq data containing irq number of gpio pin
* @type: interrupt type that is to be set for the gpio pin
*
* This function gets the gpio pin number and its bank from the gpio pin number
* and configures the INT_TYPE, INT_POLARITY and INT_ANY registers.
*
* Return: 0, negative error otherwise.
* TYPE-EDGE_RISING, INT_TYPE - 1, INT_POLARITY - 1, INT_ANY - 0;
* TYPE-EDGE_FALLING, INT_TYPE - 1, INT_POLARITY - 0, INT_ANY - 0;
* TYPE-EDGE_BOTH, INT_TYPE - 1, INT_POLARITY - NA, INT_ANY - 1;
* TYPE-LEVEL_HIGH, INT_TYPE - 0, INT_POLARITY - 1, INT_ANY - NA;
* TYPE-LEVEL_LOW, INT_TYPE - 0, INT_POLARITY - 0, INT_ANY - NA
*/
static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
{
u32 int_type, int_pol, int_any;
unsigned int device_pin_num, bank_num, bank_pin_num;
struct zynq_gpio *gpio = irq_data_get_irq_chip_data(irq_data);
device_pin_num = irq_data->hwirq;
zynq_gpio_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
int_type = readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
int_pol = readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
int_any = readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_INTANY_OFFSET(bank_num));
/*
* based on the type requested, configure the INT_TYPE, INT_POLARITY
* and INT_ANY registers
*/
switch (type) {
case IRQ_TYPE_EDGE_RISING:
int_type |= BIT(bank_pin_num);
int_pol |= BIT(bank_pin_num);
int_any &= ~BIT(bank_pin_num);
break;
case IRQ_TYPE_EDGE_FALLING:
int_type |= BIT(bank_pin_num);
int_pol &= ~BIT(bank_pin_num);
int_any &= ~BIT(bank_pin_num);
break;
case IRQ_TYPE_EDGE_BOTH:
int_type |= BIT(bank_pin_num);
int_any |= BIT(bank_pin_num);
break;
case IRQ_TYPE_LEVEL_HIGH:
int_type &= ~BIT(bank_pin_num);
int_pol |= BIT(bank_pin_num);
break;
case IRQ_TYPE_LEVEL_LOW:
int_type &= ~BIT(bank_pin_num);
int_pol &= ~BIT(bank_pin_num);
break;
default:
return -EINVAL;
}
writel_relaxed(int_type,
gpio->base_addr + ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
writel_relaxed(int_pol,
gpio->base_addr + ZYNQ_GPIO_INTPOL_OFFSET(bank_num));
writel_relaxed(int_any,
gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num));
return 0;
}
static int zynq_gpio_set_wake(struct irq_data *data, unsigned int on)
{
if (on)
zynq_gpio_irq_unmask(data);
else
zynq_gpio_irq_mask(data);
return 0;
}
/* irq chip descriptor */
static struct irq_chip zynq_gpio_irqchip = {
.name = DRIVER_NAME,
.irq_enable = zynq_gpio_irq_enable,
.irq_mask = zynq_gpio_irq_mask,
.irq_unmask = zynq_gpio_irq_unmask,
.irq_set_type = zynq_gpio_set_irq_type,
.irq_set_wake = zynq_gpio_set_wake,
};
/**
* zynq_gpio_irqhandler - IRQ handler for the gpio banks of a gpio device
* @irq: irq number of the gpio bank where interrupt has occurred
* @desc: irq descriptor instance of the 'irq'
*
* This function reads the Interrupt Status Register of each bank to get the
* gpio pin number which has triggered an interrupt. It then acks the triggered
* interrupt and calls the pin specific handler set by the higher layer
* application for that pin.
* Note: A bug is reported if no handler is set for the gpio pin.
*/
static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc)
{
u32 int_sts, int_enb;
unsigned int bank_num;
struct zynq_gpio *gpio = irq_get_handler_data(irq);
struct irq_chip *irqchip = irq_desc_get_chip(desc);
chained_irq_enter(irqchip, desc);
for (bank_num = 0; bank_num < ZYNQ_GPIO_MAX_BANK; bank_num++) {
int_sts = readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
int_enb = readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
int_sts &= ~int_enb;
if (int_sts) {
int offset;
unsigned long pending = int_sts;
for_each_set_bit(offset, &pending, 32) {
unsigned int gpio_irq =
irq_find_mapping(gpio->chip.irqdomain,
offset);
generic_handle_irq(gpio_irq);
}
/* clear IRQ in HW */
writel_relaxed(int_sts, gpio->base_addr +
ZYNQ_GPIO_INTSTS_OFFSET(bank_num));
}
}
chained_irq_exit(irqchip, desc);
}
static int __maybe_unused zynq_gpio_suspend(struct device *dev)
{
if (!device_may_wakeup(dev))
return pm_runtime_force_suspend(dev);
return 0;
}
static int __maybe_unused zynq_gpio_resume(struct device *dev)
{
if (!device_may_wakeup(dev))
return pm_runtime_force_resume(dev);
return 0;
}
static int __maybe_unused zynq_gpio_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct zynq_gpio *gpio = platform_get_drvdata(pdev);
clk_disable_unprepare(gpio->clk);
return 0;
}
static int __maybe_unused zynq_gpio_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct zynq_gpio *gpio = platform_get_drvdata(pdev);
return clk_prepare_enable(gpio->clk);
}
static int zynq_gpio_request(struct gpio_chip *chip, unsigned offset)
{
int ret;
ret = pm_runtime_get_sync(chip->dev);
/*
* If the device is already active pm_runtime_get() will return 1 on
* success, but gpio_request still needs to return 0.
*/
return ret < 0 ? ret : 0;
}
static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pm_runtime_put(chip->dev);
}
static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume)
SET_PM_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend,
zynq_gpio_runtime_resume, NULL)
};
/**
* zynq_gpio_probe - Initialization method for a zynq_gpio device
* @pdev: platform device instance
*
* This function allocates memory resources for the gpio device and registers
* all the banks of the device. It will also set up interrupts for the gpio
* pins.
* Note: Interrupts are disabled for all the banks during initialization.
*
* Return: 0 on success, negative error otherwise.
*/
static int zynq_gpio_probe(struct platform_device *pdev)
{
int ret, bank_num, irq;
struct zynq_gpio *gpio;
struct gpio_chip *chip;
struct resource *res;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
platform_set_drvdata(pdev, gpio);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gpio->base_addr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(gpio->base_addr))
return PTR_ERR(gpio->base_addr);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "invalid IRQ\n");
return irq;
}
/* configure the gpio chip */
chip = &gpio->chip;
chip->label = "zynq_gpio";
chip->owner = THIS_MODULE;
chip->dev = &pdev->dev;
chip->get = zynq_gpio_get_value;
chip->set = zynq_gpio_set_value;
chip->request = zynq_gpio_request;
chip->free = zynq_gpio_free;
chip->direction_input = zynq_gpio_dir_in;
chip->direction_output = zynq_gpio_dir_out;
chip->base = -1;
chip->ngpio = ZYNQ_GPIO_NR_GPIOS;
/* Enable GPIO clock */
gpio->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(gpio->clk)) {
dev_err(&pdev->dev, "input clock not found.\n");
return PTR_ERR(gpio->clk);
}
ret = clk_prepare_enable(gpio->clk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable clock.\n");
return ret;
}
/* report a bug if gpio chip registration fails */
ret = gpiochip_add(chip);
if (ret) {
dev_err(&pdev->dev, "Failed to add gpio chip\n");
goto err_disable_clk;
}
/* disable interrupts for all banks */
for (bank_num = 0; bank_num < ZYNQ_GPIO_MAX_BANK; bank_num++)
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
ret = gpiochip_irqchip_add(chip, &zynq_gpio_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(&pdev->dev, "Failed to add irq chip\n");
goto err_rm_gpiochip;
}
gpiochip_set_chained_irqchip(chip, &zynq_gpio_irqchip, irq,
zynq_gpio_irqhandler);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
device_set_wakeup_capable(&pdev->dev, 1);
return 0;
err_rm_gpiochip:
if (gpiochip_remove(chip))
dev_err(&pdev->dev, "Failed to remove gpio chip\n");
err_disable_clk:
clk_disable_unprepare(gpio->clk);
return ret;
}
/**
* zynq_gpio_remove - Driver removal function
* @pdev: platform device instance
*
* Return: 0 always
*/
static int zynq_gpio_remove(struct platform_device *pdev)
{
int ret;
struct zynq_gpio *gpio = platform_get_drvdata(pdev);
pm_runtime_get_sync(&pdev->dev);
ret = gpiochip_remove(&gpio->chip);
if (ret) {
dev_err(&pdev->dev, "Failed to remove gpio chip\n");
return ret;
}
clk_disable_unprepare(gpio->clk);
device_set_wakeup_capable(&pdev->dev, 0);
return 0;
}
static struct of_device_id zynq_gpio_of_match[] = {
{ .compatible = "xlnx,zynq-gpio-1.0", },
{ /* end of table */ }
};
MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
static struct platform_driver zynq_gpio_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.pm = &zynq_gpio_dev_pm_ops,
.of_match_table = zynq_gpio_of_match,
},
.probe = zynq_gpio_probe,
.remove = zynq_gpio_remove,
};
/**
* zynq_gpio_init - Initial driver registration call
*
* Return: value from platform_driver_register
*/
static int __init zynq_gpio_init(void)
{
return platform_driver_register(&zynq_gpio_driver);
}
postcore_initcall(zynq_gpio_init);
MODULE_AUTHOR("Xilinx Inc.");
MODULE_DESCRIPTION("Zynq GPIO driver");
MODULE_LICENSE("GPL");

View File

@ -157,7 +157,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
gpiod_direction_input(desc);
ret = gpiod_lock_as_irq(desc);
ret = gpio_lock_as_irq(chip, pin);
if (ret) {
dev_err(chip->dev, "Failed to lock GPIO as interrupt\n");
goto fail_free_desc;
@ -212,7 +212,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
fail_free_event:
kfree(event);
fail_unlock_irq:
gpiod_unlock_as_irq(desc);
gpio_unlock_as_irq(chip, pin);
fail_free_desc:
gpiochip_free_own_desc(desc);
@ -221,7 +221,7 @@ fail_free_desc:
/**
* acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
* @acpi_gpio: ACPI GPIO chip
* @chip: GPIO chip
*
* ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
* handled by ACPI event methods which need to be called from the GPIO
@ -229,11 +229,21 @@ fail_free_desc:
* gpio pins have acpi event methods and assigns interrupt handlers that calls
* the acpi event methods for those pins.
*/
static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
{
struct gpio_chip *chip = acpi_gpio->chip;
struct acpi_gpio_chip *acpi_gpio;
acpi_handle handle;
acpi_status status;
if (!chip->to_irq)
if (!chip->dev || !chip->to_irq)
return;
handle = ACPI_HANDLE(chip->dev);
if (!handle)
return;
status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
if (ACPI_FAILURE(status))
return;
INIT_LIST_HEAD(&acpi_gpio->events);
@ -243,17 +253,27 @@ static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)
/**
* acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts.
* @acpi_gpio: ACPI GPIO chip
* @chip: GPIO chip
*
* Free interrupts associated with GPIO ACPI event method for the given
* GPIO chip.
*/
static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
{
struct acpi_gpio_chip *acpi_gpio;
struct acpi_gpio_event *event, *ep;
struct gpio_chip *chip = acpi_gpio->chip;
acpi_handle handle;
acpi_status status;
if (!chip->to_irq)
if (!chip->dev || !chip->to_irq)
return;
handle = ACPI_HANDLE(chip->dev);
if (!handle)
return;
status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
if (ACPI_FAILURE(status))
return;
list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
@ -263,7 +283,7 @@ static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio)
desc = gpiochip_get_desc(chip, event->pin);
if (WARN_ON(IS_ERR(desc)))
continue;
gpiod_unlock_as_irq(desc);
gpio_unlock_as_irq(chip, event->pin);
gpiochip_free_own_desc(desc);
list_del(&event->node);
kfree(event);
@ -525,7 +545,6 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
return;
}
acpi_gpiochip_request_interrupts(acpi_gpio);
acpi_gpiochip_request_regions(acpi_gpio);
}
@ -549,7 +568,6 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
}
acpi_gpiochip_free_regions(acpi_gpio);
acpi_gpiochip_free_interrupts(acpi_gpio);
acpi_detach_data(handle, acpi_gpio_chip_dh);
kfree(acpi_gpio);

View File

@ -0,0 +1,102 @@
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/gpio.h>
#include "gpiolib.h"
void gpio_free(unsigned gpio)
{
gpiod_free(gpio_to_desc(gpio));
}
EXPORT_SYMBOL_GPL(gpio_free);
/**
* gpio_request_one - request a single GPIO with initial configuration
* @gpio: the GPIO number
* @flags: GPIO configuration as specified by GPIOF_*
* @label: a literal description string of this GPIO
*/
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
{
struct gpio_desc *desc;
int err;
desc = gpio_to_desc(gpio);
err = gpiod_request(desc, label);
if (err)
return err;
if (flags & GPIOF_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
if (flags & GPIOF_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
if (flags & GPIOF_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (flags & GPIOF_DIR_IN)
err = gpiod_direction_input(desc);
else
err = gpiod_direction_output_raw(desc,
(flags & GPIOF_INIT_HIGH) ? 1 : 0);
if (err)
goto free_gpio;
if (flags & GPIOF_EXPORT) {
err = gpiod_export(desc, flags & GPIOF_EXPORT_CHANGEABLE);
if (err)
goto free_gpio;
}
return 0;
free_gpio:
gpiod_free(desc);
return err;
}
EXPORT_SYMBOL_GPL(gpio_request_one);
int gpio_request(unsigned gpio, const char *label)
{
return gpiod_request(gpio_to_desc(gpio), label);
}
EXPORT_SYMBOL_GPL(gpio_request);
/**
* gpio_request_array - request multiple GPIOs in a single call
* @array: array of the 'struct gpio'
* @num: how many GPIOs in the array
*/
int gpio_request_array(const struct gpio *array, size_t num)
{
int i, err;
for (i = 0; i < num; i++, array++) {
err = gpio_request_one(array->gpio, array->flags, array->label);
if (err)
goto err_free;
}
return 0;
err_free:
while (i--)
gpio_free((--array)->gpio);
return err;
}
EXPORT_SYMBOL_GPL(gpio_request_array);
/**
* gpio_free_array - release multiple GPIOs in a single call
* @array: array of the 'struct gpio'
* @num: how many GPIOs in the array
*/
void gpio_free_array(const struct gpio *array, size_t num)
{
while (num--)
gpio_free((array++)->gpio);
}
EXPORT_SYMBOL_GPL(gpio_free_array);

View File

@ -23,7 +23,7 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
struct gpio_desc;
#include "gpiolib.h"
/* Private data structure for of_gpiochip_find_and_xlate */
struct gg_data {
@ -82,19 +82,19 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
&gg_data.gpiospec);
if (ret) {
pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
__func__, np->full_name, index);
pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n",
__func__, propname, np->full_name, index);
return ERR_PTR(ret);
}
gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
of_node_put(gg_data.gpiospec.np);
pr_debug("%s exited with status %d\n", __func__,
pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n",
__func__, propname, np->full_name, index,
PTR_ERR_OR_ZERO(gg_data.out_gpio));
return gg_data.out_gpio;
}
EXPORT_SYMBOL(of_get_named_gpiod_flags);
int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
int index, enum of_gpio_flags *flags)

View File

@ -0,0 +1,827 @@
#include <linux/idr.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/sysfs.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/kdev_t.h>
#include "gpiolib.h"
static DEFINE_IDR(dirent_idr);
/* lock protects against unexport_gpio() being called while
* sysfs files are active.
*/
static DEFINE_MUTEX(sysfs_lock);
/*
* /sys/class/gpio/gpioN... only for GPIOs that are exported
* /direction
* * MAY BE OMITTED if kernel won't allow direction changes
* * is read/write as "in" or "out"
* * may also be written as "high" or "low", initializing
* output value as specified ("out" implies "low")
* /value
* * always readable, subject to hardware behavior
* * may be writable, as zero/nonzero
* /edge
* * configures behavior of poll(2) on /value
* * available only if pin can generate IRQs on input
* * is read/write as "none", "falling", "rising", or "both"
* /active_low
* * configures polarity of /value
* * is read/write as zero/nonzero
* * also affects existing and subsequent "falling" and "rising"
* /edge configuration
*/
static ssize_t gpio_direction_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags)) {
status = -EIO;
} else {
gpiod_get_direction(desc);
status = sprintf(buf, "%s\n",
test_bit(FLAG_IS_OUT, &desc->flags)
? "out" : "in");
}
mutex_unlock(&sysfs_lock);
return status;
}
static ssize_t gpio_direction_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else if (sysfs_streq(buf, "high"))
status = gpiod_direction_output_raw(desc, 1);
else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
status = gpiod_direction_output_raw(desc, 0);
else if (sysfs_streq(buf, "in"))
status = gpiod_direction_input(desc);
else
status = -EINVAL;
mutex_unlock(&sysfs_lock);
return status ? : size;
}
static /* const */ DEVICE_ATTR(direction, 0644,
gpio_direction_show, gpio_direction_store);
static ssize_t gpio_value_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else
status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));
mutex_unlock(&sysfs_lock);
return status;
}
static ssize_t gpio_value_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else if (!test_bit(FLAG_IS_OUT, &desc->flags))
status = -EPERM;
else {
long value;
status = kstrtol(buf, 0, &value);
if (status == 0) {
gpiod_set_value_cansleep(desc, value);
status = size;
}
}
mutex_unlock(&sysfs_lock);
return status;
}
static const DEVICE_ATTR(value, 0644,
gpio_value_show, gpio_value_store);
static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
{
struct kernfs_node *value_sd = priv;
sysfs_notify_dirent(value_sd);
return IRQ_HANDLED;
}
static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
unsigned long gpio_flags)
{
struct kernfs_node *value_sd;
unsigned long irq_flags;
int ret, irq, id;
if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags)
return 0;
irq = gpiod_to_irq(desc);
if (irq < 0)
return -EIO;
id = desc->flags >> ID_SHIFT;
value_sd = idr_find(&dirent_idr, id);
if (value_sd)
free_irq(irq, value_sd);
desc->flags &= ~GPIO_TRIGGER_MASK;
if (!gpio_flags) {
gpio_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
ret = 0;
goto free_id;
}
irq_flags = IRQF_SHARED;
if (test_bit(FLAG_TRIG_FALL, &gpio_flags))
irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
if (test_bit(FLAG_TRIG_RISE, &gpio_flags))
irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
if (!value_sd) {
value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
if (!value_sd) {
ret = -ENODEV;
goto err_out;
}
ret = idr_alloc(&dirent_idr, value_sd, 1, 0, GFP_KERNEL);
if (ret < 0)
goto free_sd;
id = ret;
desc->flags &= GPIO_FLAGS_MASK;
desc->flags |= (unsigned long)id << ID_SHIFT;
if (desc->flags >> ID_SHIFT != id) {
ret = -ERANGE;
goto free_id;
}
}
ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,
"gpiolib", value_sd);
if (ret < 0)
goto free_id;
ret = gpio_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;
}
desc->flags |= gpio_flags;
return 0;
free_id:
idr_remove(&dirent_idr, id);
desc->flags &= GPIO_FLAGS_MASK;
free_sd:
if (value_sd)
sysfs_put(value_sd);
err_out:
return ret;
}
static const struct {
const char *name;
unsigned long flags;
} trigger_types[] = {
{ "none", 0 },
{ "falling", BIT(FLAG_TRIG_FALL) },
{ "rising", BIT(FLAG_TRIG_RISE) },
{ "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) },
};
static ssize_t gpio_edge_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else {
int i;
status = 0;
for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
if ((desc->flags & GPIO_TRIGGER_MASK)
== trigger_types[i].flags) {
status = sprintf(buf, "%s\n",
trigger_types[i].name);
break;
}
}
mutex_unlock(&sysfs_lock);
return status;
}
static ssize_t gpio_edge_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
int i;
for (i = 0; i < ARRAY_SIZE(trigger_types); i++)
if (sysfs_streq(trigger_types[i].name, buf))
goto found;
return -EINVAL;
found:
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else {
status = gpio_setup_irq(desc, dev, trigger_types[i].flags);
if (!status)
status = size;
}
mutex_unlock(&sysfs_lock);
return status;
}
static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev,
int value)
{
int status = 0;
if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
return 0;
if (value)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
else
clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
/* reconfigure poll(2) support if enabled on one edge only */
if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^
!!test_bit(FLAG_TRIG_FALL, &desc->flags))) {
unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK;
gpio_setup_irq(desc, dev, 0);
status = gpio_setup_irq(desc, dev, trigger_flags);
}
return status;
}
static ssize_t gpio_active_low_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else
status = sprintf(buf, "%d\n",
!!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
mutex_unlock(&sysfs_lock);
return status;
}
static ssize_t gpio_active_low_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status;
mutex_lock(&sysfs_lock);
if (!test_bit(FLAG_EXPORT, &desc->flags)) {
status = -EIO;
} else {
long value;
status = kstrtol(buf, 0, &value);
if (status == 0)
status = sysfs_set_active_low(desc, dev, value != 0);
}
mutex_unlock(&sysfs_lock);
return status ? : size;
}
static const DEVICE_ATTR(active_low, 0644,
gpio_active_low_show, gpio_active_low_store);
static const struct attribute *gpio_attrs[] = {
&dev_attr_value.attr,
&dev_attr_active_low.attr,
NULL,
};
static const struct attribute_group gpio_attr_group = {
.attrs = (struct attribute **) gpio_attrs,
};
/*
* /sys/class/gpio/gpiochipN/
* /base ... matching gpio_chip.base (N)
* /label ... matching gpio_chip.label
* /ngpio ... matching gpio_chip.ngpio
*/
static ssize_t chip_base_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_chip *chip = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", chip->base);
}
static DEVICE_ATTR(base, 0444, chip_base_show, NULL);
static ssize_t chip_label_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_chip *chip = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", chip->label ? : "");
}
static DEVICE_ATTR(label, 0444, chip_label_show, NULL);
static ssize_t chip_ngpio_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_chip *chip = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", chip->ngpio);
}
static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
static const struct attribute *gpiochip_attrs[] = {
&dev_attr_base.attr,
&dev_attr_label.attr,
&dev_attr_ngpio.attr,
NULL,
};
static const struct attribute_group gpiochip_attr_group = {
.attrs = (struct attribute **) gpiochip_attrs,
};
/*
* /sys/class/gpio/export ... write-only
* integer N ... number of GPIO to export (full access)
* /sys/class/gpio/unexport ... write-only
* integer N ... number of GPIO to unexport
*/
static ssize_t export_store(struct class *class,
struct class_attribute *attr,
const char *buf, size_t len)
{
long gpio;
struct gpio_desc *desc;
int status;
status = kstrtol(buf, 0, &gpio);
if (status < 0)
goto done;
desc = gpio_to_desc(gpio);
/* reject invalid GPIOs */
if (!desc) {
pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
/* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so
* they may be undone on its behalf too.
*/
status = gpiod_request(desc, "sysfs");
if (status < 0) {
if (status == -EPROBE_DEFER)
status = -ENODEV;
goto done;
}
status = gpiod_export(desc, true);
if (status < 0)
gpiod_free(desc);
else
set_bit(FLAG_SYSFS, &desc->flags);
done:
if (status)
pr_debug("%s: status %d\n", __func__, status);
return status ? : len;
}
static ssize_t unexport_store(struct class *class,
struct class_attribute *attr,
const char *buf, size_t len)
{
long gpio;
struct gpio_desc *desc;
int status;
status = kstrtol(buf, 0, &gpio);
if (status < 0)
goto done;
desc = gpio_to_desc(gpio);
/* reject bogus commands (gpio_unexport ignores them) */
if (!desc) {
pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
status = -EINVAL;
/* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so
* they may be undone on its behalf too.
*/
if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
status = 0;
gpiod_free(desc);
}
done:
if (status)
pr_debug("%s: status %d\n", __func__, status);
return status ? : len;
}
static struct class_attribute gpio_class_attrs[] = {
__ATTR(export, 0200, NULL, export_store),
__ATTR(unexport, 0200, NULL, unexport_store),
__ATTR_NULL,
};
static struct class gpio_class = {
.name = "gpio",
.owner = THIS_MODULE,
.class_attrs = gpio_class_attrs,
};
/**
* gpiod_export - export a GPIO through sysfs
* @gpio: gpio to make available, already requested
* @direction_may_change: true if userspace may change gpio direction
* Context: arch_initcall or later
*
* When drivers want to make a GPIO accessible to userspace after they
* have requested it -- perhaps while debugging, or as part of their
* public interface -- they may use this routine. If the GPIO can
* change direction (some can't) and the caller allows it, userspace
* will see "direction" sysfs attribute which may be used to change
* the gpio's direction. A "value" attribute will always be provided.
*
* Returns zero on success, else an error.
*/
int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
{
unsigned long flags;
int status;
const char *ioname = NULL;
struct device *dev;
int offset;
/* can't export until sysfs is available ... */
if (!gpio_class.p) {
pr_debug("%s: called too early!\n", __func__);
return -ENOENT;
}
if (!desc) {
pr_debug("%s: invalid gpio descriptor\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock);
spin_lock_irqsave(&gpio_lock, flags);
if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
test_bit(FLAG_EXPORT, &desc->flags)) {
spin_unlock_irqrestore(&gpio_lock, flags);
gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n",
__func__,
test_bit(FLAG_REQUESTED, &desc->flags),
test_bit(FLAG_EXPORT, &desc->flags));
status = -EPERM;
goto fail_unlock;
}
if (!desc->chip->direction_input || !desc->chip->direction_output)
direction_may_change = false;
spin_unlock_irqrestore(&gpio_lock, flags);
offset = gpio_chip_hwgpio(desc);
if (desc->chip->names && desc->chip->names[offset])
ioname = desc->chip->names[offset];
dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
desc, ioname ? ioname : "gpio%u",
desc_to_gpio(desc));
if (IS_ERR(dev)) {
status = PTR_ERR(dev);
goto fail_unlock;
}
status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
if (status)
goto fail_unregister_device;
if (direction_may_change) {
status = device_create_file(dev, &dev_attr_direction);
if (status)
goto fail_unregister_device;
}
if (gpiod_to_irq(desc) >= 0 && (direction_may_change ||
!test_bit(FLAG_IS_OUT, &desc->flags))) {
status = device_create_file(dev, &dev_attr_edge);
if (status)
goto fail_unregister_device;
}
set_bit(FLAG_EXPORT, &desc->flags);
mutex_unlock(&sysfs_lock);
return 0;
fail_unregister_device:
device_unregister(dev);
fail_unlock:
mutex_unlock(&sysfs_lock);
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
}
EXPORT_SYMBOL_GPL(gpiod_export);
static int match_export(struct device *dev, const void *data)
{
return dev_get_drvdata(dev) == data;
}
/**
* gpiod_export_link - create a sysfs link to an exported GPIO node
* @dev: device under which to create symlink
* @name: name of the symlink
* @gpio: gpio to create symlink to, already exported
*
* Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
* node. Caller is responsible for unlinking.
*
* Returns zero on success, else an error.
*/
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc)
{
int status = -EINVAL;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock);
if (test_bit(FLAG_EXPORT, &desc->flags)) {
struct device *tdev;
tdev = class_find_device(&gpio_class, NULL, desc, match_export);
if (tdev != NULL) {
status = sysfs_create_link(&dev->kobj, &tdev->kobj,
name);
} else {
status = -ENODEV;
}
}
mutex_unlock(&sysfs_lock);
if (status)
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
}
EXPORT_SYMBOL_GPL(gpiod_export_link);
/**
* gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value
* @gpio: gpio to change
* @value: non-zero to use active low, i.e. inverted values
*
* Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute.
* The GPIO does not have to be exported yet. If poll(2) support has
* been enabled for either rising or falling edge, it will be
* reconfigured to follow the new polarity.
*
* Returns zero on success, else an error.
*/
int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
{
struct device *dev = NULL;
int status = -EINVAL;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock);
if (test_bit(FLAG_EXPORT, &desc->flags)) {
dev = class_find_device(&gpio_class, NULL, desc, match_export);
if (dev == NULL) {
status = -ENODEV;
goto unlock;
}
}
status = sysfs_set_active_low(desc, dev, value);
unlock:
mutex_unlock(&sysfs_lock);
if (status)
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
}
EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);
/**
* gpiod_unexport - reverse effect of gpio_export()
* @gpio: gpio to make unavailable
*
* This is implicit on gpio_free().
*/
void gpiod_unexport(struct gpio_desc *desc)
{
int status = 0;
struct device *dev = NULL;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return;
}
mutex_lock(&sysfs_lock);
if (test_bit(FLAG_EXPORT, &desc->flags)) {
dev = class_find_device(&gpio_class, NULL, desc, match_export);
if (dev) {
gpio_setup_irq(desc, dev, 0);
clear_bit(FLAG_EXPORT, &desc->flags);
} else
status = -ENODEV;
}
mutex_unlock(&sysfs_lock);
if (dev) {
device_unregister(dev);
put_device(dev);
}
if (status)
gpiod_dbg(desc, "%s: status %d\n", __func__, status);
}
EXPORT_SYMBOL_GPL(gpiod_unexport);
int gpiochip_export(struct gpio_chip *chip)
{
int status;
struct device *dev;
/* Many systems register gpio chips for SOC support very early,
* before driver model support is available. In those cases we
* export this later, in gpiolib_sysfs_init() ... here we just
* verify that _some_ field of gpio_class got initialized.
*/
if (!gpio_class.p)
return 0;
/* use chip->base for the ID; it's already known to be unique */
mutex_lock(&sysfs_lock);
dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
"gpiochip%d", chip->base);
if (!IS_ERR(dev)) {
status = sysfs_create_group(&dev->kobj,
&gpiochip_attr_group);
} else
status = PTR_ERR(dev);
chip->exported = (status == 0);
mutex_unlock(&sysfs_lock);
if (status)
chip_dbg(chip, "%s: status %d\n", __func__, status);
return status;
}
void gpiochip_unexport(struct gpio_chip *chip)
{
int status;
struct device *dev;
mutex_lock(&sysfs_lock);
dev = class_find_device(&gpio_class, NULL, chip, match_export);
if (dev) {
put_device(dev);
device_unregister(dev);
chip->exported = false;
status = 0;
} else
status = -ENODEV;
mutex_unlock(&sysfs_lock);
if (status)
chip_dbg(chip, "%s: status %d\n", __func__, status);
}
static int __init gpiolib_sysfs_init(void)
{
int status;
unsigned long flags;
struct gpio_chip *chip;
status = class_register(&gpio_class);
if (status < 0)
return status;
/* Scan and register the gpio_chips which registered very
* early (e.g. before the class_register above was called).
*
* We run before arch_initcall() so chip->dev nodes can have
* registered, and so arch_initcall() can always gpio_export().
*/
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(chip, &gpio_chips, list) {
if (chip->exported)
continue;
/*
* TODO we yield gpio_lock here because gpiochip_export()
* acquires a mutex. This is unsafe and needs to be fixed.
*
* Also it would be nice to use gpiochip_find() here so we
* can keep gpio_chips local to gpiolib.c, but the yield of
* gpio_lock prevents us from doing this.
*/
spin_unlock_irqrestore(&gpio_lock, flags);
status = gpiochip_export(chip);
spin_lock_irqsave(&gpio_lock, flags);
}
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
}
postcore_initcall(gpiolib_sysfs_init);

File diff suppressed because it is too large Load Diff

View File

@ -31,12 +31,21 @@ struct acpi_gpio_info {
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
struct acpi_gpio_info *info);
#else
static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
static inline void
acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
static inline void
acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
static inline struct gpio_desc *
acpi_get_gpiod_by_index(struct device *dev, int index,
struct acpi_gpio_info *info)
@ -45,10 +54,100 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
}
#endif
int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
void gpiochip_free_own_desc(struct gpio_desc *desc);
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
extern struct spinlock gpio_lock;
extern struct list_head gpio_chips;
struct gpio_desc {
struct gpio_chip *chip;
unsigned long flags;
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
#define FLAG_IS_OUT 1
#define FLAG_EXPORT 2 /* protected by sysfs_lock */
#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
#define FLAG_TRIG_FALL 4 /* trigger on falling edge */
#define FLAG_TRIG_RISE 5 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 6 /* value has active low */
#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define ID_SHIFT 16 /* add new flags before this one */
#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)
#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
const char *label;
};
int gpiod_request(struct gpio_desc *desc, const char *label);
void gpiod_free(struct gpio_desc *desc);
/*
* Return the GPIO number of the passed descriptor relative to its chip
*/
static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc)
{
return desc - &desc->chip->desc[0];
}
/* With descriptor prefix */
#define gpiod_emerg(desc, fmt, ...) \
pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
##__VA_ARGS__)
#define gpiod_crit(desc, fmt, ...) \
pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
##__VA_ARGS__)
#define gpiod_err(desc, fmt, ...) \
pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
##__VA_ARGS__)
#define gpiod_warn(desc, fmt, ...) \
pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
##__VA_ARGS__)
#define gpiod_info(desc, fmt, ...) \
pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
##__VA_ARGS__)
#define gpiod_dbg(desc, fmt, ...) \
pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
##__VA_ARGS__)
/* With chip prefix */
#define chip_emerg(chip, fmt, ...) \
pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
#define chip_crit(chip, fmt, ...) \
pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
#define chip_err(chip, fmt, ...) \
pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
#define chip_warn(chip, fmt, ...) \
pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
#define chip_info(chip, fmt, ...) \
pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
#define chip_dbg(chip, fmt, ...) \
pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)
#ifdef CONFIG_GPIO_SYSFS
int gpiochip_export(struct gpio_chip *chip);
void gpiochip_unexport(struct gpio_chip *chip);
#else
static inline int gpiochip_export(struct gpio_chip *chip)
{
return 0;
}
static inline void gpiochip_unexport(struct gpio_chip *chip)
{
}
#endif /* CONFIG_GPIO_SYSFS */
#endif /* GPIOLIB_H */

View File

@ -110,9 +110,6 @@ static inline int __gpio_to_irq(unsigned gpio)
return gpiod_to_irq(gpio_to_desc(gpio));
}
extern int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
extern void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
extern int gpio_request_array(const struct gpio *array, size_t num);
extern void gpio_free_array(const struct gpio *array, size_t num);

View File

@ -18,30 +18,79 @@ struct gpio_desc;
#ifdef CONFIG_GPIOLIB
#define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
/**
* Optional flags that can be passed to one of gpiod_* to configure direction
* and output value. These values cannot be OR'd.
*/
enum gpiod_flags {
GPIOD_ASIS = 0,
GPIOD_IN = GPIOD_FLAGS_BIT_DIR_SET,
GPIOD_OUT_LOW = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,
GPIOD_OUT_HIGH = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
GPIOD_FLAGS_BIT_DIR_VAL,
};
/* Acquire and dispose GPIOs */
struct gpio_desc *__must_check gpiod_get(struct device *dev,
const char *con_id);
struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
struct gpio_desc *__must_check __gpiod_get(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
#define __gpiod_get(dev, con_id, flags, ...) __gpiod_get(dev, con_id, flags)
#define gpiod_get(varargs...) __gpiod_get(varargs, 0)
struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx);
struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
const char *con_id);
struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
unsigned int idx,
enum gpiod_flags flags);
#define __gpiod_get_index(dev, con_id, index, flags, ...) \
__gpiod_get_index(dev, con_id, index, flags)
#define gpiod_get_index(varargs...) __gpiod_get_index(varargs, 0)
struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
#define __gpiod_get_optional(dev, con_id, flags, ...) \
__gpiod_get_optional(dev, con_id, flags)
#define gpiod_get_optional(varargs...) __gpiod_get_optional(varargs, 0)
struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
const char *con_id,
unsigned int index);
unsigned int index,
enum gpiod_flags flags);
#define __gpiod_get_index_optional(dev, con_id, index, flags, ...) \
__gpiod_get_index_optional(dev, con_id, index, flags)
#define gpiod_get_index_optional(varargs...) \
__gpiod_get_index_optional(varargs, 0)
void gpiod_put(struct gpio_desc *desc);
struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
const char *con_id);
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
#define __devm_gpiod_get(dev, con_id, flags, ...) \
__devm_gpiod_get(dev, con_id, flags)
#define devm_gpiod_get(varargs...) __devm_gpiod_get(varargs, 0)
struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
const char *con_id,
unsigned int idx);
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
const char *con_id);
unsigned int idx,
enum gpiod_flags flags);
#define __devm_gpiod_get_index(dev, con_id, index, flags, ...) \
__devm_gpiod_get_index(dev, con_id, index, flags)
#define devm_gpiod_get_index(varargs...) __devm_gpiod_get_index(varargs, 0)
struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
#define __devm_gpiod_get_optional(dev, con_id, flags, ...) \
__devm_gpiod_get_optional(dev, con_id, flags)
#define devm_gpiod_get_optional(varargs...) \
__devm_gpiod_get_optional(varargs, 0)
struct gpio_desc *__must_check
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index);
__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags);
#define __devm_gpiod_get_index_optional(dev, con_id, index, flags, ...) \
__devm_gpiod_get_index_optional(dev, con_id, index, flags)
#define devm_gpiod_get_index_optional(varargs...) \
__devm_gpiod_get_index_optional(varargs, 0)
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);

View File

@ -141,73 +141,16 @@ extern const char *gpiochip_is_requested(struct gpio_chip *chip,
/* add/remove chips */
extern int gpiochip_add(struct gpio_chip *chip);
extern int __must_check gpiochip_remove(struct gpio_chip *chip);
extern int gpiochip_remove(struct gpio_chip *chip);
extern struct gpio_chip *gpiochip_find(void *data,
int (*match)(struct gpio_chip *chip, void *data));
/* lock/unlock as IRQ */
int gpiod_lock_as_irq(struct gpio_desc *desc);
void gpiod_unlock_as_irq(struct gpio_desc *desc);
int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
u16 hwnum);
enum gpio_lookup_flags {
GPIO_ACTIVE_HIGH = (0 << 0),
GPIO_ACTIVE_LOW = (1 << 0),
GPIO_OPEN_DRAIN = (1 << 1),
GPIO_OPEN_SOURCE = (1 << 2),
};
/**
* struct gpiod_lookup - lookup table
* @chip_label: name of the chip the GPIO belongs to
* @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO
* @con_id: name of the GPIO from the device's point of view
* @idx: index of the GPIO in case several GPIOs share the same name
* @flags: mask of GPIO_* values
*
* gpiod_lookup is a lookup table for associating GPIOs to specific devices and
* functions using platform data.
*/
struct gpiod_lookup {
const char *chip_label;
u16 chip_hwnum;
const char *con_id;
unsigned int idx;
enum gpio_lookup_flags flags;
};
struct gpiod_lookup_table {
struct list_head list;
const char *dev_id;
struct gpiod_lookup table[];
};
/*
* Simple definition of a single GPIO under a con_id
*/
#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _con_id, _flags) \
GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, 0, _flags)
/*
* Use this macro if you need to have several GPIOs under the same con_id.
* Each GPIO needs to use a different index and can be accessed using
* gpiod_get_index()
*/
#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, _idx, _flags) \
{ \
.chip_label = _chip_label, \
.chip_hwnum = _chip_hwnum, \
.con_id = _con_id, \
.idx = _idx, \
.flags = _flags, \
}
void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
#ifdef CONFIG_GPIOLIB_IRQCHIP
void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
@ -223,6 +166,9 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
#endif /* CONFIG_GPIO_IRQCHIP */
int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
void gpiochip_free_own_desc(struct gpio_desc *desc);
#else /* CONFIG_GPIOLIB */
static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)

View File

@ -0,0 +1,61 @@
#ifndef __LINUX_GPIO_MACHINE_H
#define __LINUX_GPIO_MACHINE_H
#include <linux/types.h>
#include <linux/list.h>
enum gpio_lookup_flags {
GPIO_ACTIVE_HIGH = (0 << 0),
GPIO_ACTIVE_LOW = (1 << 0),
GPIO_OPEN_DRAIN = (1 << 1),
GPIO_OPEN_SOURCE = (1 << 2),
};
/**
* struct gpiod_lookup - lookup table
* @chip_label: name of the chip the GPIO belongs to
* @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO
* @con_id: name of the GPIO from the device's point of view
* @idx: index of the GPIO in case several GPIOs share the same name
* @flags: mask of GPIO_* values
*
* gpiod_lookup is a lookup table for associating GPIOs to specific devices and
* functions using platform data.
*/
struct gpiod_lookup {
const char *chip_label;
u16 chip_hwnum;
const char *con_id;
unsigned int idx;
enum gpio_lookup_flags flags;
};
struct gpiod_lookup_table {
struct list_head list;
const char *dev_id;
struct gpiod_lookup table[];
};
/*
* Simple definition of a single GPIO under a con_id
*/
#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _con_id, _flags) \
GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, 0, _flags)
/*
* Use this macro if you need to have several GPIOs under the same con_id.
* Each GPIO needs to use a different index and can be accessed using
* gpiod_get_index()
*/
#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _con_id, _idx, _flags) \
{ \
.chip_label = _chip_label, \
.chip_hwnum = _chip_hwnum, \
.con_id = _con_id, \
.idx = _idx, \
.flags = _flags, \
}
void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
#endif /* __LINUX_GPIO_MACHINE_H */