This is the bulk of GPIO changes for the v5.9 kernel cycle:

Core changes:
 
 - Introduce the for_each_requested_gpio() macro to help in
   dependent code all over the place. Also patch a few locations
   to use it while we are at it.
 
 - Split out the sysfs code into its own file.
 
 - Split out the character device code into its own file, then
   make a set of refactorings and improvements to this code.
   We are setting the stage to revamp the userspace API a bit
   in the next cycle.
 
 - Fix a whole slew of kerneldoc that was wrong or missing.
 
 New drivers:
 
 - The PCA953x driver now supports the PCAL9535.
 
 Driver improvements:
 
 - A host of incremental modernizations and improvements to the
   PCA953x driver.
 
 - Incremental improvements to the Xilinx Zynq driver.
 
 - Some improvements to the GPIO aggregator driver.
 
 - I ran all over the place switching all threaded and other
   drivers requesting their own IRQ while using the core
   GPIO IRQ helpers to pass the GPIO irq chip as a template
   instead of calling the explicit set-up functions. Next merge
   window we may retire the old code altogether.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAl8p2cEACgkQQRCzN7AZ
 XXMjBBAAs4YwEALYTCvpzbXdYGAgMGIEAD84dPBZTAYj3P/iGuXPk/+wdt4wLHTD
 dQl0/MG6JXf+mCClgsHhC+ILPUS6YM/v/it4gnV4j6o/ugYiNPADYl4pieaq/SVb
 jNrSxs0tzZYTtlq6xSmRMCpA8SgP3ASWNa5dp5mDkuo3xaEJvM3cpsww7Q5GG3Fb
 HQD9+XgBGQx7H+6JMoNHR8/E9A5y4pwIvTlfqzTcq3UupTqlvklekgu0fTiA6D7t
 z/ydQpYtqevuirir7J7oMiIhTSPgTkOcUwNO6hCcwpO/a0q7jwy1DvGIyJDM2yIj
 UYby03SCLknFGxLwKAcavC3mnLIIor61385e5+lXBH0OS7EO8OpBoi9vAxqalcZ8
 ZRrOyYrT3et40rD+ByFFwbUsrD9D4c0Ul+Ocr8upKdnGlRW/u8YahIwn82qnKjF0
 ANJanZu76c8ZU8AJQyM/HD7hrcJ0MJXhECXb/JJx4O52ebi4fmOdtS/Kx2urH4KR
 hX3tspQM/tU89a4jW7NIzzfZKlnPI2rI3NxYgziQVgVnt+iVrkyBiYSoWhK+DEyu
 JJl5zXHvgb1UmejqN2Qtkq9V+3R2VEYg7WUyr6b48q4acSVI1q+NfGE7+GBT/+d4
 Kt1eGz8QtEnxspDhVsQNY4WSP8QpwhmWWM2ujsO6a81vyjB4vSg=
 =OSvz
 -----END PGP SIGNATURE-----

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

Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v5.9 kernel cycle.

  There is nothing too exciting in it, but a new macro that fixes a
  build failure on a minor ARM32 platform that appeared yesterday is
  part of it so we better merge it.

  Core changes:

   - Introduce the for_each_requested_gpio() macro to help in dependent
     code all over the place. Also patch a few locations to use it while
     we are at it.

   - Split out the sysfs code into its own file.

   - Split out the character device code into its own file, then make a
     set of refactorings and improvements to this code. We are setting
     the stage to revamp the userspace API a bit in the next cycle.

   - Fix a whole slew of kerneldoc that was wrong or missing.

  New drivers:

   - The PCA953x driver now supports the PCAL9535.

  Driver improvements:

   - A host of incremental modernizations and improvements to the
     PCA953x driver.

   - Incremental improvements to the Xilinx Zynq driver.

   - Some improvements to the GPIO aggregator driver.

   - I ran all over the place switching all threaded and other drivers
     requesting their own IRQ while using the core GPIO IRQ helpers to
     pass the GPIO irq chip as a template instead of calling the
     explicit set-up functions. Next merge window we may retire the old
     code altogether"

* tag 'gpio-v5.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (97 commits)
  gpio: wcove: Request IRQ after all initialisation done
  gpio: crystalcove: Free IRQ on error path
  gpio: pca953x: Request IRQ after all initialisation done
  gpio: don't use same lockdep class for all devm_gpiochip_add_data users
  gpio: max732x: Use irqchip template
  gpio: stmpe: Move chip registration
  gpio: rcar: Use irqchip template
  gpio: regmap: fix type clash
  gpio: Correct kernel-doc inconsistency
  gpio: pci-idio-16: Use irqchip template
  gpio: pcie-idio-24: Use irqchip template
  gpio: 104-idio-16: Use irqchip template
  gpio: 104-idi-48: Use irqchip template
  gpio: 104-dio-48e: Use irqchip template
  gpio: ws16c48: Use irqchip template
  gpio: omap: improve coding style for pin config flags
  gpio: dln2: Use irqchip template
  gpio: sch: Add a blank line between declaration and code
  gpio: sch: changed every 'unsigned' to 'unsigned int'
  gpio: ich: changed every 'unsigned' to 'unsigned int'
  ...
This commit is contained in:
Linus Torvalds 2020-08-05 12:56:27 -07:00
commit 1d8ce0e093
59 changed files with 2053 additions and 1602 deletions

View File

@ -19,6 +19,7 @@ Required properties:
nxp,pca9698
nxp,pcal6416
nxp,pcal6524
nxp,pcal9535
nxp,pcal9555a
maxim,max7310
maxim,max7312

View File

@ -0,0 +1,47 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/gpio-pca9570.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: PCA9570 I2C GPO expander
maintainers:
- Sungbo Eo <mans0n@gorani.run>
properties:
compatible:
enum:
- nxp,pca9570
reg:
maxItems: 1
gpio-controller: true
'#gpio-cells':
const: 2
required:
- compatible
- reg
- gpio-controller
- "#gpio-cells"
additionalProperties: false
examples:
- |
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
gpio@24 {
compatible = "nxp,pca9570";
reg = <0x24>;
gpio-controller;
#gpio-cells = <2>;
};
};
...

View File

@ -6,7 +6,9 @@ Required properties:
- First cell is the GPIO line number
- Second cell is used to specify optional
parameters (unused)
- compatible : Should be "xlnx,zynq-gpio-1.0" or "xlnx,zynqmp-gpio-1.0"
- compatible : Should be "xlnx,zynq-gpio-1.0" or
"xlnx,zynqmp-gpio-1.0" or "xlnx,versal-gpio-1.0
or "xlnx,pmc-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

View File

@ -89,6 +89,13 @@ hardware descriptions such as device tree or ACPI:
Consumer Electronics Control bus using only GPIO. It is used to communicate
with devices on the HDMI bus.
- gpio-charger: drivers/power/supply/gpio-charger.c is used if you need to do
battery charging and all you have to go by to check the presence of the
AC charger or more complex tasks such as indicating charging status using
nothing but GPIO lines, this driver provides that and also a clearly defined
way to pass the charging parameters from hardware descriptions such as the
device tree.
Apart from this there are special GPIO drivers in subsystems like MMC/SD to
read card detect and write protect GPIO lines, and in the TTY serial subsystem
to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The

View File

@ -410,7 +410,7 @@ config GPIO_MXS
config GPIO_OCTEON
tristate "Cavium OCTEON GPIO"
depends on GPIOLIB && CAVIUM_OCTEON_SOC
depends on CAVIUM_OCTEON_SOC
default y
help
Say yes here to support the on-chip GPIO lines on the OCTEON
@ -962,6 +962,14 @@ config GPIO_PCA953X_IRQ
Say yes here to enable the pca953x to be used as an interrupt
controller. It requires the driver to be built in the kernel.
config GPIO_PCA9570
tristate "PCA9570 4-Bit I2C GPO expander"
help
Say yes here to enable the GPO driver for the NXP PCA9570 chip.
To compile this driver as a module, choose M here: the module will
be called gpio-pca9570.
config GPIO_PCF857X
tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
select GPIOLIB_IRQCHIP
@ -1117,7 +1125,7 @@ config GPIO_DLN2
config HTC_EGPIO
bool "HTC EGPIO support"
depends on GPIOLIB && ARM
depends on ARM
help
This driver supports the CPLD egpio chip present on
several HTC phones. It provides basic support for input

View File

@ -7,6 +7,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIOLIB) += gpiolib-devres.o
obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o
obj-$(CONFIG_GPIOLIB) += gpiolib-cdev.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
@ -110,6 +111,7 @@ obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o
obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o
obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCA9570) += gpio-pca9570.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o

View File

@ -5,7 +5,7 @@ subsystem.
GPIO descriptors
Starting with commit 79a9becda894 the GPIO subsystem embarked on a journey
to move away from the global GPIO numberspace and toward a decriptor-based
to move away from the global GPIO numberspace and toward a descriptor-based
approach. This means that GPIO consumers, drivers and machine descriptions
ideally have no use or idea of the global GPIO numberspace that has/was
used in the inception of the GPIO subsystem.

View File

@ -368,10 +368,21 @@ static const char *dio48e_names[DIO48E_NGPIO] = {
"PPI Group 1 Port C 5", "PPI Group 1 Port C 6", "PPI Group 1 Port C 7"
};
static int dio48e_irq_init_hw(struct gpio_chip *gc)
{
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(gc);
/* Disable IRQ by default */
inb(dio48egpio->base + 0xB);
return 0;
}
static int dio48e_probe(struct device *dev, unsigned int id)
{
struct dio48e_gpio *dio48egpio;
const char *const name = dev_name(dev);
struct gpio_irq_chip *girq;
int err;
dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
@ -399,13 +410,17 @@ static int dio48e_probe(struct device *dev, unsigned int id)
dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
dio48egpio->base = base[id];
raw_spin_lock_init(&dio48egpio->lock);
girq = &dio48egpio->chip.irq;
girq->chip = &dio48e_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
girq->init_hw = dio48e_irq_init_hw;
err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
}
raw_spin_lock_init(&dio48egpio->lock);
/* initialize all GPIO as output */
outb(0x80, base[id] + 3);
@ -419,13 +434,9 @@ static int dio48e_probe(struct device *dev, unsigned int id)
outb(0x00, base[id] + 6);
outb(0x00, base[id] + 7);
/* disable IRQ by default */
inb(base[id] + 0xB);
err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
}

