diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 29 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpio/devres.c | 32 | ||||
-rw-r--r-- | drivers/gpio/gpio-104-dio-48e.c | 91 | ||||
-rw-r--r-- | drivers/gpio/gpio-104-idi-48.c | 45 | ||||
-rw-r--r-- | drivers/gpio/gpio-104-idio-16.c | 60 | ||||
-rw-r--r-- | drivers/gpio/gpio-davinci.c | 177 | ||||
-rw-r--r-- | drivers/gpio/gpio-exar.c | 200 | ||||
-rw-r--r-- | drivers/gpio/gpio-gemini.c | 236 | ||||
-rw-r--r-- | drivers/gpio/gpio-gpio-mm.c | 68 | ||||
-rw-r--r-- | drivers/gpio/gpio-intel-mid.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-mcp23s08.c | 320 | ||||
-rw-r--r-- | drivers/gpio/gpio-mm-lantiq.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-mockup.c | 377 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-pci-idio-16.c | 349 | ||||
-rw-r--r-- | drivers/gpio/gpio-rcar.c | 21 | ||||
-rw-r--r-- | drivers/gpio/gpio-stp-xway.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-ws16c48.c | 90 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 5 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 31 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 55 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.h | 3 |
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 = ®s->set_data; - chips[i].clr_data = ®s->clr_data; - chips[i].in_data = ®s->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 |