summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig92
-rw-r--r--drivers/gpio/Makefile7
-rw-r--r--drivers/gpio/gpio-altera.c1
-rw-r--r--drivers/gpio/gpio-arizona.c2
-rw-r--r--drivers/gpio/gpio-aspeed.c455
-rw-r--r--drivers/gpio/gpio-ath79.c1
-rw-r--r--drivers/gpio/gpio-axp209.c192
-rw-r--r--drivers/gpio/gpio-bcm-kona.c2
-rw-r--r--drivers/gpio/gpio-da9052.c2
-rw-r--r--drivers/gpio/gpio-da9055.c2
-rw-r--r--drivers/gpio/gpio-f7188x.c3
-rw-r--r--drivers/gpio/gpio-gpio-mm.c267
-rw-r--r--drivers/gpio/gpio-iop.c115
-rw-r--r--drivers/gpio/gpio-it87.c2
-rw-r--r--drivers/gpio/gpio-loongson1.c6
-rw-r--r--drivers/gpio/gpio-lp873x.c183
-rw-r--r--drivers/gpio/gpio-lpc18xx.c2
-rw-r--r--drivers/gpio/gpio-lpc32xx.c15
-rw-r--r--drivers/gpio/gpio-mmio.c4
-rw-r--r--drivers/gpio/gpio-mockup.c214
-rw-r--r--drivers/gpio/gpio-msic.c6
-rw-r--r--drivers/gpio/gpio-mxc.c10
-rw-r--r--drivers/gpio/gpio-palmas.c1
-rw-r--r--drivers/gpio/gpio-pca953x.c328
-rw-r--r--drivers/gpio/gpio-pisosr.c2
-rw-r--r--drivers/gpio/gpio-rcar.c4
-rw-r--r--drivers/gpio/gpio-sch.c2
-rw-r--r--drivers/gpio/gpio-spear-spics.c7
-rw-r--r--drivers/gpio/gpio-stmpe.c169
-rw-r--r--drivers/gpio/gpio-sx150x.c2
-rw-r--r--drivers/gpio/gpio-tc3589x.c47
-rw-r--r--drivers/gpio/gpio-tpic2810.c2
-rw-r--r--drivers/gpio/gpio-tps65086.c2
-rw-r--r--drivers/gpio/gpio-tps65218.c15
-rw-r--r--drivers/gpio/gpio-tps65912.c2
-rw-r--r--drivers/gpio/gpio-ts4800.c1
-rw-r--r--drivers/gpio/gpio-ts4900.c190
-rw-r--r--drivers/gpio/gpio-twl4030.c2
-rw-r--r--drivers/gpio/gpio-vf610.c7
-rw-r--r--drivers/gpio/gpio-wcove.c470
-rw-r--r--drivers/gpio/gpio-wm831x.c2
-rw-r--r--drivers/gpio/gpio-wm8350.c2
-rw-r--r--drivers/gpio/gpio-wm8994.c2
-rw-r--r--drivers/gpio/gpio-zynq.c15
-rw-r--r--drivers/gpio/gpiolib-sysfs.c4
-rw-r--r--drivers/gpio/gpiolib.c92
46 files changed, 2546 insertions, 407 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 03be200619a4..59ba58b8ac13 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -10,27 +10,6 @@ config ARCH_HAVE_CUSTOM_GPIO_H
overriding the default implementations. New uses of this are
strongly discouraged.
-config ARCH_WANT_OPTIONAL_GPIOLIB
- bool
- help
- Select this config option from the architecture Kconfig, if
- it is possible to use gpiolib on the architecture, but let the
- user decide whether to actually build it or not.
- Select this instead of ARCH_REQUIRE_GPIOLIB, if your architecture does
- not depend on GPIOs being available, but rather let the user
- decide whether he needs it or not.
-
-config ARCH_REQUIRE_GPIOLIB
- bool
- select GPIOLIB
- help
- Platforms select gpiolib if they use this infrastructure
- for all their GPIOs, usually starting with ones integrated
- into SOC processors.
- Selecting this from the architecture code will cause the gpiolib
- code to always get built in.
-
-
menuconfig GPIOLIB
bool "GPIO Support"
select ANON_INODES
@@ -127,6 +106,13 @@ config GPIO_AMDPT
driver for GPIO functionality on Promontory IOHub
Require ACPI ASL code to enumerate as a platform device.
+config GPIO_ASPEED
+ tristate "Aspeed GPIO support"
+ depends on (ARCH_ASPEED || COMPILE_TEST) && OF_GPIO
+ select GPIOLIB_IRQCHIP
+ help
+ Say Y here to support Aspeed AST2400 and AST2500 GPIO controllers.
+
config GPIO_ATH79
tristate "Atheros AR71XX/AR724X/AR913X GPIO support"
default y if ATH79
@@ -137,6 +123,12 @@ config GPIO_ATH79
Select this option to enable GPIO driver for
Atheros AR71XX/AR724X/AR913X SoC devices.
+config GPIO_AXP209
+ tristate "X-Powers AXP209 PMIC GPIO Support"
+ depends on MFD_AXP20X
+ help
+ Say yes to enable GPIO support for the AXP209 PMIC
+
config GPIO_BCM_KONA
bool "Broadcom Kona GPIO"
depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST)
@@ -236,7 +228,8 @@ config GPIO_ICH
config GPIO_IOP
tristate "Intel IOP GPIO"
- depends on ARM && (ARCH_IOP32X || ARCH_IOP33X)
+ depends on ARCH_IOP32X || ARCH_IOP33X || COMPILE_TEST
+ select GPIO_GENERIC
help
Say yes here to support the GPIO functionality of a number of Intel
IOP32X or IOP33X.
@@ -286,6 +279,18 @@ config GPIO_MM_LANTIQ
(EBU) found on Lantiq SoCs. The gpios are output only as they are
created by attaching a 16bit latch to the bus.
+config GPIO_MOCKUP
+ tristate "GPIO Testing Driver"
+ depends on GPIOLIB
+ select GPIO_SYSFS
+ help
+ This enables GPIO Testing driver, which provides a way to test GPIO
+ subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS
+ must be selected for this test.
+ User could use it through the script in
+ tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
+ it.
+
config GPIO_MOXART
bool "MOXART GPIO support"
depends on ARCH_MOXART || COMPILE_TEST
@@ -573,6 +578,19 @@ config GPIO_F7188X
To compile this driver as a module, choose M here: the module will
be called f7188x-gpio.
+config GPIO_GPIO_MM
+ tristate "Diamond Systems GPIO-MM GPIO support"
+ depends on ISA_BUS_API
+ help
+ Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12.
+
+ The Diamond Systems GPIO-MM device features 48 lines of digital I/O
+ via the emulation of dual 82C55A PPI chips. This driver provides GPIO
+ support for these 48 channels of digital I/O.
+
+ The base port addresses for the devices may be configured via the base
+ array module parameter.
+
config GPIO_IT87
tristate "IT87xx GPIO support"
help
@@ -779,6 +797,13 @@ config GPIO_TPIC2810
To compile this driver as a module, choose M here: the module will
be called gpio-tpic2810.
+config GPIO_TS4900
+ tristate "Technologic Systems FPGA I2C GPIO"
+ select REGMAP_I2C
+ help
+ Say yes here to enabled the GPIO driver for Technologic's FPGA core.
+ Series supported include TS-4100, TS-4900, TS-7970 and TS-7990.
+
endmenu
menu "MFD GPIO expanders"
@@ -882,6 +907,16 @@ config GPIO_LP3943
LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
Open drain outputs are required for this usage.
+config GPIO_LP873X
+ tristate "TI LP873X GPO"
+ depends on MFD_TI_LP873X
+ help
+ This driver supports the GPO on TI Lp873x PMICs. 2 GPOs are present
+ on LP873X PMICs.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-lp873x.
+
config GPIO_MAX77620
tristate "GPIO support for PMIC MAX77620 and MAX20024"
depends on MFD_MAX77620
@@ -992,6 +1027,19 @@ config GPIO_UCB1400
This enables support for the Philips UCB1400 GPIO pins.
The UCB1400 is an AC97 audio codec.
+config GPIO_WHISKEY_COVE
+ tristate "GPIO support for Whiskey Cove PMIC"
+ depends on INTEL_SOC_PMIC
+ select GPIOLIB_IRQCHIP
+ help
+ Support for GPIO pins on Whiskey Cove PMIC.
+
+ Say Yes if you have a Intel SoC based tablet with Whiskey Cove PMIC
+ inside.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-wcove.
+
config GPIO_WM831X
tristate "WM831x GPIOs"
depends on MFD_WM831X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 32ebc07074ed..ab28a2daeacc 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -28,6 +28,8 @@ obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
+obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
+obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
@@ -44,6 +46,7 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.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
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
@@ -57,6 +60,7 @@ obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
+obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
@@ -71,6 +75,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
+obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o
obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
@@ -111,6 +116,7 @@ obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o
+obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o
obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
@@ -121,6 +127,7 @@ obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
+obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o
obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c
index 3f87a03abc22..5bddbd507ca9 100644
--- a/drivers/gpio/gpio-altera.c
+++ b/drivers/gpio/gpio-altera.c
@@ -17,6 +17,7 @@
*/
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 991370494922..482462889c8f 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -79,7 +79,7 @@ static void arizona_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
ARIZONA_GPN_LVL, value);
}
-static struct gpio_chip template_chip = {
+static const struct gpio_chip template_chip = {
.label = "arizona",
.owner = THIS_MODULE,
.direction_input = arizona_gpio_direction_in,
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
new file mode 100644
index 000000000000..03a5925a423c
--- /dev/null
+++ b/drivers/gpio/gpio-aspeed.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright 2015 IBM Corp.
+ *
+ * Joel Stanley <joel@jms.id.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/gpio/driver.h>
+#include <linux/pinctrl/consumer.h>
+
+struct aspeed_gpio {
+ struct gpio_chip chip;
+ spinlock_t lock;
+ void __iomem *base;
+ int irq;
+};
+
+struct aspeed_gpio_bank {
+ uint16_t val_regs;
+ uint16_t irq_regs;
+ const char names[4];
+};
+
+static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
+ {
+ .val_regs = 0x0000,
+ .irq_regs = 0x0008,
+ .names = { 'A', 'B', 'C', 'D' },
+ },
+ {
+ .val_regs = 0x0020,
+ .irq_regs = 0x0028,
+ .names = { 'E', 'F', 'G', 'H' },
+ },
+ {
+ .val_regs = 0x0070,
+ .irq_regs = 0x0098,
+ .names = { 'I', 'J', 'K', 'L' },
+ },
+ {
+ .val_regs = 0x0078,
+ .irq_regs = 0x00e8,
+ .names = { 'M', 'N', 'O', 'P' },
+ },
+ {
+ .val_regs = 0x0080,
+ .irq_regs = 0x0118,
+ .names = { 'Q', 'R', 'S', 'T' },
+ },
+ {
+ .val_regs = 0x0088,
+ .irq_regs = 0x0148,
+ .names = { 'U', 'V', 'W', 'X' },
+ },
+ /*
+ * A bank exists for { 'Y', 'Z', "AA", "AB" }, but is not implemented.
+ * Only half of GPIOs Y support interrupt configuration, and none of Z,
+ * AA or AB do as they are output only.
+ */
+};
+
+#define GPIO_BANK(x) ((x) >> 5)
+#define GPIO_OFFSET(x) ((x) & 0x1f)
+#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
+
+#define GPIO_DATA 0x00
+#define GPIO_DIR 0x04
+
+#define GPIO_IRQ_ENABLE 0x00
+#define GPIO_IRQ_TYPE0 0x04
+#define GPIO_IRQ_TYPE1 0x08
+#define GPIO_IRQ_TYPE2 0x0c
+#define GPIO_IRQ_STATUS 0x10
+
+static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
+{
+ unsigned int bank = GPIO_BANK(offset);
+
+ WARN_ON(bank > ARRAY_SIZE(aspeed_gpio_banks));
+ return &aspeed_gpio_banks[bank];
+}
+
+static void __iomem *bank_val_reg(struct aspeed_gpio *gpio,
+ const struct aspeed_gpio_bank *bank,
+ unsigned int reg)
+{
+ return gpio->base + bank->val_regs + reg;
+}
+
+static void __iomem *bank_irq_reg(struct aspeed_gpio *gpio,
+ const struct aspeed_gpio_bank *bank,
+ unsigned int reg)
+{
+ return gpio->base + bank->irq_regs + reg;
+}
+
+static int aspeed_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+
+ return !!(ioread32(bank_val_reg(gpio, bank, GPIO_DATA))
+ & GPIO_BIT(offset));
+}
+
+static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
+ int val)
+{
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ void __iomem *addr;
+ u32 reg;
+
+ addr = bank_val_reg(gpio, bank, GPIO_DATA);
+ reg = ioread32(addr);
+
+ if (val)
+ reg |= GPIO_BIT(offset);
+ else
+ reg &= ~GPIO_BIT(offset);
+
+ iowrite32(reg, addr);
+}
+
+static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
+ int val)
+{
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ __aspeed_gpio_set(gc, offset, val);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
+{
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
+ iowrite32(reg & ~GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR));
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int aspeed_gpio_dir_out(struct gpio_chip *gc,
+ unsigned int offset, int val)
+{
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR));
+ iowrite32(reg | GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR));
+
+ __aspeed_gpio_set(gc, offset, val);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+ struct aspeed_gpio *gpio = gpiochip_get_data(gc);
+ const struct aspeed_gpio_bank *bank = to_bank(offset);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ val = ioread32(bank_val_reg(gpio, bank, GPIO_DIR)) & GPIO_BIT(offset);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return !val;
+
+}
+
+static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
+ struct aspeed_gpio **gpio,
+ const struct aspeed_gpio_bank **bank,
+ u32 *bit)
+{
+ int offset;
+
+ offset = irqd_to_hwirq(d);
+
+ *gpio = irq_data_get_irq_chip_data(d);
+ *bank = to_bank(offset);
+ *bit = GPIO_BIT(offset);
+
+ return 0;
+}
+
+static void aspeed_gpio_irq_ack(struct irq_data *d)
+{
+ const struct aspeed_gpio_bank *bank;
+ struct aspeed_gpio *gpio;
+ unsigned long flags;
+ void __iomem *status_addr;
+ u32 bit;
+ int rc;
+
+ rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit);
+ if (rc)
+ return;
+
+ status_addr = bank_irq_reg(gpio, bank, GPIO_IRQ_STATUS);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ iowrite32(bit, status_addr);
+ spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
+{
+ const struct aspeed_gpio_bank *bank;
+ struct aspeed_gpio *gpio;
+ unsigned long flags;
+ u32 reg, bit;
+ void __iomem *addr;
+ int rc;
+
+ rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit);
+ if (rc)
+ return;
+
+ addr = bank_irq_reg(gpio, bank, GPIO_IRQ_ENABLE);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ reg = ioread32(addr);
+ if (set)
+ reg |= bit;
+ else
+ reg &= bit;
+ iowrite32(reg, addr);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static void aspeed_gpio_irq_mask(struct irq_data *d)
+{
+ aspeed_gpio_irq_set_mask(d, false);
+}
+
+static void aspeed_gpio_irq_unmask(struct irq_data *d)
+{
+ aspeed_gpio_irq_set_mask(d, true);
+}
+
+static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
+{
+ u32 type0 = 0;
+ u32 type1 = 0;
+ u32 type2 = 0;
+ u32 bit, reg;
+ const struct aspeed_gpio_bank *bank;
+ irq_flow_handler_t handler;
+ struct aspeed_gpio *gpio;
+ unsigned long flags;
+ void __iomem *addr;
+ int rc;
+
+ rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit);
+ if (rc)
+ return -EINVAL;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_BOTH:
+ type2 |= bit;
+ case IRQ_TYPE_EDGE_RISING:
+ type0 |= bit;
+ case IRQ_TYPE_EDGE_FALLING:
+ handler = handle_edge_irq;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ type0 |= bit;
+ case IRQ_TYPE_LEVEL_LOW:
+ type1 |= bit;
+ handler = handle_level_irq;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&gpio->lock, flags);
+
+ addr = bank_irq_reg(gpio, bank, GPIO_IRQ_TYPE0);
+ reg = ioread32(addr);
+ reg = (reg & ~bit) | type0;
+ iowrite32(reg, addr);
+
+ addr = bank_irq_reg(gpio, bank, GPIO_IRQ_TYPE1);
+ reg = ioread32(addr);
+ reg = (reg & ~bit) | type1;
+ iowrite32(reg, addr);
+
+ addr = bank_irq_reg(gpio, bank, GPIO_IRQ_TYPE2);
+ reg = ioread32(addr);
+ reg = (reg & ~bit) | type2;
+ iowrite32(reg, addr);
+
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ irq_set_handler_locked(d, handler);
+
+ return 0;
+}
+
+static void aspeed_gpio_irq_handler(struct irq_desc *desc)
+{
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct irq_chip *ic = irq_desc_get_chip(desc);
+ struct aspeed_gpio *data = gpiochip_get_data(gc);
+ unsigned int i, p, girq;
+ unsigned long reg;
+
+ chained_irq_enter(ic, desc);
+
+ for (i = 0; i < ARRAY_SIZE(aspeed_gpio_banks); i++) {
+ const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
+
+ reg = ioread32(bank_irq_reg(data, bank, GPIO_IRQ_STATUS));
+
+ for_each_set_bit(p, &reg, 32) {
+ girq = irq_find_mapping(gc->irqdomain, i * 32 + p);
+ generic_handle_irq(girq);
+ }
+
+ }
+
+ chained_irq_exit(ic, desc);
+}
+
+static struct irq_chip aspeed_gpio_irqchip = {
+ .name = "aspeed-gpio",
+ .irq_ack = aspeed_gpio_irq_ack,
+ .irq_mask = aspeed_gpio_irq_mask,
+ .irq_unmask = aspeed_gpio_irq_unmask,
+ .irq_set_type = aspeed_gpio_set_type,
+};
+
+static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
+ struct platform_device *pdev)
+{
+ int rc;
+
+ rc = platform_get_irq(pdev, 0);
+ if (rc < 0)
+ return rc;
+
+ gpio->irq = rc;
+
+ rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip,
+ 0, handle_bad_irq, IRQ_TYPE_NONE);
+ if (rc) {
+ dev_info(&pdev->dev, "Could not add irqchip\n");
+ return rc;
+ }
+
+ gpiochip_set_chained_irqchip(&gpio->chip, &aspeed_gpio_irqchip,
+ gpio->irq, aspeed_gpio_irq_handler);
+
+ return 0;
+}
+
+static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
+static int __init aspeed_gpio_probe(struct platform_device *pdev)
+{
+ struct aspeed_gpio *gpio;
+ struct resource *res;
+ int rc;
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+ if (!gpio)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ gpio->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(gpio->base))
+ return PTR_ERR(gpio->base);
+
+ spin_lock_init(&gpio->lock);
+
+ gpio->chip.ngpio = ARRAY_SIZE(aspeed_gpio_banks) * 32;
+
+ gpio->chip.parent = &pdev->dev;
+ gpio->chip.direction_input = aspeed_gpio_dir_in;
+ gpio->chip.direction_output = aspeed_gpio_dir_out;
+ gpio->chip.get_direction = aspeed_gpio_get_direction;
+ gpio->chip.request = aspeed_gpio_request;
+ gpio->chip.free = aspeed_gpio_free;
+ gpio->chip.get = aspeed_gpio_get;
+ gpio->chip.set = aspeed_gpio_set;
+ gpio->chip.label = dev_name(&pdev->dev);
+ gpio->chip.base = -1;
+
+ rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
+ if (rc < 0)
+ return rc;
+
+ return aspeed_gpio_setup_irqs(gpio, pdev);
+}
+
+static const struct of_device_id aspeed_gpio_of_table[] = {
+ { .compatible = "aspeed,ast2400-gpio" },
+ { .compatible = "aspeed,ast2500-gpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
+
+static struct platform_driver aspeed_gpio_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = aspeed_gpio_of_table,
+ },
+};
+
+module_platform_driver_probe(aspeed_gpio_driver, aspeed_gpio_probe);
+
+MODULE_DESCRIPTION("Aspeed GPIO Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c
index c4f4cddc7c1a..9457e2022bf6 100644
--- a/drivers/gpio/gpio-ath79.c
+++ b/drivers/gpio/gpio-ath79.c
@@ -15,6 +15,7 @@
#include <linux/platform_data/gpio-ath79.h>
#include <linux/of_device.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/irq.h>
#define AR71XX_GPIO_REG_OE 0x00
diff --git a/drivers/gpio/gpio-axp209.c b/drivers/gpio/gpio-axp209.c
new file mode 100644
index 000000000000..d9c2a517c6df
--- /dev/null
+++ b/drivers/gpio/gpio-axp209.c
@@ -0,0 +1,192 @@
+/*
+ * AXP20x GPIO driver
+ *
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/g