View File

@ -247,10 +247,22 @@ static const char *idi48_names[IDI48_NGPIO] = {
"Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B"
};
static int idi_48_irq_init_hw(struct gpio_chip *gc)
{
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(gc);
/* Disable IRQ by default */
outb(0, idi48gpio->base + 7);
inb(idi48gpio->base + 7);
return 0;
}
static int idi_48_probe(struct device *dev, unsigned int id)
{
struct idi_48_gpio *idi48gpio;
const char *const name = dev_name(dev);
struct gpio_irq_chip *girq;
int err;
idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
@ -275,6 +287,16 @@ static int idi_48_probe(struct device *dev, unsigned int id)
idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
idi48gpio->base = base[id];
girq = &idi48gpio->chip.irq;
girq->chip = &idi_48_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
girq->init_hw = idi_48_irq_init_hw;
raw_spin_lock_init(&idi48gpio->lock);
spin_lock_init(&idi48gpio->ack_lock);
@ -284,17 +306,6 @@ static int idi_48_probe(struct device *dev, unsigned int id)
return err;
}
/* Disable IRQ by default */
outb(0, base[id] + 7);
inb(base[id] + 7);
err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
return err;
}
err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED,
name, idi48gpio);
if (err) {

View File

@ -224,10 +224,22 @@ static const char *idio_16_names[IDIO_16_NGPIO] = {
"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
};
static int idio_16_irq_init_hw(struct gpio_chip *gc)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
/* Disable IRQ by default */
outb(0, idio16gpio->base + 2);
outb(0, idio16gpio->base + 1);
return 0;
}
static int idio_16_probe(struct device *dev, unsigned int id)
{
struct idio_16_gpio *idio16gpio;
const char *const name = dev_name(dev);
struct gpio_irq_chip *girq;
int err;
idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
@ -256,6 +268,16 @@ static int idio_16_probe(struct device *dev, unsigned int id)
idio16gpio->base = base[id];
idio16gpio->out_state = 0xFFFF;
girq = &idio16gpio->chip.irq;
girq->chip = &idio_16_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
girq->init_hw = idio_16_irq_init_hw;
raw_spin_lock_init(&idio16gpio->lock);
err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
@ -264,17 +286,6 @@ static int idio_16_probe(struct device *dev, unsigned int id)
return err;
}
/* Disable IRQ by default */
outb(0, base[id] + 2);
outb(0, base[id] + 1);
err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
return err;
}
err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
idio16gpio);
if (err) {

View File

@ -238,36 +238,6 @@ unlock:
mutex_unlock(&adnp->i2c_lock);
}
static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
{
struct gpio_chip *chip = &adnp->gpio;
int err;
adnp->reg_shift = get_count_order(num_gpios) - 3;
chip->direction_input = adnp_gpio_direction_input;
chip->direction_output = adnp_gpio_direction_output;
chip->get = adnp_gpio_get;
chip->set = adnp_gpio_set;
chip->can_sleep = true;
if (IS_ENABLED(CONFIG_DEBUG_FS))
chip->dbg_show = adnp_gpio_dbg_show;
chip->base = -1;
chip->ngpio = num_gpios;
chip->label = adnp->client->name;
chip->parent = &adnp->client->dev;
chip->of_node = chip->parent->of_node;
chip->owner = THIS_MODULE;
err = devm_gpiochip_add_data(&adnp->client->dev, chip, adnp);
if (err)
return err;
return 0;
}
static irqreturn_t adnp_irq(int irq, void *data)
{
struct adnp *adnp = data;
@ -464,18 +434,54 @@ static int adnp_irq_setup(struct adnp *adnp)
return err;
}
err = gpiochip_irqchip_add_nested(chip,
&adnp_irq_chip,
0,
handle_simple_irq,
IRQ_TYPE_NONE);
if (err) {
dev_err(chip->parent,
"could not connect irqchip to gpiochip\n");
return err;
return 0;
}
static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios,
bool is_irq_controller)
{
struct gpio_chip *chip = &adnp->gpio;
int err;
adnp->reg_shift = get_count_order(num_gpios) - 3;
chip->direction_input = adnp_gpio_direction_input;
chip->direction_output = adnp_gpio_direction_output;
chip->get = adnp_gpio_get;
chip->set = adnp_gpio_set;
chip->can_sleep = true;
if (IS_ENABLED(CONFIG_DEBUG_FS))
chip->dbg_show = adnp_gpio_dbg_show;
chip->base = -1;
chip->ngpio = num_gpios;
chip->label = adnp->client->name;
chip->parent = &adnp->client->dev;
chip->of_node = chip->parent->of_node;
chip->owner = THIS_MODULE;
if (is_irq_controller) {
struct gpio_irq_chip *girq;
err = adnp_irq_setup(adnp);
if (err)
return err;
girq = &chip->irq;
girq->chip = &adnp_irq_chip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->threaded = true;
}
gpiochip_set_nested_irqchip(chip, &adnp_irq_chip, adnp->client->irq);
err = devm_gpiochip_add_data(&adnp->client->dev, chip, adnp);
if (err)
return err;
return 0;
}
@ -503,16 +509,11 @@ static int adnp_i2c_probe(struct i2c_client *client,
mutex_init(&adnp->i2c_lock);
adnp->client = client;
err = adnp_gpio_setup(adnp, num_gpios);
err = adnp_gpio_setup(adnp, num_gpios,
of_property_read_bool(np, "interrupt-controller"));
if (err)
return err;
if (of_find_property(np, "interrupt-controller", NULL)) {
err = adnp_irq_setup(adnp);
if (err)
return err;
}
i2c_set_clientdata(client, adnp);
return 0;

View File

@ -272,13 +272,24 @@ static irqreturn_t adp5588_irq_handler(int irq, void *devid)
return IRQ_HANDLED;
}
static int adp5588_irq_init_hw(struct gpio_chip *gc)
{
struct adp5588_gpio *dev = gpiochip_get_data(gc);
/* Enable IRQs after registering chip */
adp5588_gpio_write(dev->client, CFG,
ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_KE_IEN);
return 0;
}
static int adp5588_irq_setup(struct adp5588_gpio *dev)
{
struct i2c_client *client = dev->client;
int ret;
struct adp5588_gpio_platform_data *pdata =
dev_get_platdata(&client->dev);
int irq_base = pdata ? pdata->irq_base : 0;
struct gpio_irq_chip *girq;
adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
@ -294,21 +305,19 @@ static int adp5588_irq_setup(struct adp5588_gpio *dev)
client->irq);
return ret;
}
ret = gpiochip_irqchip_add_nested(&dev->gpio_chip,
&adp5588_irq_chip, irq_base,
handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
gpiochip_set_nested_irqchip(&dev->gpio_chip,
&adp5588_irq_chip,
client->irq);
adp5588_gpio_write(client, CFG,
ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_KE_IEN);
/* This will be registered in the call to devm_gpiochip_add_data() */
girq = &dev->gpio_chip.irq;
girq->chip = &adp5588_irq_chip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->first = pdata ? pdata->irq_base : 0;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->init_hw = adp5588_irq_init_hw;
girq->threaded = true;
return 0;
}

View File

