summaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 08:46:04 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 08:46:04 -0800
commit1ec5c1867af085897bb9e0f67bef3713334dbe7f (patch)
tree6d4fa09006a3a4a163fd357bc10da047207341cf /drivers/gpio
parentd5dee39b27201f9f5460eca55efcc91a663b738c (diff)
parent3498d8694d41af701c51289e7caf3ffefc7bfb6b (diff)
Merge tag 'gpio-v4.11-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 v4.11 cycle Core changes: - Augment fwnode_get_named_gpiod() to configure the GPIO pin immediately after requesting it like all other APIs do. This is a treewide change also updating all users. - Pass a GPIO label down to gpiod_request() from fwnode_get_named_gpiod(). This makes debugfs and the userspace ABI correctly reflect the current in-kernel consumer of a pin taken using this abstraction. This is a treewide change also updating all users. - Rename devm_get_gpiod_from_child() to devm_fwnode_get_gpiod_from_child() to reflect the fact that this function is operating on a fwnode object. This is a treewide change also updating all users. - Make it possible to take multiple GPIOs in a single hog of device tree hogs. - The refactorings switching GPIO chips to use the .set_config() callback using standard pin control properties and providing a backend into the pin control subsystem that were also merged into the pin control tree naturally appear here too. Testing instrumentation: - A whole slew of cleanups and improvements to the mockup GPIO driver. We now have an extended userspace test exercising the subsystem, and we can inject interrupts etc from userspace to fully test the core GPIO functionality. New drivers: - New driver for the Cortina Systems Gemini GPIO controller. - New driver for the Exar XR17V352/354/358 chips. - New driver for the ACCES PCI-IDIO-16 PCI GPIO card. Driver changes: - RCAR: set the irqchip parent device, add fine-grained runtime PM support. - pca953x: support optional RESET control line on the chip. - DaVinci: cleanups and simplifications. Add support for multiple instances. - .set_multiple() and naming of lines on more or less all of the ISA/PCI GPIO controllers. - mcp23s08: refactored to use regmap as a first step to further rewrites and modernizations" * tag 'gpio-v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (61 commits) gpio: reintroduce devm_get_gpiod_from_child() gpio: pci-idio-16: Fix PCI BAR index gpio: pci-idio-16: Fix PCI device ID code gpio: mockup: implement event injecting over debugfs gpio: mockup: add a dummy irqchip gpio: mockup: implement naming the lines gpio: mockup: code shrink gpio: mockup: readability tweaks gpio: Add GPIO support for the ACCES PCI-IDIO-16 gpio: Add the devm_fwnode_get_index_gpiod_from_child() helper gpio: Rename devm_get_gpiod_from_child() gpio: mcp23s08: Select REGMAP/REGMAP_I2C to fix build error gpio: ws16c48: Add support for GPIO names gpio: gpio-mm: Add support for GPIO names gpio: 104-idio-16: Add support for GPIO names gpio: 104-idi-48: Add support for GPIO names gpio: 104-dio-48e: Add support for GPIO names gpio: ws16c48: Remove unnecessary driver_data set gpio: gpio-mm: Remove unnecessary driver_data set gpio: 104-idio-16: Remove unnecessary driver_data set ...
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 -E