diff options
Diffstat (limited to 'drivers/gpio')
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, ®, 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 |