@ -10,6 +10,7 @@
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
@ -38,9 +39,9 @@ static DEFINE_IDR(gpio_aggregator_idr);
static char *get_arg(char **args)
{
char *start = *args, *end;
char *start, *end;
start = skip_spaces(start);
start = skip_spaces(*args);
if (!*start)
return NULL;
@ -111,55 +112,45 @@ static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key,
static int aggr_parse(struct gpio_aggregator *aggr)
{
unsigned int first_index, last_index, i, n = 0;
char *name, *offsets, *first, *last, *next;
char *args = aggr->args;
int error;
unsigned long *bitmap;
unsigned int i, n = 0;
char *name, *offsets;
int error = 0;
bitmap = bitmap_alloc(ARCH_NR_GPIOS, GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
for (name = get_arg(&args), offsets = get_arg(&args); name;
offsets = get_arg(&args)) {
if (IS_ERR(name)) {
pr_err("Cannot get GPIO specifier: %pe\n", name);
return PTR_ERR(name);
error = PTR_ERR(name);
goto free_bitmap;
}
if (!isrange(offsets)) {
/* Named GPIO line */
error = aggr_add_gpio(aggr, name, U16_MAX, &n);
if (error)
return error;
goto free_bitmap;
name = offsets;
continue;
}
/* GPIO chip + offset(s) */
for (first = offsets; *first; first = next) {
next = strchrnul(first, ',');
if (*next)
*next++ = '\0';
error = bitmap_parselist(offsets, bitmap, ARCH_NR_GPIOS);
if (error) {
pr_err("Cannot parse %s: %d\n", offsets, error);
goto free_bitmap;
}
last = strchr(first, '-');
if (last)
*last++ = '\0';
if (kstrtouint(first, 10, &first_index)) {
pr_err("Cannot parse GPIO index %s\n", first);
return -EINVAL;
}
if (!last) {
last_index = first_index;
} else if (kstrtouint(last, 10, &last_index)) {
pr_err("Cannot parse GPIO index %s\n", last);
return -EINVAL;
}
for (i = first_index; i <= last_index; i++) {
error = aggr_add_gpio(aggr, name, i, &n);
if (error)
return error;
}
for_each_set_bit(i, bitmap, ARCH_NR_GPIOS) {
error = aggr_add_gpio(aggr, name, i, &n);
if (error)
goto free_bitmap;
}
name = get_arg(&args);
@ -167,10 +158,12 @@ static int aggr_parse(struct gpio_aggregator *aggr)
if (!n) {
pr_err("No GPIOs specified\n");
return -EINVAL;
error = -EINVAL;
}
return 0;
free_bitmap:
bitmap_free(bitmap);
return error;
}
static ssize_t new_device_store(struct device_driver *driver, const char *buf,

View File

@ -24,6 +24,7 @@
* @interrupt_trigger : specifies the hardware configured IRQ trigger type
* (rising, falling, both, high)
* @mapped_irq : kernel mapped irq number.
* @irq_chip : IRQ chip configuration
*/
struct altera_gpio_chip {
struct of_mm_gpio_chip mmchip;
@ -69,7 +70,7 @@ static void altera_gpio_irq_mask(struct irq_data *d)
raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
}
/**
/*
* This controller's IRQ type is synthesized in hardware, so this function
* just checks if the requested set_type matches the synthesized IRQ type
*/

View File

@ -129,7 +129,7 @@ static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio)
regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value);
}
static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned int gpio)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
int reg = to_reg(gpio, CTRL_OUT);
@ -140,7 +140,7 @@ static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
return regmap_write(cg->regmap, reg, CTLO_INPUT_SET);
}
static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio,
int value)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
@ -152,7 +152,7 @@ static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value);
}
static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned int gpio)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
unsigned int val;
@ -169,7 +169,7 @@ static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
}
static void crystalcove_gpio_set(struct gpio_chip *chip,
unsigned gpio, int value)
unsigned int gpio, int value)
{
struct crystalcove_gpio *cg = gpiochip_get_data(chip);
int reg = to_reg(gpio, CTRL_OUT);
@ -183,7 +183,7 @@ static void crystalcove_gpio_set(struct gpio_chip *chip,
regmap_update_bits(cg->regmap, reg, 1, 0);
}
static int crystalcove_irq_type(struct irq_data *data, unsigned type)
static int crystalcove_irq_type(struct irq_data *data, unsigned int type)
{
struct crystalcove_gpio *cg =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
@ -330,6 +330,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
int retval;
struct device *dev = pdev->dev.parent;
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
struct gpio_irq_chip *girq;
if (irq < 0)
return irq;
@ -353,46 +354,39 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
cg->chip.dbg_show = crystalcove_gpio_dbg_show;
cg->regmap = pmic->regmap;
girq = &cg->chip.irq;
girq->chip = &crystalcove_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->threaded = true;
retval = devm_request_threaded_irq(&pdev->dev, irq, NULL,
crystalcove_gpio_irq_handler,
IRQF_ONESHOT, KBUILD_MODNAME, cg);
if (retval) {
dev_warn(&pdev->dev, "request irq failed: %d\n", retval);
return retval;
}
retval = devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg);
if (retval) {
dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval);
return retval;
}
gpiochip_irqchip_add_nested(&cg->chip, &crystalcove_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler,
IRQF_ONESHOT, KBUILD_MODNAME, cg);
if (retval) {
dev_warn(&pdev->dev, "request irq failed: %d\n", retval);
return retval;
}
gpiochip_set_nested_irqchip(&cg->chip, &crystalcove_irqchip, irq);
return 0;
}
static int crystalcove_gpio_remove(struct platform_device *pdev)
{
struct crystalcove_gpio *cg = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
if (irq >= 0)
free_irq(irq, cg);
return 0;
}
static struct platform_driver crystalcove_gpio_driver = {
.probe = crystalcove_gpio_probe,
.remove = crystalcove_gpio_remove,
.driver = {
.name = "crystal_cove_gpio",
},
};
module_platform_driver(crystalcove_gpio_driver);
MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");

View File

@ -440,6 +440,7 @@ static int dln2_gpio_probe(struct platform_device *pdev)
{
struct dln2_gpio *dln2;
struct device *dev = &pdev->dev;
struct gpio_irq_chip *girq;
int pins;
int ret;
@ -476,6 +477,15 @@ static int dln2_gpio_probe(struct platform_device *pdev)
dln2->gpio.direction_output = dln2_gpio_direction_output;
dln2->gpio.set_config = dln2_gpio_set_config;
girq = &dln2->gpio.irq;
girq->chip = &dln2_gpio_irqchip;
/* The event comes from the outside so no parent handler */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
platform_set_drvdata(pdev, dln2);
ret = devm_gpiochip_add_data(dev, &dln2->gpio, dln2);
@ -484,13 +494,6 @@ static int dln2_gpio_probe(struct platform_device *pdev)
return ret;
}
ret = gpiochip_irqchip_add(&dln2->gpio, &dln2_gpio_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret < 0) {
dev_err(dev, "failed to add irq chip: %d\n", ret);
return ret;
}
ret = dln2_register_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV,
dln2_gpio_event);
if (ret) {

View File

@ -74,8 +74,8 @@ struct ichx_desc {
u32 use_sel_ignore[3];
/* Some chipsets have quirks, let these use their own request/get */
int (*request)(struct gpio_chip *chip, unsigned offset);
int (*get)(struct gpio_chip *chip, unsigned offset);
int (*request)(struct gpio_chip *chip, unsigned int offset);
int (*get)(struct gpio_chip *chip, unsigned int offset);
/*
* Some chipsets don't let reading output values on GPIO_LVL register
@ -100,7 +100,7 @@ static int modparam_gpiobase = -1; /* dynamic */
module_param_named(gpiobase, modparam_gpiobase, int, 0444);
MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default.");
static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
static int ichx_write_bit(int reg, unsigned int nr, int val, int verify)
{
unsigned long flags;
u32 data, tmp;
@ -132,7 +132,7 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
return (verify && data != tmp) ? -EPERM : 0;
}
static int ichx_read_bit(int reg, unsigned nr)
static int ichx_read_bit(int reg, unsigned int nr)
{
unsigned long flags;
u32 data;
@ -152,12 +152,12 @@ static int ichx_read_bit(int reg, unsigned nr)
return !!(data & BIT(bit));
}
static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned int nr)
{
return !!(ichx_priv.use_gpio & BIT(nr / 32));
}
static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr)
static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned int nr)
{
if (ichx_read_bit(GPIO_IO_SEL, nr))
return GPIO_LINE_DIRECTION_IN;
@ -165,7 +165,7 @@ static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr)
return GPIO_LINE_DIRECTION_OUT;
}
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned int nr)
{
/*
* Try setting pin as an input and verify it worked since many pins
@ -174,7 +174,7 @@ static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
return ichx_write_bit(GPIO_IO_SEL, nr, 1, 1);
}
static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned int nr,
int val)
{
/* Disable blink hardware which is available for GPIOs from 0 to 31. */
@ -191,12 +191,12 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
return ichx_write_bit(GPIO_IO_SEL, nr, 0, 1);
}
static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
static int ichx_gpio_get(struct gpio_chip *chip, unsigned int nr)
{
return ichx_read_bit(GPIO_LVL, nr);
}
static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
static int ich6_gpio_get(struct gpio_chip *chip, unsigned int nr)
{
unsigned long flags;
u32 data;
@ -223,7 +223,7 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
}
}
static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
static int ichx_gpio_request(struct gpio_chip *chip, unsigned int nr)
{
if (!ichx_gpio_check_available(chip, nr))
return -ENXIO;
@ -240,7 +240,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
}
static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr)
static int ich6_gpio_request(struct gpio_chip *chip, unsigned int nr)
{
/*
* Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100
@ -254,7 +254,7 @@ static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr)
return ichx_gpio_request(chip, nr);
}
static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
static void ichx_gpio_set(struct gpio_chip *chip, unsigned int nr, int val)
{
ichx_write_bit(GPIO_LVL, nr, val, 0);
}

View File

@ -47,13 +47,13 @@
/**
* struct it87_gpio - it87-specific GPIO chip
* @chip the underlying gpio_chip structure
* @lock a lock to avoid races between operations
* @io_base base address for gpio ports
* @io_size size of the port rage starting from io_base.
* @output_base Super I/O register address for Output Enable register
* @simple_base Super I/O 'Simple I/O' Enable register
* @simple_size Super IO 'Simple I/O' Enable register size; this is
* @chip: the underlying gpio_chip structure
* @lock: a lock to avoid races between operations
* @io_base: base address for gpio ports
* @io_size: size of the port rage starting from io_base.
* @output_base: Super I/O register address for Output Enable register
* @simple_base: Super I/O 'Simple I/O' Enable register
* @simple_size: Super IO 'Simple I/O' Enable register size; this is
* required because IT87xx chips might only provide Simple I/O
* switches on a subset of lines, whereas the others keep the
* same status all time.

View File

@ -503,6 +503,8 @@ static int max732x_irq_setup(struct max732x_chip *chip,
if (((pdata && pdata->irq_base) || client->irq)
&& has_irq != INT_NONE) {
struct gpio_irq_chip *girq;
if (pdata)
irq_base = pdata->irq_base;
chip->irq_features = has_irq;
@ -517,19 +519,17 @@ static int max732x_irq_setup(struct max732x_chip *chip,
client->irq);
return ret;
}
ret = gpiochip_irqchip_add_nested(&chip->gpio_chip,
&max732x_irq_chip,
irq_base,
handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
gpiochip_set_nested_irqchip(&chip->gpio_chip,
&max732x_irq_chip,
client->irq);
girq = &chip->gpio_chip.irq;
girq->chip = &max732x_irq_chip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->threaded = true;
girq->first = irq_base; /* FIXME: get rid of this */
}
return 0;
@ -695,15 +695,15 @@ static int max732x_probe(struct i2c_client *client,
return ret;
}
ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
if (ret)
return ret;
ret = max732x_irq_setup(chip, id);
if (ret)
return ret;
if (pdata && pdata->setup) {
ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
if (ret)
return ret;
if (pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0)

View File

@ -19,8 +19,8 @@ struct max77620_gpio {
struct regmap *rmap;
struct device *dev;
struct mutex buslock; /* irq_bus_lock */
unsigned int irq_type[8];
bool irq_enabled[8];
unsigned int irq_type[MAX77620_GPIO_NR];
bool irq_enabled[MAX77620_GPIO_NR];
};
static irqreturn_t max77620_gpio_irqhandler(int irq, void *data)
@ -38,7 +38,7 @@ static irqreturn_t max77620_gpio_irqhandler(int irq, void *data)
pending = value;
for_each_set_bit(offset, &pending, 8) {
for_each_set_bit(offset, &pending, MAX77620_GPIO_NR) {
unsigned int virq;
virq = irq_find_mapping(gpio->gpio_chip.irq.domain, offset);
@ -260,26 +260,54 @@ static int max77620_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
return -ENOTSUPP;
}
static int max77620_gpio_irq_init_hw(struct gpio_chip *gc)
{
struct max77620_gpio *gpio = gpiochip_get_data(gc);
unsigned int i;
int err;
/*
* GPIO interrupts may be left ON after bootloader, hence let's
* pre-initialize hardware to the expected state by disabling all
* the interrupts.
*/
for (i = 0; i < MAX77620_GPIO_NR; i++) {
err = regmap_update_bits(gpio->rmap, GPIO_REG_ADDR(i),
MAX77620_CNFG_GPIO_INT_MASK, 0);
if (err < 0) {
dev_err(gpio->dev,
"failed to disable interrupt: %d\n", err);
return err;
}
}
return 0;
}
static int max77620_gpio_probe(struct platform_device *pdev)
{
struct max77620_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct max77620_gpio *mgpio;
int gpio_irq;
struct gpio_irq_chip *girq;
unsigned int gpio_irq;
int ret;
gpio_irq = platform_get_irq(pdev, 0);
if (gpio_irq <= 0)
return -ENODEV;
ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
gpio_irq = ret;
mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL);
if (!mgpio)
return -ENOMEM;
mutex_init(&mgpio->buslock);
mgpio->rmap = chip->rmap;
mgpio->dev = &pdev->dev;
mgpio->gpio_chip.label = pdev->name;
mgpio->gpio_chip.parent = &pdev->dev;
mgpio->gpio_chip.parent = pdev->dev.parent;
mgpio->gpio_chip.direction_input = max77620_gpio_dir_input;
mgpio->gpio_chip.get = max77620_gpio_get;
mgpio->gpio_chip.direction_output = max77620_gpio_dir_output;
@ -288,9 +316,17 @@ static int max77620_gpio_probe(struct platform_device *pdev)
mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
mgpio->gpio_chip.can_sleep = 1;
mgpio->gpio_chip.base = -1;
#ifdef CONFIG_OF_GPIO
mgpio->gpio_chip.of_node = pdev->dev.parent->of_node;
#endif
girq = &mgpio->gpio_chip.irq;
girq->chip = &max77620_gpio_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
girq->init_hw = max77620_gpio_irq_init_hw,
girq->threaded = true;
platform_set_drvdata(pdev, mgpio);
@ -300,21 +336,14 @@ static int max77620_gpio_probe(struct platform_device *pdev)
return ret;
}
mutex_init(&mgpio->buslock);
gpiochip_irqchip_add_nested(&mgpio->gpio_chip, &max77620_gpio_irqchip,
0, handle_edge_irq, IRQ_TYPE_NONE);
ret = request_threaded_irq(gpio_irq, NULL, max77620_gpio_irqhandler,
IRQF_ONESHOT, "max77620-gpio", mgpio);
ret = devm_request_threaded_irq(&pdev->dev, gpio_irq, NULL,
max77620_gpio_irqhandler, IRQF_ONESHOT,
"max77620-gpio", mgpio);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret);
return ret;
}
gpiochip_set_nested_irqchip(&mgpio->gpio_chip, &max77620_gpio_irqchip,
gpio_irq);
return 0;
}

