diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 38 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpio/gpio-altera-a10sr.c | 130 | ||||
-rw-r--r-- | drivers/gpio/gpio-arizona.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-axp209.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpio-davinci.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpio-etraxfs.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpio-htc-egpio.c | 54 | ||||
-rw-r--r-- | drivers/gpio/gpio-intel-mid.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpio-max77620.c | 11 | ||||
-rw-r--r-- | drivers/gpio/gpio-mb86s7x.c | 6 | ||||
-rw-r--r-- | drivers/gpio/gpio-merrifield.c | 33 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 45 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-stmpe.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-sx150x.c | 792 | ||||
-rw-r--r-- | drivers/gpio/gpio-vf610.c | 6 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 107 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-devprop.c | 67 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 51 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 38 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.h | 2 |
22 files changed, 459 insertions, 966 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 26ee00f6bd58..28ed4ccc15b4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -171,7 +171,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. @@ -455,7 +455,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 @@ -524,6 +524,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. @@ -607,7 +608,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 @@ -781,16 +782,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" @@ -802,6 +800,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. @@ -818,6 +817,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 @@ -826,7 +833,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. @@ -839,6 +846,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 @@ -931,7 +939,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 @@ -1032,7 +1040,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. @@ -1071,6 +1079,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. @@ -1112,6 +1121,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 ab28a2daeacc..8043a95e43dc 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_GPIO_DEVRES) += 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-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-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-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-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-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 b9daa0bf32a4..62061f740ccf 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; - ct->regs.mask = PINCTRL_IRQEN(port); + ct->regs.enable = PINCTRL_IRQEN(port) + MXS_SET; + ct->regs.disable = PINCTRL_IRQEN(port) + MXS_CLR; + ct->handler = handle_level_irq; irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); @@ -297,11 +321,8 @@ static int mxs_gpio_probe(struct platform_device *pdev) } port->base = base; - /* - * select the pin interrupt functionality but initially - * disable the interrupts - */ - writel(~0U, port->base + PINCTRL_PIN2IRQ(port)); + /* initially disable the interrupts */ + writel(0, port->base + PINCTRL_PIN2IRQ(port)); writel(0, port->base + PINCTRL_IRQEN(port)); /* clear address has to be used to clear IRQSTAT bits */ diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index e422568e14ad..601c4550ee27 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -74,6 +74,7 @@ static const struct i2c_device_id pca953x_id[] = { { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, { "max7315", 8 | PCA953X_TYPE | PCA_INT, }, + { "max7318", 16 | PCA953X_TYPE | PCA_INT, }, { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, @@ -907,6 +908,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), }, { .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), }, + { .compatible = "maxim,max7318", .data = OF_953X(16, PCA_INT), }, { .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,pca9536", .data = OF_953X( 4, 0), }, diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index e7d422a6b90b..e2e1b16a42db 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -413,7 +413,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev) stmpe->partnum != STMPE1801) { stmpe_reg_write(stmpe, statmsbreg + i, status[i]); stmpe_reg_write(stmpe, - stmpe->regs[STMPE_IDX_GPEDR_LSB + i], + stmpe->regs[STMPE_IDX_GPEDR_MSB] + i, status[i]); } } diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c deleted file mode 100644 index af95de89db01..000000000000 --- a/drivers/gpio/gpio-sx150x.c +++ /dev/null @@ -1,792 +0,0 @@ -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. - * - * Driver for Semtech SX150X I2C GPIO Expanders - * - * Author: Gregory Bean <gbean@codeaurora.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -#include <linux/gpio.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/of_gpio.h> -#include <linux/of_device.h> - -#define NO_UPDATE_PENDING -1 - -/* The chip models of sx150x */ -#define SX150X_123 0 -#define SX150X_456 1 -#define SX150X_789 2 - -struct sx150x_123_pri { - u8 reg_pld_mode; - u8 reg_pld_table0; - u8 reg_pld_table1; - u8 reg_pld_table2; - u8 reg_pld_table3; - u8 reg_pld_table4; - u8 reg_advance; -}; - -struct sx150x_456_pri { - u8 reg_pld_mode; - u8 reg_pld_table0; - u8 reg_pld_table1; - u8 reg_pld_table2; - u8 reg_pld_table3; - u8 reg_pld_table4; - u8 reg_advance; -}; - -struct sx150x_789_pri { - u8 reg_drain; - u8 reg_polarity; - u8 reg_clock; - u8 reg_misc; - u8 reg_reset; - u8 ngpios; -}; - -struct sx150x_device_data { - u8 model; - u8 reg_pullup; - u8 reg_pulldn; - u8 reg_dir; - u8 reg_data; - u8 reg_irq_mask; - u8 reg_irq_src; - u8 reg_sense; - u8 ngpios; - union { - struct sx150x_123_pri x123; - struct sx150x_456_pri x456; - struct sx150x_789_pri x789; - } pri; -}; - -/** - * struct sx150x_platform_data - config data for SX150x driver - * @gpio_base: The index number of the first GPIO assigned to this - * GPIO expander. The expander will create a block of - * consecutively numbered gpios beginning at the given base, - * with the size of the block depending on the model of the - * expander chip. - * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO - * instead of as an oscillator, increasing the size of the - * GP(I)O pool created by this expander by one. The - * output-only GPO pin will be added at the end of the block. - * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor - * for each IO line in the expander. Setting the bit at - * position n will enable the pull-up for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down - * resistor for each IO line in the expander. Setting the - * bit at position n will enable the pull-down for the IO at - * the corresponding offset. For chips with fewer than - * 16 IO pins, high-end bits are ignored. - * @io_polarity: A bit-mask which enables polarity inversion for each IO line - * in the expander. Setting the bit at position n inverts - * the polarity of that IO line, while clearing it results - * in normal polarity. For chips with fewer than 16 IO pins, - * high-end bits are ignored. - * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line - * is connected, via which it reports interrupt events - * across all GPIO lines. This must be a real, - * pre-existing IRQ line. - * Setting this value < 0 disables the irq_chip functionality - * of the driver. - * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based - * IRQ lines will appear. Similarly to gpio_base, the expander - * will create a block of irqs beginning at this number. - * This value is ignored if irq_summary is < 0. - * @reset_during_probe: If set to true, the driver will trigger a full - * reset of the chip at the beginning of the probe - * in order to place it in a known state. - */ -struct sx150x_platform_data { - unsigned gpio_base; - bool oscio_is_gpo; - u16 io_pullup_ena; - u16 io_pulldn_ena; - u16 io_polarity; - int irq_summary; - unsigned irq_base; - bool reset_during_probe; -}; - -struct sx150x_chip { - struct gpio_chip gpio_chip; - struct i2c_client *client; - const struct sx150x_device_data *dev_cfg; - int irq_summary; - int irq_base; - int irq_update; - u32 irq_sense; - u32 irq_masked; - u32 dev_sense; - u32 dev_masked; - struct irq_chip irq_chip; - struct mutex lock; -}; - -static const struct sx150x_device_data sx150x_devices[] = { - [0] = { /* sx1508q */ - .model = SX150X_789, - .reg_pullup = 0x03, - .reg_pulldn = 0x04, - .reg_dir = 0x07, - .reg_data = 0x08, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0c, - .reg_sense = 0x0b, - .pri.x789 = { - .reg_drain = 0x05, - .reg_polarity = 0x06, - .reg_clock = 0x0f, - .reg_misc = 0x10, - .reg_reset = 0x7d, - }, - .ngpios = 8, - }, - [1] = { /* sx1509q */ - .model = SX150X_789, - .reg_pullup = 0x07, - .reg_pulldn = 0x09, - .reg_dir = 0x0f, - .reg_data = 0x11, - .reg_irq_mask = 0x13, - .reg_irq_src = 0x19, - .reg_sense = 0x17, - .pri.x789 = { - .reg_drain = 0x0b, - .reg_polarity = 0x0d, - .reg_clock = 0x1e, - .reg_misc = 0x1f, - .reg_reset = 0x7d, - }, - .ngpios = 16 - }, - [2] = { /* sx1506q */ - .model = SX150X_456, - .reg_pullup = 0x05, - .reg_pulldn = 0x07, - .reg_dir = 0x03, - .reg_data = 0x01, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0f, - .reg_sense = 0x0d, - .pri.x456 = { - .reg_pld_mode = 0x21, - .reg_pld_table0 = 0x23, - .reg_pld_table1 = 0x25, - .reg_pld_table2 = 0x27, - .reg_pld_table3 = 0x29, - .reg_pld_table4 = 0x2b, - .reg_advance = 0xad, - }, - .ngpios = 16 - }, - [3] = { /* sx1502q */ - .model = SX150X_123, - .reg_pullup = 0x02, - .reg_pulldn = 0x03, - .reg_dir = 0x01, - .reg_data = 0x00, - .reg_irq_mask = 0x05, - .reg_irq_src = 0x08, - .reg_sense = 0x07, - .pri.x123 = { - .reg_pld_mode = 0x10, - .reg_pld_table0 = 0x11, - .reg_pld_table1 = 0x12, - .reg_pld_table2 = 0x13, - .reg_pld_table3 = 0x14, - .reg_pld_table4 = 0x15, - .reg_advance = 0xad, - }, - .ngpios = 8, - }, -}; - -static const struct i2c_device_id sx150x_id[] = { - {"sx1508q", 0}, - {"sx1509q", 1}, - {"sx1506q", 2}, - {"sx1502q", 3}, - {} -}; - -static const struct of_device_id sx150x_of_match[] = { - { .compatible = "semtech,sx1508q" }, - { .compatible = "semtech,sx1509q" }, - { .compatible = "semtech,sx1506q" }, - { .compatible = "semtech,sx1502q" }, - {}, -}; - -static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) -{ - s32 err = i2c_smbus_write_byte_data(client, reg, val); - - if (err < 0) - dev_warn(&client->dev, - "i2c write fail: can't write %02x to %02x: %d\n", - val, reg, err); - return err; -} - -static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) -{ - s32 err = i2c_smbus_read_byte_data(client, reg); - - if (err >= 0) - *val = err; - else - dev_warn(&client->dev, - "i2c read fail: can't read from %02x: %d\n", - reg, err); - return err; -} - -static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset) -{ - return (chip->dev_cfg->ngpios == offset); -} - -/* - * These utility functions solve the common problem of locating and setting - * configuration bits. Configuration bits are grouped into registers - * whose indexes increase downwards. For example, with eight-bit registers, - * sixteen gpios would have their config bits grouped in the following order: - * REGISTER N-1 [ f e d c b a 9 8 ] - * N [ 7 6 5 4 3 2 1 0 ] - * - * For multi-bit configurations, the pattern gets wider: - * REGISTER N-3 [ f f e e d d c c ] - * N-2 [ b b a a 9 9 8 8 ] - * N-1 [ 7 7 6 6 5 5 4 4 ] - * N [ 3 3 2 2 1 1 0 0 ] - * - * Given the address of the starting register 'N', the index of the gpio - * whose configuration we seek to change, and the width in bits of that - * configuration, these functions allow us to locate the correct - * register and mask the correct bits. - */ -static inline void sx150x_find_cfg(u8 offset, u8 width, - u8 *reg, u8 *mask, u8 *shift) -{ - *reg -= offset * width / 8; - *mask = (1 << width) - 1; - *shift = (offset * width) % 8; - *mask <<= *shift; -} - -static s32 sx150x_write_cfg(struct sx150x_chip *chip, - u8 offset, u8 width, u8 reg, u8 val) -{ - u8 mask; - u8 data; - u8 shift; - s32 err; - - sx150x_find_cfg(offset, width, ®, &mask, &shift); - err = sx150x_i2c_read(chip->client, reg, &data); - if (err < 0) - return err; - - data &= ~mask; - data |= (val << shift) & mask; - return sx150x_i2c_write(chip->client, reg, data); -} - -static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset) -{ - u8 reg = chip->dev_cfg->reg_data; - u8 mask; - u8 data; - u8 shift; - s32 err; - - sx150x_find_cfg(offset, 1, ®, &mask, &shift); - err = sx150x_i2c_read(chip->client, reg, &data); - if (err >= 0) - err = (data & mask) != 0 ? 1 : 0; - - return err; -} - -static void sx150x_set_oscio(struct sx150x_chip *chip, int val) -{ - sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x789.reg_clock, - (val ? 0x1f : 0x10)); -} - -static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val) -{ - sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_data, - (val ? 1 : 0)); -} - -static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset) -{ - return sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_dir, - 1); -} - -static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val) -{ - int err; - - err = sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_data, - (val ? 1 : 0)); - if (err >= 0) - err = sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->reg_dir, - 0); - return err; -} - -static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - int status = -EINVAL; - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_get_io(chip, offset); - mutex_unlock(&chip->lock); - } - - return (status < 0) ? status : !!status; -} - -static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - - mutex_lock(&chip->lock); - if (offset_is_oscio(chip, offset)) - sx150x_set_oscio(chip, val); - else - sx150x_set_io(chip, offset, val); - mutex_unlock(&chip->lock); -} - -static int sx150x_gpio_set_single_ended(struct gpio_chip *gc, - unsigned offset, - enum single_ended_mode mode) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - - /* On the SX160X 789 we can set open drain */ - if (chip->dev_cfg->model != SX150X_789) - return -ENOTSUPP; - - if (mode == LINE_MODE_PUSH_PULL) - return sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->pri.x789.reg_drain, - 0); - - if (mode == LINE_MODE_OPEN_DRAIN) - return sx150x_write_cfg(chip, - offset, - 1, - chip->dev_cfg->pri.x789.reg_drain, - 1); - return -ENOTSUPP; -} - -static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - int status = -EINVAL; - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_io_input(chip, offset); - mutex_unlock(&chip->lock); - } - return status; -} - -static int sx150x_gpio_direction_output(struct gpio_chip *gc, - unsigned offset, - int val) -{ - struct sx150x_chip *chip = gpiochip_get_data(gc); - int status = 0; - - if (!offset_is_oscio(chip, offset)) { - mutex_lock(&chip->lock); - status = sx150x_io_output(chip, offset, val); - mutex_unlock(&chip->lock); - } - return status; -} - -static void sx150x_irq_mask(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n = d->hwirq; - - chip->irq_masked |= (1 << n); - chip->irq_update = n; -} - -static void sx150x_irq_unmask(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n = d->hwirq; - - chip->irq_masked &= ~(1 << n); - chip->irq_update = n; -} - -static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n, val = 0; - - if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) - return -EINVAL; - - n = d->hwirq; - - if (flow_type & IRQ_TYPE_EDGE_RISING) - val |= 0x1; - if (flow_type & IRQ_TYPE_EDGE_FALLING) - val |= 0x2; - - chip->irq_sense &= ~(3UL << (n * 2)); - chip->irq_sense |= val << (n * 2); - chip->irq_update = n; - return 0; -} - -static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) -{ - struct sx150x_chip *chip = (struct sx150x_chip *)dev_id; - unsigned nhandled = 0; - unsigned sub_irq; - unsigned n; - s32 err; - u8 val; - int i; - - for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) { - err = sx150x_i2c_read(chip->client, - chip->dev_cfg->reg_irq_src - i, - &val); - if (err < 0) - continue; - - sx150x_i2c_write(chip->client, - chip->dev_cfg->reg_irq_src - i, - val); - for (n = 0; n < 8; ++n) { - if (val & (1 << n)) { - sub_irq = irq_find_mapping( - chip->gpio_chip.irqdomain, - (i * 8) + n); - handle_nested_irq(sub_irq); - ++nhandled; - } - } - } - - return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); -} - -static void sx150x_irq_bus_lock(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - - mutex_lock(&chip->lock); -} - -static void sx150x_irq_bus_sync_unlock(struct irq_data *d) -{ - struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned n; - - if (chip->irq_update == NO_UPDATE_PENDING) - goto out; - - n = chip->irq_update; - chip->irq_update = NO_UPDATE_PENDING; - - /* Avoid updates if nothing changed */ - if (chip->dev_sense == chip->irq_sense && - chip->dev_masked == chip->irq_masked) - goto out; - - chip->dev_sense = chip->irq_sense; - chip->dev_masked = chip->irq_masked; - - if (chip->irq_masked & (1 << n)) { - sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); - sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); - } else { - sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); - sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, - chip->irq_sense >> (n * 2)); - } -out: - mutex_unlock(&chip->lock); -} - -static void sx150x_init_chip(struct sx150x_chip *chip, - struct i2c_client *client, - kernel_ulong_t driver_data, - struct sx150x_platform_data *pdata) -{ - mutex_init(&chip->lock); - - chip->client = client; - chip->dev_cfg = &sx150x_devices[driver_data]; - chip->gpio_chip.parent = &client->dev; - chip->gpio_chip.label = client->name; - chip->gpio_chip.direction_input = sx150x_gpio_direction_input; - chip->gpio_chip.direction_output = sx150x_gpio_direction_output; - chip->gpio_chip.get = sx150x_gpio_get; - chip->gpio_chip.set = sx150x_gpio_set; - chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended; - chip->gpio_chip.base = pdata->gpio_base; - chip->gpio_chip.can_sleep = true; - chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; -#ifdef CONFIG_OF_GPIO - chip->gpio_chip.of_node = client->dev.of_node; - chip->gpio_chip.of_gpio_n_cells = 2; -#endif - if (pdata->oscio_is_gpo) - ++chip->gpio_chip.ngpio; - - chip->irq_chip.name = client->name; - chip->irq_chip.irq_mask = sx150x_irq_mask; - chip->irq_chip.irq_unmask = sx150x_irq_unmask; - chip->irq_chip.irq_set_type = sx150x_irq_set_type; - chip->irq_chip.irq_bus_lock = sx150x_irq_bus_lock; - chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; - chip->irq_summary = -1; - chip->irq_base = -1; - chip->irq_masked = ~0; - chip->irq_sense = 0; - chip->dev_masked = ~0; - chip->dev_sense = 0; - chip->irq_update = NO_UPDATE_PENDING; -} - -static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) -{ - int err = 0; - unsigned n; - - for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n) - err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8)); - return err; -} - -static int sx150x_reset(struct sx150x_chip *chip) -{ - int err; - - err = i2c_smbus_write_byte_data(chip->client, - chip->dev_cfg->pri.x789.reg_reset, - 0x12); - if (err < 0) - return err; - - err = i2c_smbus_write_byte_data(chip->client, - chip->dev_cfg->pri.x789.reg_reset, - 0x34); - return err; -} - -static int sx150x_init_hw(struct sx150x_chip *chip, - struct sx150x_platform_data *pdata) -{ - int err = 0; - - if (pdata->reset_during_probe) { - err = sx150x_reset(chip); - if (err < 0) - return err; - } - - if (chip->dev_cfg->model == SX150X_789) - err = sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x789.reg_misc, - 0x01); - else if (chip->dev_cfg->model == SX150X_456) - err = sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x456.reg_advance, - 0x04); - else - err = sx150x_i2c_write(chip->client, - chip->dev_cfg->pri.x123.reg_advance, - 0x00); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup, - pdata->io_pullup_ena); - if (err < 0) - return err; - - err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn, - pdata->io_pulldn_ena); - if (err < 0) - return err; - - if (chip->dev_cfg->model == SX150X_789) { - err = sx150x_init_io(chip, - chip->dev_cfg->pri.x789.reg_polarity, - pdata->io_polarity); - if (err < 0) - return err; - } else if (chip->dev_cfg->model == SX150X_456) { - /* Set all pins to work in normal mode */ - err = sx150x_init_io(chip, - chip->dev_cfg->pri.x456.reg_pld_mode, - 0); - if (err < 0) - return err; - } else { - /* Set all pins to work in normal mode */ - err = sx150x_init_io(chip, - chip->dev_cfg->pri.x123.reg_pld_mode, - 0); - if (err < 0) - return err; - } - - - if (pdata->oscio_is_gpo) - sx150x_set_oscio(chip, 0); - - return err; -} - -static int sx150x_install_irq_chip(struct sx150x_chip *chip, - int irq_summary, - int irq_base) -{ - int err; - - chip->irq_summary = irq_summary; - chip->irq_base = irq_base; - - /* Add gpio chip to irq subsystem */ - err = gpiochip_irqchip_add(&chip->gpio_chip, - &chip->irq_chip, chip->irq_base, - handle_edge_irq, IRQ_TYPE_EDGE_BOTH); - if (err) { - dev_err(&chip->client->dev, - "could not connect irqchip to gpiochip\n"); - return err; - } - - err = devm_request_threaded_irq(&chip->client->dev, - irq_summary, NULL, sx150x_irq_thread_fn, - IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING, - chip->irq_chip.name, chip); - if (err < 0) { - chip->irq_summary = -1; - chip->irq_base = -1; - } - - return err; -} - -static int sx150x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_WORD_DATA; - struct sx150x_platform_data *pdata; - struct sx150x_chip *chip; - int rc; - - pdata = dev_get_platdata(&client->dev); - if (!pdata) - return -EINVAL; - - if (!i2c_check_functionality(client->adapter, i2c_funcs)) - return -ENOSYS; - - chip = devm_kzalloc(&client->dev, - sizeof(struct sx150x_chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - sx150x_init_chip(chip, client, id->driver_data, pdata); - rc = sx150x_init_hw(chip, pdata); - if (rc < 0) - return rc; - - rc = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); - if (rc) - return rc; - - if (pdata->irq_summary >= 0) { - rc = sx150x_install_irq_chip(chip, - pdata->irq_summary, - pdata->irq_base); - if (rc < 0) - return rc; - } - - i2c_set_clientdata(client, chip); - - return 0; -} - -static struct i2c_driver sx150x_driver = { - .driver = { - .name = "sx150x", - .of_match_table = of_match_ptr(sx150x_of_match), - }, - .probe = sx150x_probe, - .id_table = sx150x_id, -}; - -static int __init sx150x_init(void) -{ - return i2c_add_driver(&sx150x_driver); -} -subsys_initcall(sx150x_init); diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 3edb09cb9ee0..521fbe338589 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -283,8 +283,4 @@ static struct platform_driver vf610_gpio_driver = { .probe = vf610_gpio_probe, }; -static int __init gpio_vf610_init(void) -{ - return platform_driver_register(&vf610_gpio_driver); -} -device_initcall(gpio_vf610_init); +builtin_platform_driver(vf610_gpio_driver); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 58ece201b8e6..fec93b994fe9 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -468,7 +468,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, int ret; memset(&args, 0, sizeof(args)); - ret = acpi_node_get_property_reference(fwnode, propname, index, &args); + ret = __acpi_node_get_property_reference(fwnode, propname, index, 3, + &args); if (ret) { struct acpi_device *adev = to_acpi_device_node(fwnode); @@ -483,13 +484,13 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, * on returned args. */ lookup->adev = args.adev; - if (args.nargs >= 2) { - lookup->index = args.args[0]; - lookup->pin_index = args.args[1]; - /* 3rd argument, if present is used to specify active_low. */ - if (args.nargs >= 3) - lookup->active_low = !!args.args[2]; - } + if (args.nargs != 3) + return -EPROTO; + + lookup->index = args.args[0]; + lookup->pin_index = args.args[1]; + lookup->active_low = !!args.args[2]; + return 0; } @@ -856,6 +857,77 @@ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip) } } +static struct gpio_desc *acpi_gpiochip_parse_own_gpio( + struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode, + const char **name, unsigned int *lflags, unsigned int *dflags) +{ + struct gpio_chip *chip = achip->chip; + struct gpio_desc *desc; + u32 gpios[2]; + int ret; + + *lflags = 0; + *dflags = 0; + *name = NULL; + + ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios, + ARRAY_SIZE(gpios)); + if (ret < 0) + return ERR_PTR(ret); + + ret = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, gpios[0]); + if (ret < 0) + return ERR_PTR(ret); + + desc = gpiochip_get_desc(chip, ret); + if (IS_ERR(desc)) + return desc; + + if (gpios[1]) + *lflags |= GPIO_ACTIVE_LOW; + + if (fwnode_property_present(fwnode, "input")) + *dflags |= GPIOD_IN; + else if (fwnode_property_present(fwnode, "output-low")) + *dflags |= GPIOD_OUT_LOW; + else if (fwnode_property_present(fwnode, "output-high")) + *dflags |= GPIOD_OUT_HIGH; + else + return ERR_PTR(-EINVAL); + + fwnode_property_read_string(fwnode, "line-name", name); + + return desc; +} + +static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) +{ + struct gpio_chip *chip = achip->chip; + struct fwnode_handle *fwnode; + + device_for_each_child_node(chip->parent, fwnode) { + unsigned int lflags, dflags; + struct gpio_desc *desc; + const char *name; + int ret; + + if (!fwnode_property_present(fwnode, "gpio-hog")) + continue; + + desc = acpi_gpiochip_parse_own_gpio(achip, fwnode, &name, + &lflags, &dflags); + if (IS_ERR(desc)) + continue; + + ret = gpiod_hog(desc, name, lflags, dflags); + if (ret) { + dev_err(chip->parent, "Failed to hog GPIO\n"); + fwnode_handle_put(fwnode); + return; + } + } +} + void acpi_gpiochip_add(struct gpio_chip *chip) { struct acpi_gpio_chip *acpi_gpio; @@ -886,7 +958,11 @@ void acpi_gpiochip_add(struct gpio_chip *chip) return; } + if (!chip->names) + devprop_gpiochip_set_names(chip); + acpi_gpiochip_request_regions(acpi_gpio); + acpi_gpiochip_scan_gpios(acpi_gpio); acpi_walk_dep_device_list(handle); } @@ -915,18 +991,27 @@ void acpi_gpiochip_remove(struct gpio_chip *chip) kfree(acpi_gpio); } -static unsigned int acpi_gpio_package_count(const union acpi_object *obj) +static int acpi_gpio_package_count(const union acpi_object *obj) { const union acpi_object *element = obj->package.elements; const union acpi_object *end = element + obj->package.count; unsigned int count = 0; while (element < end) { - if (element->type == ACPI_TYPE_LOCAL_REFERENCE) + switch (element->type) { + case ACPI_TYPE_LOCAL_REFERENCE: + element += 3; + /* Fallthrough */ + case ACPI_TYPE_INTEGER: + element++; count++; + break; - element++; + default: + return -EPROTO; + } } + return count; } diff --git a/drivers/gpio/gpiolib-devprop.c b/drivers/gpio/gpiolib-devprop.c new file mode 100644 index 000000000000..27f383bda7d9 --- /dev/null +++ b/drivers/gpio/gpiolib-devprop.c @@ -0,0 +1,67 @@ +/* + * Device property helpers for GPIO chips. + * + * Copyright (C) 2016, Intel Corporation + * Author: Mika Westerberg <mika.westerberg@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/property.h> +#include <linux/slab.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/driver.h> + +#include "gpiolib.h" + +/** + * devprop_gpiochip_set_names - Set GPIO line names using device properties + * @chip: GPIO chip whose lines should be named, if possible + * + * Looks for device property "gpio-line-names" and if it exists assigns + * GPIO line names for the chip. The memory allocated for the assigned + * names belong to the underlying firmware node and should not be released + * by the caller. + */ +void devprop_gpiochip_set_names(struct gpio_chip *chip) +{ + struct gpio_device *gdev = chip->gpiodev; + const char **names; + int ret, i; + + if (!chip->parent) { + dev_warn(&gdev->dev, "GPIO chip parent is NULL\n"); + return; + } + + ret = device_property_read_string_array(chip->parent, "gpio-line-names", + NULL, 0); + if (ret < 0) + return; + + if (ret != gdev->ngpio) { + dev_warn(chip->parent, + "names %d do not match number of GPIOs %d\n", ret, + gdev->ngpio); + return; + } + + names = kcalloc(gdev->ngpio, sizeof(*names), GFP_KERNEL); + if (!names) + return; + + ret = device_property_read_string_array(chip->parent, "gpio-line-names", + names, gdev->ngpio); + if (ret < 0) { + dev_warn(chip->parent, "failed to read GPIO line names\n"); + kfree(names); + return; + } + + for (i = 0; i < gdev->ngpio; i++) + gdev->descs[i].name = names[i]; + + kfree(names); +} diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index ecad3f0e3b77..5236966b1bdf 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -222,51 +222,6 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, } /** - * of_gpiochip_set_names() - set up the names of the lines - * @chip: GPIO chip whose lines should be named, if possible - */ -static void of_gpiochip_set_names(struct gpio_chip *gc) -{ - struct gpio_device *gdev = gc->gpiodev; - struct device_node *np = gc->of_node; - int i; - int nstrings; - - nstrings = of_property_count_strings(np, "gpio-line-names"); - if (nstrings <= 0) - /* Lines names not present */ - return; - - /* This is normally not what you want */ - if (gdev->ngpio != nstrings) - dev_info(&gdev->dev, "gpio-line-names specifies %d line " - "names but there are %d lines on the chip\n", - nstrings, gdev->ngpio); - - /* - * Make sure to not index beyond the end of the number of descriptors - * of the GPIO device. - */ - for (i = 0; i < gdev->ngpio; i++) { - const char *name; - int ret; - - ret = of_property_read_string_index(np, - "gpio-line-names", - i, - &name); - if (ret) { - if (ret != -ENODATA) - dev_err(&gdev->dev, - "unable to name line %d: %d\n", - i, ret); - break; - } - gdev->descs[i].name = name; - } -} - -/** * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions * @chip: gpio chip to act on * @@ -292,8 +247,10 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) continue; ret = gpiod_hog(desc, name, lflags, dflags); - if (ret < 0) + if (ret < 0) { + of_node_put(np); return ret; + } } return 0; @@ -522,7 +479,7 @@ int of_gpiochip_add(struct gpio_chip *chip) /* If the chip defines names itself, these take precedence */ if (!chip->names) - of_gpiochip_set_names(chip); + devprop_gpiochip_set_names(chip); of_node_get(chip->of_node); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f0fc3a0d37c8..0e29cb745648 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -913,7 +913,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp) return -ENODEV; get_device(&gdev->dev); filp->private_data = gdev; - return 0; + + return nonseekable_open(inode, filp); } /** @@ -938,7 +939,7 @@ static const struct file_operations gpio_fileops = { .release = gpio_chrdev_release, .open = gpio_chrdev_open, .owner = THIS_MODULE, - .llseek = noop_llseek, + .llseek = no_llseek, .unlocked_ioctl = gpio_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = gpio_ioctl_compat, @@ -2150,6 +2151,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input); static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) { struct gpio_chip *gc = desc->gdev->chip; + int val = !!value; int ret; /* GPIOs used for IRQs shall not be set as output */ @@ -2169,7 +2171,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) goto set_output_value; } /* Emulate open drain by not actively driving the line high */ - if (value) + if (val) return gpiod_direction_input(desc); } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { @@ -2180,7 +2182,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) goto set_output_value; } /* Emulate open source by not actively driving the line low */ - if (!value) + if (!val) return gpiod_direction_input(desc); } else { /* Make sure to disable open drain/source hardware, if any */ @@ -2198,10 +2200,10 @@ set_output_value: return -EIO; } - ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), value); + ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), val); if (!ret) set_bit(FLAG_IS_OUT, &desc->flags); - trace_gpio_value(desc_to_gpio(desc), 0, value); + trace_gpio_value(desc_to_gpio(desc), 0, val); trace_gpio_direction(desc_to_gpio(desc), 0, ret); return ret; } @@ -2241,6 +2243,8 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) VALIDATE_DESC(desc); if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) value = !value; + else + value = !!value; return _gpiod_direction_output_raw(desc, value); } EXPORT_SYMBOL_GPL(gpiod_direction_output); @@ -2682,6 +2686,15 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) } set_bit(FLAG_USED_AS_IRQ, &desc->flags); + + /* + * If the consumer has not set up a label (such as when the + * IRQ is referenced from .to_irq()) we set up a label here + * so it is clear this is used as an interrupt. + */ + if (!desc->label) + desc_set_label(desc, "interrupt"); + return 0; } EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq); @@ -2696,10 +2709,17 @@ EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq); */ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) { - if (offset >= chip->ngpio) + struct gpio_desc *desc; + + desc = gpiochip_get_desc(chip, offset); + if (IS_ERR(desc)) return; - clear_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags); + clear_bit(FLAG_USED_AS_IRQ, &desc->flags); + + /* If we only had this marking, erase it */ + if (desc->label && !strcmp(desc->label, "interrupt")) + desc_set_label(desc, NULL); } EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq); @@ -3094,7 +3114,7 @@ static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, /* Process flags */ if (dflags & GPIOD_FLAGS_BIT_DIR_OUT) status = gpiod_direction_output(desc, - dflags & GPIOD_FLAGS_BIT_DIR_VAL); + !!(dflags & GPIOD_FLAGS_BIT_DIR_VAL)); else status = gpiod_direction_input(desc); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 346fbda39220..d10eaf520860 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -209,6 +209,8 @@ static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc) return desc - &desc->gdev->descs[0]; } +void devprop_gpiochip_set_names(struct gpio_chip *chip); + /* With descriptor prefix */ #define gpiod_emerg(desc, fmt, ...) \ |