summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig29
-rw-r--r--drivers/gpio/Makefile3
-rw-r--r--drivers/gpio/devres.c32
-rw-r--r--drivers/gpio/gpio-104-dio-48e.c91
-rw-r--r--drivers/gpio/gpio-104-idi-48.c45
-rw-r--r--drivers/gpio/gpio-104-idio-16.c60
-rw-r--r--drivers/gpio/gpio-davinci.c177
-rw-r--r--drivers/gpio/gpio-exar.c200
-rw-r--r--drivers/gpio/gpio-gemini.c236
-rw-r--r--drivers/gpio/gpio-gpio-mm.c68
-rw-r--r--drivers/gpio/gpio-intel-mid.c2
-rw-r--r--drivers/gpio/gpio-mcp23s08.c320
-rw-r--r--drivers/gpio/gpio-mm-lantiq.c2
-rw-r--r--drivers/gpio/gpio-mockup.c377
-rw-r--r--drivers/gpio/gpio-mvebu.c2
-rw-r--r--drivers/gpio/gpio-pca953x.c9
-rw-r--r--drivers/gpio/gpio-pci-idio-16.c349
-rw-r--r--drivers/gpio/gpio-rcar.c21
-rw-r--r--drivers/gpio/gpio-stp-xway.c2
-rw-r--r--drivers/gpio/gpio-ws16c48.c90
-rw-r--r--drivers/gpio/gpiolib-acpi.c5
-rw-r--r--drivers/gpio/gpiolib-of.c31
-rw-r--r--drivers/gpio/gpiolib.c55
-rw-r--r--drivers/gpio/gpiolib.h3
24 files changed, 1671 insertions, 538 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d5d36549ecc1..05043071fc98 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -185,6 +185,13 @@ config GPIO_ETRAXFS
help
Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
+config GPIO_EXAR
+ tristate "Support for GPIO pins on XR17V352/354/358"
+ depends on SERIAL_8250_EXAR
+ help
+ Selecting this option will enable handling of GPIO pins present
+ on Exar XR17V352/354/358 chips.
+
config GPIO_GE_FPGA
bool "GE FPGA based GPIO"
depends on GE_FPGA
@@ -197,6 +204,15 @@ config GPIO_GE_FPGA
and write pin state) for GPIO implemented in a number of GE single
board computers.
+config GPIO_GEMINI
+ bool "Gemini GPIO"
+ depends on ARCH_GEMINI
+ depends on OF_GPIO
+ select GPIO_GENERIC
+ select GPIOLIB_IRQCHIP
+ help
+ Support for common GPIOs found in Cortina systems Gemini platforms.
+
config GPIO_GENERIC_PLATFORM
tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
select GPIO_GENERIC
@@ -282,6 +298,8 @@ config GPIO_MOCKUP
tristate "GPIO Testing Driver"
depends on GPIOLIB && SYSFS
select GPIO_SYSFS
+ select GPIOLIB_IRQCHIP
+ select IRQ_WORK
help
This enables GPIO Testing driver, which provides a way to test GPIO
subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS
@@ -1141,6 +1159,15 @@ config GPIO_PCH
ML7223/ML7831 is companion chip for Intel Atom E6xx series.
ML7223/ML7831 is completely compatible for Intel EG20T PCH.
+config GPIO_PCI_IDIO_16
+ tristate "ACCES PCI-IDIO-16 GPIO support"
+ select GPIOLIB_IRQCHIP
+ help
+ Enables GPIO support for the ACCES PCI-IDIO-16. An interrupt is
+ generated when any of the inputs change state (low to high or high to
+ low). Input filter control is not supported by this driver, and the
+ input filters are deactivated by this driver.
+
config GPIO_RDC321X
tristate "RDC R-321x GPIO support"
select MFD_CORE
@@ -1197,6 +1224,8 @@ config GPIO_MCP23S08
tristate "Microchip MCP23xxx I/O expander"
depends on OF_GPIO
select GPIOLIB_IRQCHIP
+ select REGMAP_I2C if I2C
+ select REGMAP if SPI_MASTER
help
SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
I/O expanders.
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a7676b82de6f..becb96c724fe 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -46,8 +46,10 @@ obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o
+obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
+obj-$(CONFIG_GPIO_GEMINI) += gpio-gemini.o
obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
@@ -90,6 +92,7 @@ obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
+obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o
obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index b760cbbb41d8..7031eea165c9 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -11,7 +11,7 @@
*
* This file is based on kernel/irq/devres.c
*
- * Copyright (c) 2011 John Crispin <blogic@openwrt.org>
+ * Copyright (c) 2011 John Crispin <john@phrozen.org>
*/
#include <linux/module.h>
@@ -21,6 +21,8 @@
#include <linux/device.h>
#include <linux/gfp.h>
+#include "gpiolib.h"
+
static void devm_gpiod_release(struct device *dev, void *res)
{
struct gpio_desc **desc = res;
@@ -123,19 +125,26 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
EXPORT_SYMBOL(devm_gpiod_get_index);
/**
- * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
+ * devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
+ * device's child node
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
+ * @index: index of the GPIO to obtain in the consumer
* @child: firmware node (child of @dev)
+ * @flags: GPIO initialization flags
*
* GPIO descriptors returned from this function are automatically disposed on
* driver detach.
+ *
+ * On successfull request the GPIO pin is configured in accordance with
+ * provided @flags.
*/
-struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
- const char *con_id,
- struct fwnode_handle *child)
+struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
+ const char *con_id, int index,
+ struct fwnode_handle *child,
+ enum gpiod_flags flags,
+ const char *label)
{
- static const char * const suffixes[] = { "gpios", "gpio" };
char prop_name[32]; /* 32 is max size of property name */
struct gpio_desc **dr;
struct gpio_desc *desc;
@@ -146,15 +155,16 @@ struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
if (!dr)
return ERR_PTR(-ENOMEM);
- for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
+ for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s",
- con_id, suffixes[i]);
+ con_id, gpio_suffixes[i]);
else
snprintf(prop_name, sizeof(prop_name), "%s",
- suffixes[i]);
+ gpio_suffixes[i]);
- desc = fwnode_get_named_gpiod(child, prop_name);
+ desc = fwnode_get_named_gpiod(child, prop_name, index, flags,
+ label);
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
break;
}
@@ -168,7 +178,7 @@ struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
return desc;
}
-EXPORT_SYMBOL(devm_get_gpiod_from_child);
+EXPORT_SYMBOL(devm_fwnode_get_index_gpiod_from_child);
/**
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index fcf776971ca9..17bd2ab4ebe2 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -48,7 +48,6 @@ MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");
* @control: Control registers state
* @lock: synchronization lock to prevent I/O race conditions
* @base: base port address of the GPIO device
- * @irq: Interrupt line number
* @irq_mask: I/O bits affected by interrupts
*/
struct dio48e_gpio {
@@ -58,7 +57,6 @@ struct dio48e_gpio {
unsigned char control[2];
spinlock_t lock;
unsigned base;
- unsigned irq;
unsigned char irq_mask;
};
@@ -204,6 +202,44 @@ static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_unlock_irqrestore(&dio48egpio->lock, flags);
}
+static void dio48e_gpio_set_multiple(struct gpio_chip *chip,
+ unsigned long *mask, unsigned long *bits)
+{
+ struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
+ unsigned int i;
+ const unsigned int gpio_reg_size = 8;
+ unsigned int port;
+ unsigned int out_port;
+ unsigned int bitmask;
+ unsigned long flags;
+
+ /* set bits are evaluated a gpio register size at a time */
+ for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
+ /* no more set bits in this mask word; skip to the next word */
+ if (!mask[BIT_WORD(i)]) {
+ i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
+ continue;
+ }
+
+ port = i / gpio_reg_size;
+ out_port = (port > 2) ? port + 1 : port;
+ bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
+
+ spin_lock_irqsave(&dio48egpio->lock, flags);
+
+ /* update output state data and set device gpio register */
+ dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)];
+ dio48egpio->out_state[port] |= bitmask;
+ outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
+
+ spin_unlock_irqrestore(&dio48egpio->lock, flags);
+
+ /* prepare for next gpio register set */
+ mask[BIT_WORD(i)] >>= gpio_reg_size;
+ bits[BIT_WORD(i)] >>= gpio_reg_size;
+ }
+}
+
static void dio48e_irq_ack(struct irq_data *data)
{
}
@@ -302,6 +338,26 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#define DIO48E_NGPIO 48
+static const char *dio48e_names[DIO48E_NGPIO] = {
+ "PPI Group 0 Port A 0", "PPI Group 0 Port A 1", "PPI Group 0 Port A 2",
+ "PPI Group 0 Port A 3", "PPI Group 0 Port A 4", "PPI Group 0 Port A 5",
+ "PPI Group 0 Port A 6", "PPI Group 0 Port A 7", "PPI Group 0 Port B 0",
+ "PPI Group 0 Port B 1", "PPI Group 0 Port B 2", "PPI Group 0 Port B 3",
+ "PPI Group 0 Port B 4", "PPI Group 0 Port B 5", "PPI Group 0 Port B 6",
+ "PPI Group 0 Port B 7", "PPI Group 0 Port C 0", "PPI Group 0 Port C 1",
+ "PPI Group 0 Port C 2", "PPI Group 0 Port C 3", "PPI Group 0 Port C 4",
+ "PPI Group 0 Port C 5", "PPI Group 0 Port C 6", "PPI Group 0 Port C 7",
+ "PPI Group 1 Port A 0", "PPI Group 1 Port A 1", "PPI Group 1 Port A 2",
+ "PPI Group 1 Port A 3", "PPI Group 1 Port A 4", "PPI Group 1 Port A 5",
+ "PPI Group 1 Port A 6", "PPI Group 1 Port A 7", "PPI Group 1 Port B 0",
+ "PPI Group 1 Port B 1", "PPI Group 1 Port B 2", "PPI Group 1 Port B 3",
+ "PPI Group 1 Port B 4", "PPI Group 1 Port B 5", "PPI Group 1 Port B 6",
+ "PPI Group 1 Port B 7", "PPI Group 1 Port C 0", "PPI Group 1 Port C 1",
+ "PPI Group 1 Port C 2", "PPI Group 1 Port C 3", "PPI Group 1 Port C 4",
+ "PPI Group 1 Port C 5", "PPI Group 1 Port C 6", "PPI Group 1 Port C 7"
+};
+
static int dio48e_probe(struct device *dev, unsigned int id)
{
struct dio48e_gpio *dio48egpio;
@@ -322,20 +378,19 @@ static int dio48e_probe(struct device *dev, unsigned int id)
dio48egpio->chip.parent = dev;
dio48egpio->chip.owner = THIS_MODULE;
dio48egpio->chip.base = -1;
- dio48egpio->chip.ngpio = 48;
+ dio48egpio->chip.ngpio = DIO48E_NGPIO;
+ dio48egpio->chip.names = dio48e_names;
dio48egpio->chip.get_direction = dio48e_gpio_get_direction;
dio48egpio->chip.direction_input = dio48e_gpio_direction_input;
dio48egpio->chip.direction_output = dio48e_gpio_direction_output;
dio48egpio->chip.get = dio48e_gpio_get;
dio48egpio->chip.set = dio48e_gpio_set;
+ dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple;
dio48egpio->base = base[id];
- dio48egpio->irq = irq[id];
spin_lock_init(&dio48egpio->lock);
- dev_set_drvdata(dev, dio48egpio);
-
- err = gpiochip_add_data(&dio48egpio->chip, dio48egpio);
+ err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
@@ -360,30 +415,17 @@ static int dio48e_probe(struct device *dev, unsigned int id)
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
- goto err_gpiochip_remove;
+ return err;
}
- err = request_irq(irq[id], dio48e_irq_handler, 0, name, dio48egpio);
+ err = devm_request_irq(dev, irq[id], dio48e_irq_handler, 0, name,
+ dio48egpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
- goto err_gpiochip_remove;
+ return err;
}
return 0;
-
-err_gpiochip_remove:
- gpiochip_remove(&dio48egpio->chip);
- return err;
-}
-
-static int dio48e_remove(struct device *dev, unsigned int id)
-{
- struct dio48e_gpio *const dio48egpio = dev_get_drvdata(dev);
-
- free_irq(dio48egpio->irq, dio48egpio);
- gpiochip_remove(&dio48egpio->chip);
-
- return 0;
}
static struct isa_driver dio48e_driver = {
@@ -391,7 +433,6 @@ static struct isa_driver dio48e_driver = {
.driver = {
.name = "104-dio-48e"
},
- .remove = dio48e_remove
};
module_isa_driver(dio48e_driver, num_dio48e);
diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index 2d2763ea1a68..568375a7ebc2 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -47,7 +47,6 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
* @ack_lock: synchronization lock to prevent IRQ handler race conditions
* @irq_mask: input bits affected by interrupts
* @base: base port address of the GPIO device
- * @irq: Interrupt line number
* @cos_enb: Change-Of-State IRQ enable boundaries mask
*/
struct idi_48_gpio {
@@ -56,7 +55,6 @@ struct idi_48_gpio {
spinlock_t ack_lock;
unsigned char irq_mask[6];
unsigned base;
- unsigned irq;
unsigned char cos_enb;
};
@@ -219,6 +217,18 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#define IDI48_NGPIO 48
+static const char *idi48_names[IDI48_NGPIO] = {
+ "Bit 0 A", "Bit 1 A", "Bit 2 A", "Bit 3 A", "Bit 4 A", "Bit 5 A",
+ "Bit 6 A", "Bit 7 A", "Bit 8 A", "Bit 9 A", "Bit 10 A", "Bit 11 A",
+ "Bit 12 A", "Bit 13 A", "Bit 14 A", "Bit 15 A", "Bit 16 A", "Bit 17 A",
+ "Bit 18 A", "Bit 19 A", "Bit 20 A", "Bit 21 A", "Bit 22 A", "Bit 23 A",
+ "Bit 0 B", "Bit 1 B", "Bit 2 B", "Bit 3 B", "Bit 4 B", "Bit 5 B",
+ "Bit 6 B", "Bit 7 B", "Bit 8 B", "Bit 9 B", "Bit 10 B", "Bit 11 B",
+ "Bit 12 B", "Bit 13 B", "Bit 14 B", "Bit 15 B", "Bit 16 B", "Bit 17 B",
+ "Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B"
+};
+
static int idi_48_probe(struct device *dev, unsigned int id)
{
struct idi_48_gpio *idi48gpio;
@@ -239,19 +249,17 @@ static int idi_48_probe(struct device *dev, unsigned int id)
idi48gpio->chip.parent = dev;
idi48gpio->chip.owner = THIS_MODULE;
idi48gpio->chip.base = -1;
- idi48gpio->chip.ngpio = 48;
+ idi48gpio->chip.ngpio = IDI48_NGPIO;
+ idi48gpio->chip.names = idi48_names;
idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
idi48gpio->chip.get = idi_48_gpio_get;
idi48gpio->base = base[id];
- idi48gpio->irq = irq[id];
spin_lock_init(&idi48gpio->lock);
spin_lock_init(&idi48gpio->ack_lock);
- dev_set_drvdata(dev, idi48gpio);
-
- err = gpiochip_add_data(&idi48gpio->chip, idi48gpio);
+ err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
@@ -265,31 +273,17 @@ static int idi_48_probe(struct device *dev, unsigned int id)
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
- goto err_gpiochip_remove;
+ return err;
}
- err = request_irq(irq[id], idi_48_irq_handler, IRQF_SHARED, name,
- idi48gpio);
+ err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED,
+ name, idi48gpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
- goto err_gpiochip_remove;
+ return err;
}
return 0;
-
-err_gpiochip_remove:
- gpiochip_remove(&idi48gpio->chip);
- return err;
-}
-
-static int idi_48_remove(struct device *dev, unsigned int id)
-{
- struct idi_48_gpio *const idi48gpio = dev_get_drvdata(dev);
-
- free_irq(idi48gpio->irq, idi48gpio);
- gpiochip_remove(&idi48gpio->chip);
-
- return 0;
}
static struct isa_driver idi_48_driver = {
@@ -297,7 +291,6 @@ static struct isa_driver idi_48_driver = {
.driver = {
.name = "104-idi-48"
},
- .remove = idi_48_remove
};
module_isa_driver(idi_48_driver, num_idi_48);
diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c
index 6787b8fcf0d8..7053cf736648 100644
--- a/drivers/gpio/gpio-104-idio-16.c
+++ b/drivers/gpio/gpio-104-idio-16.c
@@ -46,7 +46,6 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
* @lock: synchronization lock to prevent I/O race conditions
* @irq_mask: I/O bits affected by interrupts
* @base: base port address of the GPIO device
- * @irq: Interrupt line number
* @out_state: output bits state
*/
struct idio_16_gpio {
@@ -54,7 +53,6 @@ struct idio_16_gpio {
spinlock_t lock;
unsigned long irq_mask;
unsigned base;
- unsigned irq;
unsigned out_state;
};
@@ -116,6 +114,25 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_unlock_irqrestore(&idio16gpio->lock, flags);
}
+static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
+ unsigned long *mask, unsigned long *bits)
+{
+ struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
+ unsigned long flags;
+
+ spin_lock_irqsave(&idio16gpio->lock, flags);
+
+ idio16gpio->out_state &= ~*mask;
+ idio16gpio->out_state |= *mask & *bits;
+
+ if (*mask & 0xFF)
+ outb(idio16gpio->out_state, idio16gpio->base);
+ if ((*mask >> 8) & 0xFF)
+ outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
+
+ spin_unlock_irqrestore(&idio16gpio->lock, flags);
+}
+
static void idio_16_irq_ack(struct irq_data *data)
{
}
@@ -193,6 +210,14 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#define IDIO_16_NGPIO 32
+static const char *idio_16_names[IDIO_16_NGPIO] = {
+ "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
+ "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
+ "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
+ "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
+};
+
static int idio_16_probe(struct device *dev, unsigned int id)
{
struct idio_16_gpio *idio16gpio;
@@ -213,21 +238,20 @@ static int idio_16_probe(struct device *dev, unsigned int id)
idio16gpio->chip.parent = dev;
idio16gpio->chip.owner = THIS_MODULE;
idio16gpio->chip.base = -1;
- idio16gpio->chip.ngpio = 32;
+ idio16gpio->chip.ngpio = IDIO_16_NGPIO;
+ idio16gpio->chip.names = idio_16_names;
idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
idio16gpio->chip.get = idio_16_gpio_get;
idio16gpio->chip.set = idio_16_gpio_set;
+ idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
idio16gpio->base = base[id];
- idio16gpio->irq = irq[id];
idio16gpio->out_state = 0xFFFF;
spin_lock_init(&idio16gpio->lock);
- dev_set_drvdata(dev, idio16gpio);
-
- err = gpiochip_add_data(&idio16gpio->chip, idio16gpio);
+ err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
if (err) {
dev_err(dev, "GPIO registering failed (%d)\n", err);
return err;
@@ -241,30 +265,17 @@ static int idio_16_probe(struct device *dev, unsigned int id)
handle_edge_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(dev, "Could not add irqchip (%d)\n", err);
- goto err_gpiochip_remove;
+ return err;
}
- err = request_irq(irq[id], idio_16_irq_handler, 0, name, idio16gpio);
+ err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
+ idio16gpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
- goto err_gpiochip_remove;
+ return err;
}
return 0;
-
-err_gpiochip_remove:
- gpiochip_remove(&idio16gpio->chip);
- return err;
-}
-
-static int idio_16_remove(struct device *dev, unsigned int id)
-{
- struct idio_16_gpio *const idio16gpio = dev_get_drvdata(dev);
-
- free_irq(idio16gpio->irq, idio16gpio);
- gpiochip_remove(&idio16gpio->chip);
-
- return 0;
}
static struct isa_driver idio_16_driver = {
@@ -272,7 +283,6 @@ static struct isa_driver idio_16_driver = {
.driver = {
.name = "104-idio-16"
},
- .remove = idio_16_remove
};
module_isa_driver(idio_16_driver, num_idio_16);
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 9191056548fe..72f49d1e110d 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -43,25 +43,7 @@ typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq);
#define MAX_LABEL_SIZE 20
static void __iomem *gpio_base;
-
-static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio)
-{
- void __iomem *ptr;
-
- if (gpio < 32 * 1)
- ptr = gpio_base + 0x10;
- else if (gpio < 32 * 2)
- ptr = gpio_base + 0x38;
- else if (gpio < 32 * 3)
- ptr = gpio_base + 0x60;
- else if (gpio < 32 * 4)
- ptr = gpio_base + 0x88;
- else if (gpio < 32 * 5)
- ptr = gpio_base + 0xb0;
- else
- ptr = NULL;
- return ptr;
-}
+static unsigned int offset_array[5] = {0x10, 0x38, 0x60, 0x88, 0xb0};
static inline struct davinci_gpio_regs __iomem *irq2regs(struct irq_data *d)
{
@@ -81,11 +63,13 @@ static inline int __davinci_direction(struct gpio_chip *chip,
unsigned offset, bool out, int value)
{
struct davinci_gpio_controller *d = gpiochip_get_data(chip);
- struct davinci_gpio_regs __iomem *g = d->regs;
+ struct davinci_gpio_regs __iomem *g;
unsigned long flags;
u32 temp;
- u32 mask = 1 << offset;
+ int bank = offset / 32;
+ u32 mask = __gpio_mask(offset);
+ g = d->regs[bank];
spin_lock_irqsave(&d->lock, flags);
temp = readl_relaxed(&g->dir);
if (out) {
@@ -121,9 +105,12 @@ davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct davinci_gpio_controller *d = gpiochip_get_data(chip);
- struct davinci_gpio_regs __iomem *g = d->regs;
+ struct davinci_gpio_regs __iomem *g;
+ int bank = offset / 32;
- return !!((1 << offset) & readl_relaxed(&g->in_data));
+ g = d->regs[bank];
+
+ return !!(__gpio_mask(offset) & readl_relaxed(&g->in_data));
}
/*
@@ -133,9 +120,13 @@ static void
davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct davinci_gpio_controller *d = gpiochip_get_data(chip);
- struct davinci_gpio_regs __iomem *g = d->regs;
+ struct davinci_gpio_regs __iomem *g;
+ int bank = offset / 32;
- writel_relaxed((1 << offset), value ? &g->set_data : &g->clr_data);
+ g = d->regs[bank];
+
+ writel_relaxed(__gpio_mask(offset),
+ value ? &g->set_data : &g->clr_data);
}
static struct davinci_gpio_platform_data *
@@ -172,34 +163,13 @@ of_err:
return NULL;
}
-#ifdef CONFIG_OF_GPIO
-static int davinci_gpio_of_xlate(struct gpio_chip *gc,
- const struct of_phandle_args *gpiospec,
- u32 *flags)
-{
- struct davinci_gpio_controller *chips = dev_get_drvdata(gc->parent);
- struct davinci_gpio_platform_data *pdata = dev_get_platdata(gc->parent);
-
- if (gpiospec->args[0] > pdata->ngpio)
- return -EINVAL;
-
- if (gc != &chips[gpiospec->args[0] / 32].chip)
- return -EINVAL;
-
- if (flags)
- *flags = gpiospec->args[1];
-
- return gpiospec->args[0] % 32;
-}
-#endif
-
static int davinci_gpio_probe(struct platform_device *pdev)
{
- int i, base;
+ static int ctrl_num, bank_base;
+ int gpio, bank;
unsigned ngpio, nbank;
struct davinci_gpio_controller *chips;
struct davinci_gpio_platform_data *pdata;
- struct davinci_gpio_regs __iomem *regs;
struct device *dev = &pdev->dev;
struct resource *res;
char label[MAX_LABEL_SIZE];
@@ -238,41 +208,31 @@ static int davinci_gpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio_base))
return PTR_ERR(gpio_base);
- for (i = 0, base = 0; base < ngpio; i++, base += 32) {
- snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", i);
- chips[i].chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
- if (!chips[i].chip.label)
+ snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++);
+ chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
+ if (!chips->chip.label)
return -ENOMEM;
- chips[i].chip.direction_input = davinci_direction_in;
- chips[i].chip.get = davinci_gpio_get;
- chips[i].chip.direction_output = davinci_direction_out;
- chips[i].chip.set = davinci_gpio_set;
+ chips->chip.direction_input = davinci_direction_in;
+ chips->chip.get = davinci_gpio_get;
+ chips->chip.direction_output = davinci_direction_out;
+ chips->chip.set = davinci_gpio_set;
- chips[i].chip.base = base;
- chips[i].chip.ngpio = ngpio - base;
- if (chips[i].chip.ngpio > 32)
- chips[i].chip.ngpio = 32;
+ chips->chip.ngpio = ngpio;
+ chips->chip.base = bank_base;
#ifdef CONFIG_OF_GPIO
- chips[i].chip.of_gpio_n_cells = 2;
- chips[i].chip.of_xlate = davinci_gpio_of_xlate;
- chips[i].chip.parent = dev;
- chips[i].chip.of_node = dev->of_node;
+ chips->chip.of_gpio_n_cells = 2;
+ chips->chip.parent = dev;
+ chips->chip.of_node = dev->of_node;
#endif
- spin_lock_init(&chips[i].lock);
-
- regs = gpio2regs(base);
- if (!regs)
- return -ENXIO;
- chips[i].regs = regs;
- chips[i].set_data = &regs->set_data;
- chips[i].clr_data = &regs->clr_data;
- chips[i].in_data = &regs->in_data;
+ spin_lock_init(&chips->lock);
+ bank_base += ngpio;
- gpiochip_add_data(&chips[i].chip, &chips[i]);
- }
+ for (gpio = 0, bank = 0; gpio < ngpio; gpio += 32, bank++)
+ chips->regs[bank] = gpio_base + offset_array[bank];
+ gpiochip_add_data(&chips->chip, chips);
platform_set_drvdata(pdev, chips);
davinci_gpio_irq_setup(pdev);
return 0;
@@ -333,16 +293,19 @@ static struct irq_chip gpio_irqchip = {
static void gpio_irq_handler(struct irq_desc *desc)
{
- unsigned int irq = irq_desc_get_irq(desc);
struct davinci_gpio_regs __iomem *g;
u32 mask = 0xffff;
+ int bank_num;
struct davinci_gpio_controller *d;
+ struct davinci_gpio_irq_data *irqdata;
- d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc);
- g = (struct davinci_gpio_regs __iomem *)d->regs;
+ irqdata = (struct davinci_gpio_irq_data *)irq_desc_get_handler_data(desc);
+ bank_num = irqdata->bank_num;
+ g = irqdata->regs;
+ d = irqdata->chip;
/* we only care about one bank */
- if (irq & 1)
+ if ((bank_num % 2) == 1)
mask <<= 16;
/* temporarily mask (level sensitive) parent IRQ */
@@ -350,6 +313,7 @@ static void gpio_irq_handler(struct irq_desc *desc)
while (1) {
u32 status;
int bit;
+ irq_hw_number_t hw_irq;
/* ack any irqs */
status = readl_relaxed(&g->intstat) & mask;
@@ -362,9 +326,13 @@ static void gpio_irq_handler(struct irq_desc *desc)
while (status) {
bit = __ffs(status);
status &= ~BIT(bit);
+ /* Max number of gpios per controller is 144 so
+ * hw_irq will be in [0..143]
+ */
+ hw_irq = (bank_num / 2) * 32 + bit;
+
generic_handle_irq(
- irq_find_mapping(d->irq_domain,
- d->chip.base + bit));
+ irq_find_mapping(d->irq_domain, hw_irq));
}
}
chained_irq_exit(irq_desc_get_chip(desc), desc);
@@ -376,7 +344,7 @@ static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)
struct davinci_gpio_controller *d = gpiochip_get_data(chip);
if (d->irq_domain)
- return irq_create_mapping(d->irq_domain, d->chip.base + offset);
+ return irq_create_mapping(d->irq_domain, offset);
else
return -ENXIO;
}
@@ -390,7 +358,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
* can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
*/
if (offset < d->gpio_unbanked)
- return d->gpio_irq + offset;
+ return d->base_irq + offset;
else
return -ENODEV;
}
@@ -403,7 +371,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data);
g = (struct davinci_gpio_regs __iomem *)d->regs;
- mask = __gpio_mask(data->irq - d->gpio_irq);
+ mask = __gpio_mask(data->irq - d->base_irq);
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
return -EINVAL;
@@ -420,7 +388,9 @@ static int
davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
- struct davinci_gpio_regs __iomem *g = gpio2regs(hw);
+ struct davinci_gpio_controller *chips =
+ (struct davinci_gpio_controller *)d->host_data;
+ struct davinci_gpio_regs __iomem *g = chips->regs[hw / 32];
irq_set_chip_and_handler_name(irq, &gpio_irqchip, handle_simple_irq,
"davinci_gpio");
@@ -478,6 +448,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
struct irq_domain *irq_domain = NULL;
const struct of_device_id *match;
struct irq_chip *irq_chip;
+ struct davinci_gpio_irq_data *irqdata;
gpio_get_irq_chip_cb_t gpio_get_irq_chip;
/*
@@ -533,10 +504,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
* IRQs, while the others use banked IRQs, would need some setup
* tweaks to recognize hardware which can do that.
*/
- for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {
- chips[bank].chip.to_irq = gpio_to_irq_banked;
- chips[bank].irq_domain = irq_domain;
- }
+ chips->chip.to_irq = gpio_to_irq_banked;
+ chips->irq_domain = irq_domain;
/*
* AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO
@@ -545,9 +514,9 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
*/
if (pdata->gpio_unbanked) {
/* pass "bank 0" GPIO IRQs to AINTC */
- chips[0].chip.to_irq = gpio_to_irq_unbanked;
- chips[0].gpio_irq = bank_irq;
- chips[0].gpio_unbanked = pdata->gpio_unbanked;
+ chips->chip.to_irq = gpio_to_irq_unbanked;
+ chips->base_irq = bank_irq;
+ chips->gpio_unbanked = pdata->gpio_unbanked;
binten = GENMASK(pdata->gpio_unbanked / 16, 0);
/* AINTC handles mask/unmask; GPIO handles triggering */
@@ -557,14 +526,14 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
irq_chip->irq_set_type = gpio_irq_type_unbanked;
/* default trigger: both edges */
- g = gpio2regs(0);
+ g = chips->regs[0];
writel_relaxed(~0, &g->set_falling);
writel_relaxed(~0, &g->set_rising);
/* set the direct IRQs up to use that irqchip */
for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) {
irq_set_chip(irq, irq_chip);
- irq_set_handler_data(irq, &chips[gpio / 32]);
+ irq_set_handler_data(irq, chips);
irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
}
@@ -576,8 +545,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
* then chain through our own handler.
*/
for (gpio = 0, bank = 0; gpio < ngpio; bank++, bank_irq++, gpio += 16) {
- /* disabl