View File

@ -44,7 +44,7 @@ struct ioh_regs {
/**
* struct ioh_gpio_reg_data - The register store data.
* @ien_reg To store contents of interrupt enable register.
* @ien_reg: To store contents of interrupt enable register.
* @imask_reg: To store contents of interrupt mask regist
* @po_reg: To store contents of PO register.
* @pm_reg: To store contents of PM register.

View File

@ -127,7 +127,7 @@ static int mlxbf_gpio_resume(struct platform_device *pdev)
}
#endif
static const struct acpi_device_id mlxbf_gpio_acpi_match[] = {
static const struct acpi_device_id __maybe_unused mlxbf_gpio_acpi_match[] = {
{ "MLNXBF02", 0 },
{}
};

View File

@ -149,6 +149,8 @@ static int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs)
* Release the YU arm_gpio_lock after changing the direction mode.
*/
static void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs)
__releases(&gs->gc.bgpio_lock)
__releases(yu_arm_gpio_lock_param.lock)
{
writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io);
spin_unlock(&gs->gc.bgpio_lock);
@ -309,7 +311,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev)
}
#endif
static const struct acpi_device_id mlxbf2_gpio_acpi_match[] = {
static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = {
{ "MLNXBF22", 0 },
{},
};

View File

@ -195,8 +195,7 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask,
*bits &= ~*mask;
/* Create a mirrored mask */
bit = -1;
while ((bit = find_next_bit(mask, gc->ngpio, bit + 1)) < gc->ngpio)
for_each_set_bit(bit, mask, gc->ngpio)
readmask |= bgpio_line2mask(gc, bit);
/* Read the register */
@ -206,8 +205,7 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask,
* Mirror the result into the "bits" result, this will give line 0
* in bit 0 ... line 31 in bit 31 for a 32bit register.
*/
bit = -1;
while ((bit = find_next_bit(&val, gc->ngpio, bit + 1)) < gc->ngpio)
for_each_set_bit(bit, &val, gc->ngpio)
*bits |= bgpio_line2mask(gc, bit);
return 0;
@ -272,15 +270,11 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc,
*set_mask = 0;
*clear_mask = 0;
for (i = 0; i < gc->bgpio_bits; i++) {
if (*mask == 0)
break;
if (__test_and_clear_bit(i, mask)) {
if (test_bit(i, bits))
*set_mask |= bgpio_line2mask(gc, i);
else
*clear_mask |= bgpio_line2mask(gc, i);
}
for_each_set_bit(i, mask, gc->bgpio_bits) {
if (test_bit(i, bits))
*set_mask |= bgpio_line2mask(gc, i);
else
*clear_mask |= bgpio_line2mask(gc, i);
}
}

View File

@ -417,7 +417,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, mpc8xxx_gc->irqn,
mpc8xxx_gpio_irq_cascade,
IRQF_NO_THREAD | IRQF_SHARED, "gpio-cascade",
IRQF_SHARED, "gpio-cascade",
mpc8xxx_gc);
if (ret) {
dev_err(&pdev->dev, "%s: failed to devm_request_irq(%d), ret = %d\n",

View File

@ -846,6 +846,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
const char *label;
int i;
regmap_read(mvchip->regs, GPIO_OUT_OFF + mvchip->offset, &out);
@ -857,15 +858,10 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
edg_msk = mvebu_gpio_read_edge_mask(mvchip);
lvl_msk = mvebu_gpio_read_level_mask(mvchip);
for (i = 0; i < chip->ngpio; i++) {
const char *label;
for_each_requested_gpio(chip, i, label) {
u32 msk;
bool is_out;
label = gpiochip_is_requested(chip, i);
if (!label)
continue;
msk = BIT(i);
is_out = !(io_conf & msk);

View File

@ -60,6 +60,7 @@ struct gpio_bank {
struct clk *dbck;
struct notifier_block nb;
unsigned int is_suspended:1;
unsigned int needs_resume:1;
u32 mod_usage;
u32 irq_usage;
u32 dbck_enable_mask;
@ -896,12 +897,23 @@ static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
unsigned long config)
{
u32 debounce;
int ret = -ENOTSUPP;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
ret = gpiochip_generic_config(chip, offset, config);
break;
case PIN_CONFIG_INPUT_DEBOUNCE:
debounce = pinconf_to_config_argument(config);
ret = omap_gpio_debounce(chip, offset, debounce);
break;
default:
break;
}
debounce = pinconf_to_config_argument(config);
return omap_gpio_debounce(chip, offset, debounce);
return ret;
}
static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@ -1504,9 +1516,34 @@ static int __maybe_unused omap_gpio_runtime_resume(struct device *dev)
return 0;
}
static int omap_gpio_suspend(struct device *dev)
{
struct gpio_bank *bank = dev_get_drvdata(dev);
if (bank->is_suspended)
return 0;
bank->needs_resume = 1;
return omap_gpio_runtime_suspend(dev);
}
static int omap_gpio_resume(struct device *dev)
{
struct gpio_bank *bank = dev_get_drvdata(dev);
if (!bank->needs_resume)
return 0;
bank->needs_resume = 0;
return omap_gpio_runtime_resume(dev);
}
static const struct dev_pm_ops gpio_pm_ops = {
SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume,
NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume)
};
static struct platform_driver omap_gpio_driver = {

View File

@ -89,6 +89,7 @@ static const struct i2c_device_id pca953x_id[] = {
{ "pcal6416", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
{ "pcal6524", 24 | PCA953X_TYPE | PCA_LATCH_INT, },
{ "pcal9535", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
{ "pcal9555a", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
{ "max7310", 8 | PCA953X_TYPE, },
@ -833,6 +834,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
struct irq_chip *irq_chip = &chip->irq_chip;
DECLARE_BITMAP(reg_direction, MAX_LINE);
DECLARE_BITMAP(irq_stat, MAX_LINE);
struct gpio_irq_chip *girq;
int ret;
if (dmi_first_match(pca953x_dmi_acpi_irq_info)) {
@ -863,6 +865,26 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
bitmap_and(chip->irq_stat, irq_stat, reg_direction, chip->gpio_chip.ngpio);
mutex_init(&chip->irq_lock);
irq_chip->name = dev_name(&client->dev);
irq_chip->irq_mask = pca953x_irq_mask;
irq_chip->irq_unmask = pca953x_irq_unmask;
irq_chip->irq_set_wake = pca953x_irq_set_wake;
irq_chip->irq_bus_lock = pca953x_irq_bus_lock;
irq_chip->irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock;
irq_chip->irq_set_type = pca953x_irq_set_type;
irq_chip->irq_shutdown = pca953x_irq_shutdown;
girq = &chip->gpio_chip.irq;
girq->chip = irq_chip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->threaded = true;
girq->first = irq_base; /* FIXME: get rid of this */
ret = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pca953x_irq_handler,
IRQF_ONESHOT | IRQF_SHARED,
@ -873,26 +895,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base)
return ret;
}
irq_chip->name = dev_name(&chip->client->dev);
irq_chip->irq_mask = pca953x_irq_mask;
irq_chip->irq_unmask = pca953x_irq_unmask;
irq_chip->irq_set_wake = pca953x_irq_set_wake;
irq_chip->irq_bus_lock = pca953x_irq_bus_lock;
irq_chip->irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock;
irq_chip->irq_set_type = pca953x_irq_set_type;
irq_chip->irq_shutdown = pca953x_irq_shutdown;
ret = gpiochip_irqchip_add_nested(&chip->gpio_chip, irq_chip,
irq_base, handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
gpiochip_set_nested_irqchip(&chip->gpio_chip, irq_chip, client->irq);
return 0;
}
@ -1079,11 +1081,11 @@ static int pca953x_probe(struct i2c_client *client,
if (ret)
goto err_exit;
ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
ret = pca953x_irq_setup(chip, irq_base);
if (ret)
goto err_exit;
ret = pca953x_irq_setup(chip, irq_base);
ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
if (ret)
goto err_exit;
@ -1234,6 +1236,7 @@ static const struct of_device_id pca953x_dt_ids[] = {
{ .compatible = "nxp,pcal6416", .data = OF_953X(16, PCA_LATCH_INT), },
{ .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), },
{ .compatible = "nxp,pcal9535", .data = OF_953X(16, PCA_LATCH_INT), },
{ .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_LATCH_INT), },
{ .compatible = "maxim,max7310", .data = OF_953X( 8, 0), },

146
drivers/gpio/gpio-pca9570.c Normal file
View File

@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for PCA9570 I2C GPO expander
*
* Copyright (C) 2020 Sungbo Eo <mans0n@gorani.run>
*
* Based on gpio-tpic2810.c
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
* Andrew F. Davis <afd@ti.com>
*/
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/property.h>
/**
* struct pca9570 - GPIO driver data
* @chip: GPIO controller chip
* @lock: Protects write sequences
* @out: Buffer for device register
*/
struct pca9570 {
struct gpio_chip chip;
struct mutex lock;
u8 out;
};
static int pca9570_read(struct pca9570 *gpio, u8 *value)
{
struct i2c_client *client = to_i2c_client(gpio->chip.parent);
int ret;
ret = i2c_smbus_read_byte(client);
if (ret < 0)
return ret;
*value = ret;
return 0;
}
static int pca9570_write(struct pca9570 *gpio, u8 value)
{
struct i2c_client *client = to_i2c_client(gpio->chip.parent);
return i2c_smbus_write_byte(client, value);
}
static int pca9570_get_direction(struct gpio_chip *chip,
unsigned offset)
{
/* This device always output */
return GPIO_LINE_DIRECTION_OUT;
}
static int pca9570_get(struct gpio_chip *chip, unsigned offset)
{
struct pca9570 *gpio = gpiochip_get_data(chip);
u8 buffer;
int ret;
ret = pca9570_read(gpio, &buffer);
if (ret)
return ret;
return !!(buffer & BIT(offset));
}
static void pca9570_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct pca9570 *gpio = gpiochip_get_data(chip);
u8 buffer;
int ret;
mutex_lock(&gpio->lock);
buffer = gpio->out;
if (value)
buffer |= BIT(offset);
else
buffer &= ~BIT(offset);
ret = pca9570_write(gpio, buffer);
if (ret)
goto out;
gpio->out = buffer;
out:
mutex_unlock(&gpio->lock);
}
static int pca9570_probe(struct i2c_client *client)
{
struct pca9570 *gpio;
gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio)
return -ENOMEM;
gpio->chip.label = client->name;
gpio->chip.parent = &client->dev;
gpio->chip.owner = THIS_MODULE;
gpio->chip.get_direction = pca9570_get_direction;
gpio->chip.get = pca9570_get;
gpio->chip.set = pca9570_set;
gpio->chip.base = -1;
gpio->chip.ngpio = (uintptr_t)device_get_match_data(&client->dev);
gpio->chip.can_sleep = true;
mutex_init(&gpio->lock);
/* Read the current output level */
pca9570_read(gpio, &gpio->out);
i2c_set_clientdata(client, gpio);
return devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
}
static const struct i2c_device_id pca9570_id_table[] = {
{ "pca9570", 4 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, pca9570_id_table);
static const struct of_device_id pca9570_of_match_table[] = {
{ .compatible = "nxp,pca9570", .data = (void *)4 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pca9570_of_match_table);
static struct i2c_driver pca9570_driver = {
.driver = {
.name = "pca9570",
.of_match_table = pca9570_of_match_table,
},
.probe_new = pca9570_probe,
.id_table = pca9570_id_table,
};
module_i2c_driver(pca9570_driver);
MODULE_AUTHOR("Sungbo Eo <mans0n@gorani.run>");
MODULE_DESCRIPTION("GPIO expander driver for PCA9570");
MODULE_LICENSE("GPL v2");

View File

@ -334,29 +334,19 @@ static int pcf857x_probe(struct i2c_client *client,
gpio->out = ~n_latch;
gpio->status = gpio->out;
status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
if (status < 0)
goto fail;
/* Enable irqchip if we have an interrupt */
if (client->irq) {
gpio->irqchip.name = "pcf857x",
gpio->irqchip.irq_enable = pcf857x_irq_enable,
gpio->irqchip.irq_disable = pcf857x_irq_disable,
gpio->irqchip.irq_ack = noop,
gpio->irqchip.irq_mask = noop,
gpio->irqchip.irq_unmask = noop,
gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
status = gpiochip_irqchip_add_nested(&gpio->chip,
&gpio->irqchip,
0, handle_level_irq,
IRQ_TYPE_NONE);
if (status) {
dev_err(&client->dev, "cannot add irqchip\n");
goto fail;
}
struct gpio_irq_chip *girq;
gpio->irqchip.name = "pcf857x";
gpio->irqchip.irq_enable = pcf857x_irq_enable;
gpio->irqchip.irq_disable = pcf857x_irq_disable;
gpio->irqchip.irq_ack = noop;
gpio->irqchip.irq_mask = noop;
gpio->irqchip.irq_unmask = noop;
gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake;
gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock;
gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock;
status = devm_request_threaded_irq(&client->dev, client->irq,
NULL, pcf857x_irq, IRQF_ONESHOT |
@ -365,10 +355,21 @@ static int pcf857x_probe(struct i2c_client *client,
if (status)
goto fail;
gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
client->irq);
girq = &gpio->chip.irq;
girq->chip = &gpio->irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
girq->threaded = true;
}
status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
if (status < 0)
goto fail;
/* Let platform code set up the GPIOs and their users.
* Now is the first time anyone could use them.
*/

View File

@ -95,7 +95,7 @@ struct pch_gpio {
spinlock_t spinlock;
};
static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
static void pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
{
u32 reg_val;
struct pch_gpio *chip = gpiochip_get_data(gpio);
@ -112,14 +112,14 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
spin_unlock_irqrestore(&chip->spinlock, flags);
}
static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
static int pch_gpio_get(struct gpio_chip *gpio, unsigned int nr)
{
struct pch_gpio *chip = gpiochip_get_data(gpio);
return !!(ioread32(&chip->reg->pi) & BIT(nr));
}
static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned int nr,
int val)
{
struct pch_gpio *chip = gpiochip_get_data(gpio);
@ -146,7 +146,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
return 0;
}
static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned int nr)
{
struct pch_gpio *chip = gpiochip_get_data(gpio);
u32 pm;
@ -196,9 +196,10 @@ static void __maybe_unused pch_gpio_restore_reg_conf(struct pch_gpio *chip)
iowrite32(chip->pch_gpio_reg.gpio_use_sel_reg, &chip->reg->gpio_use_sel);
}
static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
static int pch_gpio_to_irq(struct gpio_chip *gpio, unsigned int offset)
{
struct pch_gpio *chip = gpiochip_get_data(gpio);
return chip->irq_base + offset;
}
@ -304,9 +305,10 @@ static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
unsigned long reg_val = ioread32(&chip->reg->istatus);
int i;
dev_dbg(chip->dev, "irq=%d status=0x%lx\n", irq, reg_val);
dev_vdbg(chip->dev, "irq=%d status=0x%lx\n", irq, reg_val);
reg_val &= BIT(gpio_pins[chip->ioh]) - 1;
for_each_set_bit(i, &reg_val, gpio_pins[chip->ioh])
generic_handle_irq(chip->irq_base + i);

View File

@ -280,6 +280,17 @@ static const char *idio_16_names[IDIO_16_NGPIO] = {
"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
};
static int idio_16_irq_init_hw(struct gpio_chip *gc)
{
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
/* Disable IRQ by default and clear any pending interrupt */
iowrite8(0, &idio16gpio->reg->irq_ctl);
iowrite8(0, &idio16gpio->reg->in0_7);
return 0;
}
static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *const dev = &pdev->dev;
@ -287,6 +298,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int err;
const size_t pci_bar_index = 2;
const char *const name = pci_name(pdev);
struct gpio_irq_chip *girq;
idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
if (!idio16gpio)
@ -323,6 +335,16 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
idio16gpio->chip.set = idio_16_gpio_set;
idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
girq = &idio16gpio->chip.irq;
girq->chip = &idio_16_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
girq->init_hw = idio_16_irq_init_hw;
raw_spin_lock_init(&idio16gpio->lock);
err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
@ -331,17 +353,6 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return err;
}
/* Disable IRQ by default and clear any pending interrupt */
iowrite8(0, &idio16gpio->reg->irq_ctl);
iowrite8(0, &idio16gpio->reg->in0_7);
err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
return err;
}
err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED,
name, idio16gpio);
if (err) {

View File

@ -457,6 +457,7 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int err;
const size_t pci_bar_index = 2;
const char *const name = pci_name(pdev);
struct gpio_irq_chip *girq;
idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
if (!idio24gpio)
@ -490,6 +491,15 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
idio24gpio->chip.set = idio_24_gpio_set;
idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple;
girq = &idio24gpio->chip.irq;
girq->chip = &idio_24_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
raw_spin_lock_init(&idio24gpio->lock);
/* Software board reset */
@ -501,13 +511,6 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return err;
}
err = gpiochip_irqchip_add(&idio24gpio->chip, &idio_24_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
return err;
}
err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
name, idio24gpio);
if (err) {

View File

@ -48,7 +48,7 @@ enum {
* struct sprd_pmic_eic - PMIC EIC controller
* @chip: the gpio_chip structure.
* @intc: the irq_chip structure.
* @regmap: the regmap from the parent device.
* @map: the regmap from the parent device.
* @offset: the EIC controller's offset address of the PMIC.
* @reg: the array to cache the EIC registers.
* @buslock: for bus lock/sync and unlock.

View File

@ -438,6 +438,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)
struct resource *irq;
struct gpio_chip *gpio_chip;
struct irq_chip *irq_chip;
struct gpio_irq_chip *girq;
struct device *dev = &pdev->dev;
const char *name = dev_name(dev);
unsigned int npins;
@ -496,19 +497,21 @@ static int gpio_rcar_probe(struct platform_device *pdev)
irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
girq = &gpio_chip->irq;
girq->chip = irq_chip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
ret = gpiochip_add_data(gpio_chip, p);
if (ret) {
dev_err(dev, "failed to add GPIO controller\n");
goto err0;
}
ret = gpiochip_irqchip_add(gpio_chip, irq_chip, 0, handle_level_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "cannot add irqchip\n");
goto err1;
}
p->irq_parent = irq->start;
if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler,
IRQF_SHARED, name, p)) {

View File

@ -49,7 +49,7 @@ struct sama5d2_piobu {
struct regmap *regmap;
};
/**
/*
* sama5d2_piobu_setup_pin() - prepares a pin for set_direction call
*
* Do not consider pin for tamper detection (normal and backup modes)
@ -73,7 +73,7 @@ static int sama5d2_piobu_setup_pin(struct gpio_chip *chip, unsigned int pin)
return regmap_update_bits(piobu->regmap, PIOBU_WKPR, mask, 0);
}
/**
/*
* sama5d2_piobu_write_value() - writes value & mask at the pin's PIOBU register
*/
static int sama5d2_piobu_write_value(struct gpio_chip *chip, unsigned int pin,
@ -88,7 +88,7 @@ static int sama5d2_piobu_write_value(struct gpio_chip *chip, unsigned int pin,
return regmap_update_bits(piobu->regmap, reg, mask, value);
}
/**
/*
* sama5d2_piobu_read_value() - read the value with masking from the pin's PIOBU
* register
*/
@ -108,7 +108,7 @@ static int sama5d2_piobu_read_value(struct gpio_chip *chip, unsigned int pin,
return val & mask;
}
/**
/*
* sama5d2_piobu_get_direction() - gpiochip get_direction
*/
static int sama5d2_piobu_get_direction(struct gpio_chip *chip,
@ -123,7 +123,7 @@ static int sama5d2_piobu_get_direction(struct gpio_chip *chip,
GPIO_LINE_DIRECTION_OUT;
}
/**
/*
* sama5d2_piobu_direction_input() - gpiochip direction_input
*/
static int sama5d2_piobu_direction_input(struct gpio_chip *chip,
@ -132,7 +132,7 @@ static int sama5d2_piobu_direction_input(struct gpio_chip *chip,
return sama5d2_piobu_write_value(chip, pin, PIOBU_DIRECTION, PIOBU_IN);
}
/**
/*
* sama5d2_piobu_direction_output() - gpiochip direction_output
*/
static int sama5d2_piobu_direction_output(struct gpio_chip *chip,
@ -147,7 +147,7 @@ static int sama5d2_piobu_direction_output(struct gpio_chip *chip,
val);
}
/**
/*
* sama5d2_piobu_get() - gpiochip get
*/
static int sama5d2_piobu_get(struct gpio_chip *chip, unsigned int pin)
@ -166,7 +166,7 @@ static int sama5d2_piobu_get(struct gpio_chip *chip, unsigned int pin)
return !!ret;
}
/**
/*
* sama5d2_piobu_set() - gpiochip set
*/
static void sama5d2_piobu_set(struct gpio_chip *chip, unsigned int pin,

View File

@ -26,10 +26,10 @@ struct sch_gpio {
unsigned short resume_base;
};
static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
unsigned reg)
static unsigned int sch_gpio_offset(struct sch_gpio *sch, unsigned int gpio,
unsigned int reg)
{
unsigned base = 0;
unsigned int base = 0;
if (gpio >= sch->resume_base) {
gpio -= sch->resume_base;
@ -39,14 +39,14 @@ static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
return base + reg + gpio / 8;
}
static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
static unsigned int sch_gpio_bit(struct sch_gpio *sch, unsigned int gpio)
{
if (gpio >= sch->resume_base)
gpio -= sch->resume_base;
return gpio % 8;
}
static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned gpio, unsigned reg)
static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned int gpio, unsigned int reg)
{
unsigned short offset, bit;
u8 reg_val;
@ -59,7 +59,7 @@ static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned gpio, unsigned reg)
return reg_val;
}
static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned gpio, unsigned reg,
static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned int gpio, unsigned int reg,
int val)
{
unsigned short offset, bit;
@ -76,7 +76,7 @@ static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned gpio, unsigned reg,
outb((reg_val & ~BIT(bit)), sch->iobase + offset);
}
static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
@ -86,13 +86,14 @@ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
return 0;
}
static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
return sch_gpio_reg_get(sch, gpio_num, GLV);
}
static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
@ -101,7 +102,7 @@ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
spin_unlock(&sch->lock);
}
static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num,
int val)
{
struct sch_gpio *sch = gpiochip_get_data(gc);
@ -123,7 +124,7 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
return 0;
}
static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num)
static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio_num)
{
struct sch_gpio *sch = gpiochip_get_data(gc);

View File

@ -500,13 +500,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
if (ret)
goto out_free;
ret = gpiochip_add_data(&stmpe_gpio->chip, stmpe_gpio);
if (ret) {
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
goto out_disable;
}
if (irq > 0) {
struct gpio_irq_chip *girq;
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
stmpe_gpio_irq, IRQF_ONESHOT,
"stmpe-gpio", stmpe_gpio);
@ -514,20 +510,22 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
goto out_disable;
}
ret = gpiochip_irqchip_add_nested(&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");
goto out_disable;
}
gpiochip_set_nested_irqchip(&stmpe_gpio->chip,
&stmpe_gpio_irq_chip,
irq);
girq = &stmpe_gpio->chip.irq;
girq->chip = &stmpe_gpio_irq_chip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->threaded = true;
}
ret = gpiochip_add_data(&stmpe_gpio->chip, stmpe_gpio);
if (ret) {
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
goto out_disable;
}
platform_set_drvdata(pdev, stmpe_gpio);

