diff options
Diffstat (limited to 'drivers/gpio')
31 files changed, 670 insertions, 1152 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ed37e5908b91..d5d36549ecc1 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -167,7 +167,7 @@ config GPIO_DWAPB config GPIO_EM tristate "Emma Mobile GPIO" - depends on ARM && OF_GPIO + depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO help Say yes here to support GPIO on Renesas Emma Mobile SoCs. @@ -451,7 +451,7 @@ config GPIO_VR41XX config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" - depends on PCI + depends on (X86 || COMPILE_TEST) && PCI select MFD_CORE select MFD_VX855 help @@ -520,6 +520,7 @@ config GPIO_ZYNQ config GPIO_ZX bool "ZTE ZX GPIO support" + depends on ARCH_ZX || COMPILE_TEST select GPIOLIB_IRQCHIP help Say yes here to support the GPIO device on ZTE ZX SoCs. @@ -603,7 +604,7 @@ config GPIO_IT87 config GPIO_SCH tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO" - depends on PCI + depends on (X86 || COMPILE_TEST) && PCI select MFD_CORE select LPC_SCH help @@ -777,16 +778,13 @@ config GPIO_PCF857X platform-neutral GPIO calls. config GPIO_SX150X - bool "Semtech SX150x I2C GPIO expander" - depends on I2C=y - select GPIOLIB_IRQCHIP + bool "Semtech SX150x I2C GPIO expander (deprecated)" + depends on PINCTRL && I2C=y + select PINCTRL_SX150X default n help - Say yes here to provide support for Semtech SX150-series I2C - GPIO expanders. Compatible models include: - - 8 bits: sx1508q - 16 bits: sx1509q + Say yes here to provide support for Semtech SX150x-series I2C + GPIO expanders. The GPIO driver was replaced by a Pinctrl version. config GPIO_TPIC2810 tristate "TPIC2810 8-Bit I2C GPO expander" @@ -798,6 +796,7 @@ config GPIO_TPIC2810 config GPIO_TS4900 tristate "Technologic Systems FPGA I2C GPIO" + depends on SOC_IMX6 || COMPILE_TEST select REGMAP_I2C help Say yes here to enabled the GPIO driver for Technologic's FPGA core. @@ -814,6 +813,14 @@ config GPIO_ADP5520 This option enables support for on-chip GPIO found on Analog Devices ADP5520 PMICs. +config GPIO_ALTERA_A10SR + tristate "Altera Arria10 System Resource GPIO" + depends on MFD_ALTERA_A10SR + help + Driver for Arria10 Development Kit GPIO expansion which + includes reads of pushbuttons and DIP switches as well + as writes to LEDs. + config GPIO_ARIZONA tristate "Wolfson Microelectronics Arizona class devices" depends on MFD_ARIZONA @@ -822,7 +829,7 @@ config GPIO_ARIZONA config GPIO_CRYSTAL_COVE tristate "GPIO support for Crystal Cove PMIC" - depends on INTEL_SOC_PMIC + depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC select GPIOLIB_IRQCHIP help Support for GPIO pins on Crystal Cove PMIC. @@ -835,6 +842,7 @@ config GPIO_CRYSTAL_COVE config GPIO_CS5535 tristate "AMD CS5535/CS5536 GPIO support" + depends on X86 || MIPS || COMPILE_TEST depends on MFD_CS5535 help The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that @@ -927,7 +935,7 @@ config GPIO_MAX77620 config GPIO_MSIC bool "Intel MSIC mixed signal gpio support" - depends on MFD_INTEL_MSIC + depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC help Enable support for GPIO on intel MSIC controllers found in intel MID devices @@ -1028,7 +1036,7 @@ config GPIO_UCB1400 config GPIO_WHISKEY_COVE tristate "GPIO support for Whiskey Cove PMIC" - depends on INTEL_SOC_PMIC + depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC select GPIOLIB_IRQCHIP help Support for GPIO pins on Whiskey Cove PMIC. @@ -1067,6 +1075,7 @@ menu "PCI GPIO expanders" config GPIO_AMD8111 tristate "AMD 8111 GPIO driver" + depends on X86 || COMPILE_TEST help The AMD 8111 south bridge contains 32 GPIO pins which can be used. @@ -1108,6 +1117,7 @@ config GPIO_MERRIFIELD config GPIO_ML_IOH tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" + depends on X86 || COMPILE_TEST select GENERIC_IRQ_CHIP help ML7213 is companion chip for Intel Atom E6xx series. diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d074c2299393..a7676b82de6f 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_GPIOLIB) += devres.o obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o +obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o @@ -24,6 +25,7 @@ obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o +obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o @@ -102,7 +104,6 @@ obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o -obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index 8ff7b0d3eac6..89863ea25de1 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -468,17 +468,19 @@ static int adnp_irq_setup(struct adnp *adnp) return err; } - err = gpiochip_irqchip_add(chip, - &adnp_irq_chip, - 0, - handle_simple_irq, - IRQ_TYPE_NONE); + err = gpiochip_irqchip_add_nested(chip, + &adnp_irq_chip, + 0, + handle_simple_irq, + IRQ_TYPE_NONE); if (err) { dev_err(chip->parent, "could not connect irqchip to gpiochip\n"); return err; } + gpiochip_set_nested_irqchip(chip, &adnp_irq_chip, adnp->client->irq); + return 0; } diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c new file mode 100644 index 000000000000..9e1a138fed53 --- /dev/null +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -0,0 +1,130 @@ +/* + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * GPIO driver for Altera Arria10 MAX5 System Resource Chip + * + * Adapted from gpio-tps65910.c + */ + +#include <linux/gpio/driver.h> +#include <linux/mfd/altera-a10sr.h> +#include <linux/module.h> + +/** + * struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure + * @gp: : instance of the gpio_chip + * @regmap: the regmap from the parent device. + */ +struct altr_a10sr_gpio { + struct gpio_chip gp; + struct regmap *regmap; +}; + +static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); + int ret, val; + + ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val); + if (ret < 0) + return ret; + + return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT)); +} + +static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip); + + regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG, + BIT(ALTR_A10SR_LED_VALID_SHIFT + offset), + value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset) + : 0); +} + +static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, + unsigned int nr) +{ + if (nr >= (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT)) + return 0; + return -EINVAL; +} + +static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, + unsigned int nr, int value) +{ + if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) + return 0; + return -EINVAL; +} + +static struct gpio_chip altr_a10sr_gc = { + .label = "altr_a10sr_gpio", + .owner = THIS_MODULE, + .get = altr_a10sr_gpio_get, + .set = altr_a10sr_gpio_set, + .direction_input = altr_a10sr_gpio_direction_input, + .direction_output = altr_a10sr_gpio_direction_output, + .can_sleep = true, + .ngpio = 12, + .base = -1, +}; + +static int altr_a10sr_gpio_probe(struct platform_device *pdev) +{ + struct altr_a10sr_gpio *gpio; + int ret; + struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->regmap = a10sr->regmap; + + gpio->gp = altr_a10sr_gc; + + gpio->gp.of_node = pdev->dev.of_node; + + ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, gpio); + + return 0; +} + +static const struct of_device_id altr_a10sr_gpio_of_match[] = { + { .compatible = "altr,a10sr-gpio" }, + { }, +}; +MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match); + +static struct platform_driver altr_a10sr_gpio_driver = { + .probe = altr_a10sr_gpio_probe, + .driver = { + .name = "altr_a10sr_gpio", + .of_match_table = of_match_ptr(altr_a10sr_gpio_of_match), + }, +}; +module_platform_driver(altr_a10sr_gpio_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>"); +MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO"); diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index 482462889c8f..1f91557717a6 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -137,15 +137,10 @@ static int arizona_gpio_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - goto err; + return ret; } - platform_set_drvdata(pdev, arizona_gpio); - - return ret; - -err: - return ret; + return 0; } static struct platform_driver arizona_gpio_driver = { diff --git a/drivers/gpio/gpio-axp209.c b/drivers/gpio/gpio-axp209.c index d9c2a517c6df..4a346b7b4172 100644 --- a/drivers/gpio/gpio-axp209.c +++ b/drivers/gpio/gpio-axp209.c @@ -64,13 +64,9 @@ static int axp20x_gpio_get(struct gpio_chip *chip, unsigned offset) { struct axp20x_gpio *gpio = gpiochip_get_data(chip); unsigned int val; - int reg, ret; - - reg = axp20x_gpio_get_reg(offset); - if (reg < 0) - return reg; + int ret; - ret = regmap_read(gpio->regmap, reg, &val); + ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val); if (ret) return ret; diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 7c446d118cd6..2197368cc899 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -351,8 +351,8 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) return retval; } - gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); + gpiochip_irqchip_add_nested(&cg->chip, &crystalcove_irqchip, 0, + handle_simple_irq, IRQ_TYPE_NONE); retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler, IRQF_ONESHOT, KBUILD_MODNAME, cg); @@ -362,6 +362,8 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) return retval; } + gpiochip_set_nested_irqchip(&cg->chip, &crystalcove_irqchip, irq); + return 0; } diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index dd262f00295d..9191056548fe 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -40,6 +40,7 @@ struct davinci_gpio_regs { typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq); #define BINTEN 0x8 /* GPIO Interrupt Per-Bank Enable Register */ +#define MAX_LABEL_SIZE 20 static void __iomem *gpio_base; @@ -201,6 +202,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) struct davinci_gpio_regs __iomem *regs; struct device *dev = &pdev->dev; struct resource *res; + char label[MAX_LABEL_SIZE]; pdata = davinci_gpio_get_pdata(pdev); if (!pdata) { @@ -237,7 +239,10 @@ static int davinci_gpio_probe(struct platform_device *pdev) return PTR_ERR(gpio_base); for (i = 0, base = 0; base < ngpio; i++, base += 32) { - chips[i].chip.label = "DaVinci"; + snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", i); + chips[i].chip.label = devm_kstrdup(dev, label, GFP_KERNEL); + if (!chips[i].chip.label) + return -ENOMEM; chips[i].chip.direction_input = davinci_direction_in; chips[i].chip.get = davinci_gpio_get; diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c index f7a60a441e95..5d38b08d1ee2 100644 --- a/drivers/gpio/gpio-dln2.c +++ b/drivers/gpio/gpio-dln2.c @@ -467,7 +467,6 @@ static int dln2_gpio_probe(struct platform_device *pdev) dln2->gpio.base = -1; dln2->gpio.ngpio = pins; dln2->gpio.can_sleep = true; - dln2->gpio.irq_not_threaded = true; dln2->gpio.set = dln2_gpio_set; dln2->gpio.get = dln2_gpio_get; dln2->gpio.request = dln2_gpio_request; diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c index 00b022c9acb3..a254d5b07b94 100644 --- a/drivers/gpio/gpio-etraxfs.c +++ b/drivers/gpio/gpio-etraxfs.c @@ -471,9 +471,4 @@ static struct platform_driver etraxfs_gpio_driver = { .probe = etraxfs_gpio_probe, }; -static int __init etraxfs_gpio_init(void) -{ - return platform_driver_register(&etraxfs_gpio_driver); -} - -device_initcall(etraxfs_gpio_init); +builtin_platform_driver(etraxfs_gpio_driver); diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c index 0b4df6051097..271356effb2e 100644 --- a/drivers/gpio/gpio-htc-egpio.c +++ b/drivers/gpio/gpio-htc-egpio.c @@ -17,7 +17,7 @@ #include <linux/platform_data/gpio-htc-egpio.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/module.h> +#include <linux/init.h> struct egpio_chip { int reg_start; @@ -160,10 +160,14 @@ static int egpio_get(struct gpio_chip *chip, unsigned offset) bit = egpio_bit(ei, offset); reg = egpio->reg_start + egpio_pos(ei, offset); - value = egpio_readw(ei, reg); - pr_debug("readw(%p + %x) = %x\n", - ei->base_addr, reg << ei->bus_shift, value); - return !!(value & bit); + if (test_bit(offset, &egpio->is_out)) { + return !!(egpio->cached_values & (1 << offset)); + } else { + value = egpio_readw(ei, reg); + pr_debug("readw(%p + %x) = %x\n", + ei->base_addr, reg << ei->bus_shift, value); + return !!(value & bit); + } } static int egpio_direction_input(struct gpio_chip *chip, unsigned offset) @@ -225,6 +229,15 @@ static int egpio_direction_output(struct gpio_chip *chip, } } +static int egpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct egpio_chip *egpio; + + egpio = gpiochip_get_data(chip); + + return !test_bit(offset, &egpio->is_out); +} + static void egpio_write_cache(struct egpio_info *ei) { int i; @@ -327,6 +340,7 @@ static int __init egpio_probe(struct platform_device *pdev) chip->set = egpio_set; chip->direction_input = egpio_direction_input; chip->direction_output = egpio_direction_output; + chip->get_direction = egpio_get_direction; chip->base = pdata->chip[i].gpio_base; chip->ngpio = pdata->chip[i].num_gpios; @@ -367,24 +381,6 @@ fail: return ret; } -static int __exit egpio_remove(struct platform_device *pdev) -{ - struct egpio_info *ei = platform_get_drvdata(pdev); - unsigned int irq, irq_end; - - if (ei->chained_irq) { - irq_end = ei->irq_start + ei->nirqs; - for (irq = ei->irq_start; irq < irq_end; irq++) { - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); - } - irq_set_chained_handler(ei->chained_irq, NULL); - device_init_wakeup(&pdev->dev, 0); - } - - return 0; -} - #ifdef CONFIG_PM static int egpio_suspend(struct platform_device *pdev, pm_message_t state) { @@ -416,8 +412,8 @@ static int egpio_resume(struct platform_device *pdev) static struct platform_driver egpio_driver = { .driver = { .name = "htc-egpio", + .suppress_bind_attrs = true, }, - .remove = __exit_p(egpio_remove), .suspend = egpio_suspend, .resume = egpio_resume, }; @@ -426,15 +422,5 @@ static int __init egpio_init(void) { return platform_driver_probe(&egpio_driver, egpio_probe); } - -static void __exit egpio_exit(void) -{ - platform_driver_unregister(&egpio_driver); -} - /* start early for dependencies */ subsys_initcall(egpio_init); -module_exit(egpio_exit) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kevin O'Connor <kevin@koconnor.net>"); diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 164de64b11fc..a1e44c221f66 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -421,9 +421,4 @@ static struct pci_driver intel_gpio_driver = { }, }; -static int __init intel_gpio_init(void) -{ - return pci_register_driver(&intel_gpio_driver); -} - -device_initcall(intel_gpio_init); +builtin_pci_driver(intel_gpio_driver); diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index a9aaf9d822b4..4ea4c6a1313b 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -520,20 +520,19 @@ static int max732x_irq_setup(struct max732x_chip *chip, client->irq); return ret; } - ret = gpiochip_irqchip_add(&chip->gpio_chip, - &max732x_irq_chip, - irq_base, - handle_simple_irq, - IRQ_TYPE_NONE); + ret = gpiochip_irqchip_add_nested(&chip->gpio_chip, + &max732x_irq_chip, + irq_base, + handle_simple_irq, + IRQ_TYPE_NONE); if (ret) { dev_err(&client->dev, "could not connect irqchip to gpiochip\n"); return ret; } - gpiochip_set_chained_irqchip(&chip->gpio_chip, - &max732x_irq_chip, - client->irq, - NULL); + gpiochip_set_nested_irqchip(&chip->gpio_chip, + &max732x_irq_chip, + client->irq); } return 0; diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c index b46b436cb97f..ec8de4190db9 100644 --- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -21,9 +21,6 @@ struct max77620_gpio { struct gpio_chip gpio_chip; struct regmap *rmap; struct device *dev; - int gpio_irq; - int irq_base; - int gpio_base; }; static const struct regmap_irq max77620_gpio_irqs[] = { @@ -254,7 +251,6 @@ static int max77620_gpio_probe(struct platform_device *pdev) mgpio->rmap = chip->rmap; mgpio->dev = &pdev->dev; - mgpio->gpio_irq = gpio_irq; mgpio->gpio_chip.label = pdev->name; mgpio->gpio_chip.parent = &pdev->dev; @@ -268,7 +264,6 @@ static int max77620_gpio_probe(struct platform_device *pdev) mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR; mgpio->gpio_chip.can_sleep = 1; mgpio->gpio_chip.base = -1; - mgpio->irq_base = -1; #ifdef CONFIG_OF_GPIO mgpio->gpio_chip.of_node = pdev->dev.parent->of_node; #endif @@ -281,9 +276,8 @@ static int max77620_gpio_probe(struct platform_device *pdev) return ret; } - mgpio->gpio_base = mgpio->gpio_chip.base; - ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, mgpio->gpio_irq, - IRQF_ONESHOT, mgpio->irq_base, + ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, gpio_irq, + IRQF_ONESHOT, -1, &max77620_gpio_irq_chip, &chip->gpio_irq_data); if (ret < 0) { @@ -296,6 +290,7 @@ static int max77620_gpio_probe(struct platform_device *pdev) static const struct platform_device_id max77620_gpio_devtype[] = { { .name = "max77620-gpio", }, + { .name = "max20024-gpio", }, {}, }; MODULE_DEVICE_TABLE(platform, max77620_gpio_devtype); diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index d55af50e7034..ffb73f688ae1 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -217,8 +217,4 @@ static struct platform_driver mb86s70_gpio_driver = { .remove = mb86s70_gpio_remove, }; -static int __init mb86s70_gpio_init(void) -{ - return platform_driver_register(&mb86s70_gpio_driver); -} -device_initcall(mb86s70_gpio_init); +builtin_platform_driver(mb86s70_gpio_driver); diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 99d37b56c258..504550665091 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -473,21 +473,20 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) return err; } - err = gpiochip_irqchip_add(chip, - &mcp23s08_irq_chip, - 0, - handle_simple_irq, - IRQ_TYPE_NONE); + err = gpiochip_irqchip_add_nested(chip, + &mcp23s08_irq_chip, + 0, + handle_simple_irq, + IRQ_TYPE_NONE); if (err) { dev_err(chip->parent, "could not connect irqchip to gpiochip: %d\n", err); return err; } - gpiochip_set_chained_irqchip(chip, - &mcp23s08_irq_chip, - mcp->irq, - NULL); + gpiochip_set_nested_irqchip(chip, + &mcp23s08_irq_chip, + mcp->irq); return 0; } diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 45b51278b8ee..69e0f4ace465 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -11,6 +11,7 @@ #include <linux/bitops.h> #include <linux/gpio/driver.h> +#include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -161,6 +162,34 @@ static int mrfld_gpio_direction_output(struct gpio_chip *chip, return 0; } +static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + void __iomem *gpdr = gpio_reg(chip, offset, GPDR); + + return (readl(gpdr) & BIT(offset % 32)) ? GPIOF_DIR_OUT : GPIOF_DIR_IN; +} + +static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, + unsigned int debounce) +{ + struct mrfld_gpio *priv = gpiochip_get_data(chip); + void __iomem *gfbr = gpio_reg(chip, offset, GFBR); + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&priv->lock, flags); + + if (debounce) + value = readl(gfbr) & ~BIT(offset % 32); + else + value = readl(gfbr) | BIT(offset % 32); + writel(value, gfbr); + + raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + static void mrfld_irq_ack(struct irq_data *d) { struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); @@ -384,6 +413,8 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id priv->chip.direction_output = mrfld_gpio_direction_output; priv->chip.get = mrfld_gpio_get; priv->chip.set = mrfld_gpio_set; + priv->chip.get_direction = mrfld_gpio_get_direction; + priv->chip.set_debounce = mrfld_gpio_set_debounce; priv->chip.base = gpio_base; priv->chip.ngpio = MRFLD_NGPIO; priv->chip.can_sleep = false; @@ -411,7 +442,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id } retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base, - handle_simple_irq, IRQ_TYPE_NONE); + handle_bad_irq, IRQ_TYPE_NONE); if (retval) { dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); return retval; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index ee1724806f46..1e8fde8cb803 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -87,10 +87,15 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) u32 val; u32 pin_mask = 1 << d->hwirq; struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct irq_chip_type *ct = irq_data_get_chip_type(d); struct mxs_gpio_port *port = gc->private; void __iomem *pin_addr; int edge; + if (!(ct->type & type)) + if (irq_setup_alt_chip(d, type)) + return -EINVAL; + port->both_edges &= ~pin_mask; switch (type) { case IRQ_TYPE_EDGE_BOTH: @@ -119,10 +124,13 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) /* set level or edge */ pin_addr = port->base + PINCTRL_IRQLEV(port); - if (edge & GPIO_INT_LEV_MASK) + if (edge & GPIO_INT_LEV_MASK) { writel(pin_mask, pin_addr + MXS_SET); - else + writel(pin_mask, port->base + PINCTRL_IRQEN(port) + MXS_SET); + } else { writel(pin_mask, pin_addr + MXS_CLR); + writel(pin_mask, port->base + PINCTRL_PIN2IRQ(port) + MXS_SET); + } /* set polarity */ pin_addr = port->base + PINCTRL_IRQPOL(port); @@ -202,21 +210,37 @@ static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) struct irq_chip_generic *gc; struct irq_chip_type *ct; - gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base, + gc = irq_alloc_generic_chip("gpio-mxs", 2, irq_base, port->base, handle_level_irq); if (!gc) return -ENOMEM; gc->private = port; - ct = gc->chip_types; + ct = &gc->chip_types[0]; + ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; + ct->chip.irq_ack = irq_gc_ack_set_bit; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; + ct->chip.irq_set_type = mxs_gpio_set_irq_type; + ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; + ct->chip.flags = IRQCHIP_SET_TYPE_MASKED; + ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; + ct->regs.enable = PINCTRL_PIN2IRQ(port) + MXS_SET; + ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR; + + ct = &gc->chip_types[1]; + ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ct->chip.irq_ack = irq_gc_ack_set_bit; - ct->chip.irq_mask = irq_gc_mask_clr_bit; - ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; ct->chip.irq_set_type = mxs_gpio_set_irq_type; ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; + ct->chip.flags = IRQCHIP_SET_TYPE_MASKED; ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; |