View File

@ -24,16 +24,16 @@
/**
* struct syscon_gpio_data - Configuration for the device.
* compatible: SYSCON driver compatible string.
* flags: Set of GPIO_SYSCON_FEAT_ flags:
* @compatible: SYSCON driver compatible string.
* @flags: Set of GPIO_SYSCON_FEAT_ flags:
* GPIO_SYSCON_FEAT_IN: GPIOs supports input,
* GPIO_SYSCON_FEAT_OUT: GPIOs supports output,
* GPIO_SYSCON_FEAT_DIR: GPIOs supports switch direction.
* bit_count: Number of bits used as GPIOs.
* dat_bit_offset: Offset (in bits) to the first GPIO bit.
* dir_bit_offset: Optional offset (in bits) to the first bit to switch
* @bit_count: Number of bits used as GPIOs.
* @dat_bit_offset: Offset (in bits) to the first GPIO bit.
* @dir_bit_offset: Optional offset (in bits) to the first bit to switch
* GPIO direction (Used with GPIO_SYSCON_FEAT_DIR flag).
* set: HW specific callback to assigns output value
* @set: HW specific callback to assigns output value
* for signal "offset"
*/

View File

@ -289,6 +289,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
struct device_node *np = pdev->dev.of_node;
struct tc3589x_gpio *tc3589x_gpio;
struct gpio_irq_chip *girq;
int ret;
int irq;
@ -317,6 +318,16 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
tc3589x_gpio->chip.base = -1;
tc3589x_gpio->chip.of_node = np;
girq = &tc3589x_gpio->chip.irq;
girq->chip = &tc3589x_gpio_irq_chip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->threaded = true;
/* Bring the GPIO module out of reset */
ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
TC3589x_RSTCTRL_GPIRST, 0);
@ -339,21 +350,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
return ret;
}
ret = gpiochip_irqchip_add_nested(&tc3589x_gpio->chip,
&tc3589x_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;
}
gpiochip_set_nested_irqchip(&tc3589x_gpio->chip,
&tc3589x_gpio_irq_chip,
irq);
platform_set_drvdata(pdev, tc3589x_gpio);
return 0;

View File

@ -400,6 +400,7 @@ static int wcove_gpio_probe(struct platform_device *pdev)
struct wcove_gpio *wg;
int virq, ret, irq;
struct device *dev;
struct gpio_irq_chip *girq;
/*
* This gpio platform device is created by a mfd device (see
@ -442,33 +443,34 @@ static int wcove_gpio_probe(struct platform_device *pdev)
wg->dev = dev;
wg->regmap = pmic->regmap;
ret = devm_gpiochip_add_data(dev, &wg->chip, wg);
if (ret) {
dev_err(dev, "Failed to add gpiochip: %d\n", ret);
return ret;
}
ret = gpiochip_irqchip_add_nested(&wg->chip, &wcove_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "Failed to add irqchip: %d\n", ret);
return ret;
}
virq = regmap_irq_get_virq(wg->regmap_irq_chip, irq);
if (virq < 0) {
dev_err(dev, "Failed to get virq by irq %d\n", irq);
return virq;
}
ret = devm_request_threaded_irq(dev, virq, NULL,
wcove_gpio_irq_handler, IRQF_ONESHOT, pdev->name, wg);
girq = &wg->chip.irq;
girq->chip = &wcove_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
girq->threaded = true;
ret = devm_request_threaded_irq(dev, virq, NULL, wcove_gpio_irq_handler,
IRQF_ONESHOT, pdev->name, wg);
if (ret) {
dev_err(dev, "Failed to request irq %d\n", virq);
return ret;
}
gpiochip_set_nested_irqchip(&wg->chip, &wcove_irqchip, virq);
ret = devm_gpiochip_add_data(dev, &wg->chip, wg);
if (ret) {
dev_err(dev, "Failed to add gpiochip: %d\n", ret);
return ret;
}
/* Enable GPIO0 interrupts */
ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE, GPIO_IRQ0_MASK,

View File

@ -365,10 +365,25 @@ static const char *ws16c48_names[WS16C48_NGPIO] = {
"Port 5 Bit 4", "Port 5 Bit 5", "Port 5 Bit 6", "Port 5 Bit 7"
};
static int ws16c48_irq_init_hw(struct gpio_chip *gc)
{
struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(gc);
/* Disable IRQ by default */
outb(0x80, ws16c48gpio->base + 7);
outb(0, ws16c48gpio->base + 8);
outb(0, ws16c48gpio->base + 9);
outb(0, ws16c48gpio->base + 10);
outb(0xC0, ws16c48gpio->base + 7);
return 0;
}
static int ws16c48_probe(struct device *dev, unsigned int id)
{
struct ws16c48_gpio *ws16c48gpio;
const char *const name = dev_name(dev);
struct gpio_irq_chip *girq;
int err;
ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL);
@ -396,6 +411,16 @@ static int ws16c48_probe(struct device *dev, unsigned int id)
ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple;
ws16c48gpio->base = base[id];
girq = &ws16c48gpio->chip.irq;
girq->chip = &ws16c48_irqchip;
/* This will let us handle the parent IRQ in the driver */
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
girq->init_hw = ws16c48_irq_init_hw;
raw_spin_lock_init(&ws16c48gpio->lock);
err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio);
@ -404,20 +429,6 @@ static int ws16c48_probe(struct device *dev, unsigned int id)
return err;
}
/* Disable IRQ by default */
outb(0x80, base[id] + 7);
outb(0, base[id] + 8);
outb(0, base[id] + 9);
outb(0, base[id] + 10);
outb(0xC0, base[id] + 7);
err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
return err;
}
err = devm_request_irq(dev, irq[id], ws16c48_irq_handler, IRQF_SHARED,
name, ws16c48gpio);
if (err) {

View File

@ -121,6 +121,7 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
struct xra1403 *xra = gpiochip_get_data(chip);
int value[XRA_LAST];
int i;
const char *label;
unsigned int gcr;
unsigned int gsr;
@ -136,12 +137,7 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
gcr = value[XRA_GCR + 1] << 8 | value[XRA_GCR];
gsr = value[XRA_GSR + 1] << 8 | value[XRA_GSR];
for (i = 0; i < chip->ngpio; i++) {
const char *label = gpiochip_is_requested(chip, i);
if (!label)
continue;
for_each_requested_gpio(chip, i, label) {
seq_printf(s, " gpio-%-3d (%-12s) %s %s\n",
chip->base + i, label,
(gcr & BIT(i)) ? "in" : "out",

View File

@ -10,6 +10,7 @@
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@ -21,6 +22,9 @@
/* Maximum banks */
#define ZYNQ_GPIO_MAX_BANK 4
#define ZYNQMP_GPIO_MAX_BANK 6
#define VERSAL_GPIO_MAX_BANK 4
#define PMC_GPIO_MAX_BANK 5
#define VERSAL_UNUSED_BANKS 2
#define ZYNQ_GPIO_BANK0_NGPIO 32
#define ZYNQ_GPIO_BANK1_NGPIO 22
@ -95,6 +99,7 @@
/* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
#define ZYNQ_GPIO_QUIRK_IS_ZYNQ BIT(0)
#define GPIO_QUIRK_DATA_RO_BUG BIT(1)
#define GPIO_QUIRK_VERSAL BIT(2)
struct gpio_regs {
u32 datamsw[ZYNQMP_GPIO_MAX_BANK];
@ -116,6 +121,7 @@ struct gpio_regs {
* @irq: interrupt for the GPIO device
* @p_data: pointer to platform data
* @context: context registers
* @dirlock: lock used for direction in/out synchronization
*/
struct zynq_gpio {
struct gpio_chip chip;
@ -124,6 +130,7 @@ struct zynq_gpio {
int irq;
const struct zynq_platform_data *p_data;
struct gpio_regs context;
spinlock_t dirlock; /* lock */
};
/**
@ -196,6 +203,8 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
gpio->p_data->bank_min[bank];
return;
}
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
bank = bank + VERSAL_UNUSED_BANKS;
}
/* default */
@ -297,6 +306,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
{
u32 reg;
unsigned int bank_num, bank_pin_num;
unsigned long flags;
struct zynq_gpio *gpio = gpiochip_get_data(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@ -310,9 +320,11 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
return -EINVAL;
/* clear the bit in direction mode reg to set the pin as input */
spin_lock_irqsave(&gpio->dirlock, flags);
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));
spin_unlock_irqrestore(&gpio->dirlock, flags);
return 0;
}
@ -334,11 +346,13 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
{
u32 reg;
unsigned int bank_num, bank_pin_num;
unsigned long flags;
struct zynq_gpio *gpio = gpiochip_get_data(chip);
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
/* set the GPIO pin as output */
spin_lock_irqsave(&gpio->dirlock, flags);
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));
@ -347,6 +361,7 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int 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));
spin_unlock_irqrestore(&gpio->dirlock, flags);
/* set the state of the pin */
zynq_gpio_set_value(chip, pin, state);
@ -647,6 +662,8 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc)
int_enb = readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb);
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
bank_num = bank_num + VERSAL_UNUSED_BANKS;
}
chained_irq_exit(irqchip, desc);
@ -676,6 +693,8 @@ static void zynq_gpio_save_context(struct zynq_gpio *gpio)
gpio->context.int_any[bank_num] =
readl_relaxed(gpio->base_addr +
ZYNQ_GPIO_INTANY_OFFSET(bank_num));
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
bank_num = bank_num + VERSAL_UNUSED_BANKS;
}
}
@ -707,6 +726,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
writel_relaxed(~(gpio->context.int_en[bank_num]),
gpio->base_addr +
ZYNQ_GPIO_INTEN_OFFSET(bank_num));
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
bank_num = bank_num + VERSAL_UNUSED_BANKS;
}
}
@ -715,6 +736,9 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev)
struct zynq_gpio *gpio = dev_get_drvdata(dev);
struct irq_data *data = irq_get_irq_data(gpio->irq);
if (!device_may_wakeup(dev))
disable_irq(gpio->irq);
if (!irqd_is_wakeup_set(data)) {
zynq_gpio_save_context(gpio);
return pm_runtime_force_suspend(dev);
@ -729,6 +753,9 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev)
struct irq_data *data = irq_get_irq_data(gpio->irq);
int ret;
if (!device_may_wakeup(dev))
enable_irq(gpio->irq);
if (!irqd_is_wakeup_set(data)) {
ret = pm_runtime_force_resume(dev);
zynq_gpio_restore_context(gpio);
@ -778,6 +805,31 @@ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
zynq_gpio_runtime_resume, NULL)
};
static const struct zynq_platform_data versal_gpio_def = {
.label = "versal_gpio",
.quirks = GPIO_QUIRK_VERSAL,
.ngpio = 58,
.max_bank = VERSAL_GPIO_MAX_BANK,
.bank_min[0] = 0,
.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
.bank_min[3] = 26,
.bank_max[3] = 57, /* Bank 3 is connected to FMIOs (32 pins) */
};
static const struct zynq_platform_data pmc_gpio_def = {
.label = "pmc_gpio",
.ngpio = 116,
.max_bank = PMC_GPIO_MAX_BANK,
.bank_min[0] = 0,
.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
.bank_min[1] = 26,
.bank_max[1] = 51, /* Bank 1 are connected to MIOs (26 pins) */
.bank_min[3] = 52,
.bank_max[3] = 83, /* Bank 3 is connected to EMIOs (32 pins) */
.bank_min[4] = 84,
.bank_max[4] = 115, /* Bank 4 is connected to EMIOs (32 pins) */
};
static const struct zynq_platform_data zynqmp_gpio_def = {
.label = "zynqmp_gpio",
.quirks = GPIO_QUIRK_DATA_RO_BUG,
@ -815,6 +867,8 @@ static const struct zynq_platform_data zynq_gpio_def = {
static const struct of_device_id zynq_gpio_of_match[] = {
{ .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def },
{ .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def },
{ .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def },
{ .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def },
{ /* end of table */ }
};
MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
@ -876,7 +930,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
/* Retrieve GPIO clock */
gpio->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(gpio->clk)) {
dev_err(&pdev->dev, "input clock not found.\n");
if (PTR_ERR(gpio->clk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "input clock not found.\n");
return PTR_ERR(gpio->clk);
}
ret = clk_prepare_enable(gpio->clk);
@ -885,6 +940,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
return ret;
}
spin_lock_init(&gpio->dirlock);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_get_sync(&pdev->dev);
@ -892,9 +949,12 @@ static int zynq_gpio_probe(struct platform_device *pdev)
goto err_pm_dis;
/* disable interrupts for all banks */
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
bank_num = bank_num + VERSAL_UNUSED_BANKS;
}
/* Set up the GPIO irqchip */
girq = &chip->irq;
@ -919,6 +979,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
goto err_pm_put;
}
irq_set_status_flags(gpio->irq, IRQ_DISABLE_UNLAZY);
device_init_wakeup(&pdev->dev, 1);
pm_runtime_put(&pdev->dev);
return 0;

1121
drivers/gpio/gpiolib-cdev.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef GPIOLIB_CDEV_H
#define GPIOLIB_CDEV_H
#include <linux/device.h>
int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt);
void gpiolib_cdev_unregister(struct gpio_device *gdev);
#endif /* GPIOLIB_CDEV_H */

View File

@ -487,10 +487,12 @@ static void devm_gpio_chip_release(struct device *dev, void *res)
}
/**
* devm_gpiochip_add_data() - Resource managed gpiochip_add_data()
* devm_gpiochip_add_data_with_key() - Resource managed gpiochip_add_data_with_key()
* @dev: pointer to the device that gpio_chip belongs to.
* @gc: the GPIO chip to register
* @data: driver-private data associated with this chip
* @lock_key: lockdep class for IRQ lock
* @request_key: lockdep class for IRQ request
*
* Context: potentially before irqs will work
*
@ -501,8 +503,9 @@ static void devm_gpio_chip_release(struct device *dev, void *res)
* gc->base is invalid or already associated with a different chip.
* Otherwise it returns zero as a success code.
*/
int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc,
void *data)
int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data,
struct lock_class_key *lock_key,
struct lock_class_key *request_key)
{
struct gpio_chip **ptr;
int ret;
@ -512,7 +515,7 @@ int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc,
if (!ptr)
return -ENOMEM;
ret = gpiochip_add_data(gc, data);
ret = gpiochip_add_data_with_key(gc, data, lock_key, request_key);
if (ret < 0) {
devres_free(ptr);
return ret;
@ -523,4 +526,4 @@ int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc,
return 0;
}
EXPORT_SYMBOL_GPL(devm_gpiochip_add_data);
EXPORT_SYMBOL_GPL(devm_gpiochip_add_data_with_key);

View File

@ -25,6 +25,9 @@
/**
* of_gpio_spi_cs_get_count() - special GPIO counting for SPI
* @dev: Consuming device
* @con_id: Function within the GPIO consumer
*
* Some elder GPIO controllers need special quirks. Currently we handle
* the Freescale and PPC GPIO controller with bindings that doesn't use the
* established "cs-gpios" for chip selects but instead rely on

View File

@ -11,6 +11,7 @@
#include <linux/ctype.h>
#include "gpiolib.h"
#include "gpiolib-sysfs.h"
#define GPIO_IRQF_TRIGGER_FALLING BIT(0)
#define GPIO_IRQF_TRIGGER_RISING BIT(1)
@ -365,7 +366,7 @@ static DEVICE_ATTR_RW(active_low);
static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc;
umode_t mode = attr->mode;

View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef GPIOLIB_SYSFS_H
#define GPIOLIB_SYSFS_H
#ifdef CONFIG_GPIO_SYSFS
int gpiochip_sysfs_register(struct gpio_device *gdev);
void gpiochip_sysfs_unregister(struct gpio_device *gdev);
#else
static inline int gpiochip_sysfs_register(struct gpio_device *gdev)
{
return 0;
}
static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev)
{
}
#endif /* CONFIG_GPIO_SYSFS */
#endif /* GPIOLIB_SYSFS_H */

File diff suppressed because it is too large Load Diff

View File

@ -56,7 +56,7 @@ struct gpio_device {
const char *label;
void *data;
struct list_head list;
struct atomic_notifier_head notifier;
struct blocking_notifier_head notifier;
#ifdef CONFIG_PINCTRL
/*
@ -175,22 +175,4 @@ static inline int gpio_chip_hwgpio(const struct gpio_desc *desc)
#define chip_dbg(gc, fmt, ...) \
dev_dbg(&gc->gpiodev->dev, "(%s): " fmt, gc->label, ##__VA_ARGS__)
#ifdef CONFIG_GPIO_SYSFS
int gpiochip_sysfs_register(struct gpio_device *gdev);
void gpiochip_sysfs_unregister(struct gpio_device *gdev);
#else
static inline int gpiochip_sysfs_register(struct gpio_device *gdev)
{
return 0;
}
static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev)
{
}
#endif /* CONFIG_GPIO_SYSFS */
#endif /* GPIOLIB_H */

View File

@ -1486,14 +1486,11 @@ static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
int i;
struct at91_gpio_chip *at91_gpio = gpiochip_get_data(chip);
void __iomem *pio = at91_gpio->regbase;
const char *gpio_label;
for (i = 0; i < chip->ngpio; i++) {
for_each_requested_gpio(chip, i, gpio_label) {
unsigned mask = pin_to_mask(i);
const char *gpio_label;
gpio_label = gpiochip_is_requested(chip, i);
if (!gpio_label)
continue;
mode = at91_gpio->ops->get_periph(pio, mask);
seq_printf(s, "[%s] GPIO%s%d: ",
gpio_label, chip->label, i);

View File

@ -474,6 +474,22 @@ struct gpio_chip {
extern const char *gpiochip_is_requested(struct gpio_chip *gc,
unsigned int offset);
/**
* for_each_requested_gpio_in_range - iterates over requested GPIOs in a given range
* @chip: the chip to query
* @i: loop variable
* @base: first GPIO in the range
* @size: amount of GPIOs to check starting from @base
* @label: label of current GPIO
*/
#define for_each_requested_gpio_in_range(chip, i, base, size, label) \
for (i = 0; i < size; i++) \
if ((label = gpiochip_is_requested(chip, base + i)) == NULL) {} else
/* Iterates over all requested GPIO of the given @chip */
#define for_each_requested_gpio(chip, i, label) \
for_each_requested_gpio_in_range(chip, i, 0, chip->ngpio, label)
/* add/remove chips */
extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct lock_class_key *lock_key,
@ -481,25 +497,25 @@ extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
/**
* gpiochip_add_data() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
* @gc: the chip to register, with gc->base initialized
* @data: driver-private data associated with this chip
*
* Context: potentially before irqs will work
*
* When gpiochip_add_data() is called very early during boot, so that GPIOs
* can be freely used, the chip->parent device must be registered before
* can be freely used, the gc->parent device must be registered before
* the gpio framework's arch_initcall(). Otherwise sysfs initialization
* for GPIOs will fail rudely.
*
* gpiochip_add_data() must only be called after gpiolib initialization,
* ie after core_initcall().
*
* If chip->base is negative, this requests dynamic assignment of
* If gc->base is negative, this requests dynamic assignment of
* a range of valid GPIOs.
*
* Returns:
* A negative errno if the chip can't be registered, such as because the
* chip->base is invalid or already associated with a different chip.
* gc->base is invalid or already associated with a different chip.
* Otherwise it returns zero as a success code.
*/
#ifdef CONFIG_LOCKDEP
@ -509,8 +525,16 @@ extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
gpiochip_add_data_with_key(gc, data, &lock_key, \
&request_key); \
})
#define devm_gpiochip_add_data(dev, gc, data) ({ \
static struct lock_class_key lock_key; \
static struct lock_class_key request_key; \
devm_gpiochip_add_data_with_key(dev, gc, data, &lock_key, \
&request_key); \
})
#else
#define gpiochip_add_data(gc, data) gpiochip_add_data_with_key(gc, data, NULL, NULL)
#define devm_gpiochip_add_data(dev, gc, data) \
devm_gpiochip_add_data_with_key(dev, gc, data, NULL, NULL)
#endif /* CONFIG_LOCKDEP */
static inline int gpiochip_add(struct gpio_chip *gc)
@ -518,8 +542,9 @@ static inline int gpiochip_add(struct gpio_chip *gc)
return gpiochip_add_data(gc, NULL);
}
extern void gpiochip_remove(struct gpio_chip *gc);
extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *gc,
void *data);
extern int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data,
struct lock_class_key *lock_key,
struct lock_class_key *request_key);
extern struct gpio_chip *gpiochip_find(void *data,
int (*match)(struct gpio_chip *gc, void *data));

View File

@ -8,7 +8,7 @@ struct gpio_regmap;
struct irq_domain;
struct regmap;
#define GPIO_REGMAP_ADDR_ZERO ((unsigned long)(-1))
#define GPIO_REGMAP_ADDR_ZERO ((unsigned int)(-1))
#define GPIO_REGMAP_ADDR(addr) ((addr) ? : GPIO_REGMAP_ADDR_ZERO)
/**

View File

@ -71,8 +71,8 @@ enum {
* of a GPIO line
* @info: updated line information
* @timestamp: estimate of time of status change occurrence, in nanoseconds
* and GPIOLINE_CHANGED_CONFIG
* @event_type: one of GPIOLINE_CHANGED_REQUESTED, GPIOLINE_CHANGED_RELEASED
* and GPIOLINE_CHANGED_CONFIG
*
* Note: struct gpioline_info embedded here has 32-bit alignment on its own,
* but it works fine with 64-bit alignment too. With its 72 byte size, we can

View File

@ -45,7 +45,7 @@ int monitor_device(const char *device_name,
if (fd == -1) {
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
goto exit_close_error;
goto exit_free_name;
}
req.lineoffset = line;
@ -117,6 +117,7 @@ int monitor_device(const char *device_name,
exit_close_error:
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
exit_free_name:
free(chrdev_name);
return ret;
}

View File

@ -75,7 +75,7 @@ int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
ret = -errno;
fprintf(stderr, "Failed to open %s, %s\n",
chrdev_name, strerror(errno));
goto exit_close_error;
goto exit_free_name;
}
for (i = 0; i < nlines; i++)
@ -94,9 +94,9 @@ int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
"GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
}
exit_close_error:
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
exit_free_name:
free(chrdev_name);
return ret < 0 ? ret : req.fd;
}

View File

@ -94,7 +94,7 @@ int list_device(const char *device_name)
if (fd == -1) {
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
goto exit_close_error;
goto exit_free_name;
}
/* Inspect this GPIO chip */
@ -141,6 +141,7 @@ int list_device(const char *device_name)
exit_close_error:
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
exit_free_name:
free(chrdev_name);
return ret;
}