diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 15 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-ab8500.c | 520 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 18 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-palmas.c | 184 | ||||
-rw-r--r-- | drivers/gpio/gpio-samsung.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpio-spear-spics.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpio-stp-xway.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-tegra.c | 9 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 37 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 2 |
12 files changed, 223 insertions, 597 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ab97eb80537..93aaadf99f2 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -69,7 +69,7 @@ config DEBUG_GPIO config GPIO_SYSFS bool "/sys/class/gpio/... (sysfs interface)" - depends on SYSFS && EXPERIMENTAL + depends on SYSFS help Say Y here to add a sysfs interface for GPIOs. @@ -280,7 +280,7 @@ config GPIO_ICH config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" - depends on PCI + depends on PCI && GENERIC_HARDIRQS select MFD_CORE select MFD_VX855 help @@ -610,7 +610,7 @@ config GPIO_TIMBERDALE config GPIO_RDC321X tristate "RDC R-321x GPIO support" - depends on PCI + depends on PCI && GENERIC_HARDIRQS select MFD_CORE select MFD_RDC321X help @@ -668,11 +668,12 @@ config GPIO_JANZ_TTL This driver provides support for driving the pins in output mode only. Input mode is not supported. -config GPIO_AB8500 - bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions" - depends on AB8500_CORE && BROKEN +config GPIO_PALMAS + bool "TI PALMAS series PMICs GPIO" + depends on MFD_PALMAS help - Select this to enable the AB8500 IC GPIO driver + Select this option to enable GPIO driver for the TI PALMAS + series chip family. config GPIO_TPS6586X bool "TPS6586X GPIO" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4398034db4a..22e07bc9fcb 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o -obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o @@ -71,6 +70,7 @@ obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o +obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c deleted file mode 100644 index 983ad425f0a..00000000000 --- a/drivers/gpio/gpio-ab8500.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * Author: BIBEK BASU <bibek.basu@stericsson.com> - * License terms: GNU General Public License (GPL) version 2 - * - * 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/kernel.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/mfd/ab8500.h> -#include <linux/mfd/abx500.h> -#include <linux/mfd/ab8500/gpio.h> - -/* - * GPIO registers offset - * Bank: 0x10 - */ -#define AB8500_GPIO_SEL1_REG 0x00 -#define AB8500_GPIO_SEL2_REG 0x01 -#define AB8500_GPIO_SEL3_REG 0x02 -#define AB8500_GPIO_SEL4_REG 0x03 -#define AB8500_GPIO_SEL5_REG 0x04 -#define AB8500_GPIO_SEL6_REG 0x05 - -#define AB8500_GPIO_DIR1_REG 0x10 -#define AB8500_GPIO_DIR2_REG 0x11 -#define AB8500_GPIO_DIR3_REG 0x12 -#define AB8500_GPIO_DIR4_REG 0x13 -#define AB8500_GPIO_DIR5_REG 0x14 -#define AB8500_GPIO_DIR6_REG 0x15 - -#define AB8500_GPIO_OUT1_REG 0x20 -#define AB8500_GPIO_OUT2_REG 0x21 -#define AB8500_GPIO_OUT3_REG 0x22 -#define AB8500_GPIO_OUT4_REG 0x23 -#define AB8500_GPIO_OUT5_REG 0x24 -#define AB8500_GPIO_OUT6_REG 0x25 - -#define AB8500_GPIO_PUD1_REG 0x30 -#define AB8500_GPIO_PUD2_REG 0x31 -#define AB8500_GPIO_PUD3_REG 0x32 -#define AB8500_GPIO_PUD4_REG 0x33 -#define AB8500_GPIO_PUD5_REG 0x34 -#define AB8500_GPIO_PUD6_REG 0x35 - -#define AB8500_GPIO_IN1_REG 0x40 -#define AB8500_GPIO_IN2_REG 0x41 -#define AB8500_GPIO_IN3_REG 0x42 -#define AB8500_GPIO_IN4_REG 0x43 -#define AB8500_GPIO_IN5_REG 0x44 -#define AB8500_GPIO_IN6_REG 0x45 -#define AB8500_GPIO_ALTFUN_REG 0x45 -#define ALTFUN_REG_INDEX 6 -#define AB8500_NUM_GPIO 42 -#define AB8500_NUM_VIR_GPIO_IRQ 16 - -enum ab8500_gpio_action { - NONE, - STARTUP, - SHUTDOWN, - MASK, - UNMASK -}; - -struct ab8500_gpio { - struct gpio_chip chip; - struct ab8500 *parent; - struct device *dev; - struct mutex lock; - u32 irq_base; - enum ab8500_gpio_action irq_action; - u16 rising; - u16 falling; -}; -/** - * to_ab8500_gpio() - get the pointer to ab8500_gpio - * @chip: Member of the structure ab8500_gpio - */ -static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct ab8500_gpio, chip); -} - -static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg, - unsigned offset, int val) -{ - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - u8 pos = offset % 8; - int ret; - - reg = reg + (offset / 8); - ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev, - AB8500_MISC, reg, 1 << pos, val << pos); - if (ret < 0) - dev_err(ab8500_gpio->dev, "%s write failed\n", __func__); - return ret; -} -/** - * ab8500_gpio_get() - Get the particular GPIO value - * @chip: Gpio device - * @offset: GPIO number to read - */ -static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - u8 mask = 1 << (offset % 8); - u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8); - int ret; - u8 data; - ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC, - reg, &data); - if (ret < 0) { - dev_err(ab8500_gpio->dev, "%s read failed\n", __func__); - return ret; - } - return (data & mask) >> (offset % 8); -} - -static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) -{ - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - int ret; - /* Write the data */ - ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1); - if (ret < 0) - dev_err(ab8500_gpio->dev, "%s write failed\n", __func__); -} - -static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int val) -{ - int ret; - /* set direction as output */ - ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1); - if (ret < 0) - return ret; - /* disable pull down */ - ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1); - if (ret < 0) - return ret; - /* set the output as 1 or 0 */ - return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val); - -} - -static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - /* set the register as input */ - return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0); -} - -static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - /* - * Only some GPIOs are interrupt capable, and they are - * organized in discontiguous clusters: - * - * GPIO6 to GPIO13 - * GPIO24 and GPIO25 - * GPIO36 to GPIO41 - */ - static struct ab8500_gpio_irq_cluster { - int start; - int end; - } clusters[] = { - {.start = 6, .end = 13}, - {.start = 24, .end = 25}, - {.start = 36, .end = 41}, - }; - struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip); - int base = ab8500_gpio->irq_base; - int i; - - for (i = 0; i < ARRAY_SIZE(clusters); i++) { - struct ab8500_gpio_irq_cluster *cluster = &clusters[i]; - - if (offset >= cluster->start && offset <= cluster->end) - return base + offset - cluster->start; - - /* Advance by the number of gpios in this cluster */ - base += cluster->end - cluster->start + 1; - } - - return -EINVAL; -} - -static struct gpio_chip ab8500gpio_chip = { - .label = "ab8500_gpio", - .owner = THIS_MODULE, - .direction_input = ab8500_gpio_direction_input, - .get = ab8500_gpio_get, - .direction_output = ab8500_gpio_direction_output, - .set = ab8500_gpio_set, - .to_irq = ab8500_gpio_to_irq, -}; - -static unsigned int irq_to_rising(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - int new_irq = offset + AB8500_INT_GPIO6R - + ab8500_gpio->parent->irq_base; - return new_irq; -} - -static unsigned int irq_to_falling(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - int new_irq = offset + AB8500_INT_GPIO6F - + ab8500_gpio->parent->irq_base; - return new_irq; - -} - -static unsigned int rising_to_irq(unsigned int irq, void *dev) -{ - struct ab8500_gpio *ab8500_gpio = dev; - int offset = irq - AB8500_INT_GPIO6R - - ab8500_gpio->parent->irq_base ; - int new_irq = offset + ab8500_gpio->irq_base; - return new_irq; -} - -static unsigned int falling_to_irq(unsigned int irq, void *dev) -{ - struct ab8500_gpio *ab8500_gpio = dev; - int offset = irq - AB8500_INT_GPIO6F - - ab8500_gpio->parent->irq_base ; - int new_irq = offset + ab8500_gpio->irq_base; - return new_irq; - -} - -/* - * IRQ handler - */ - -static irqreturn_t handle_rising(int irq, void *dev) -{ - - handle_nested_irq(rising_to_irq(irq , dev)); - return IRQ_HANDLED; -} - -static irqreturn_t handle_falling(int irq, void *dev) -{ - - handle_nested_irq(falling_to_irq(irq, dev)); - return IRQ_HANDLED; -} - -static void ab8500_gpio_irq_lock(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - mutex_lock(&ab8500_gpio->lock); -} - -static void ab8500_gpio_irq_sync_unlock(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - bool rising = ab8500_gpio->rising & BIT(offset); - bool falling = ab8500_gpio->falling & BIT(offset); - int ret; - - switch (ab8500_gpio->irq_action) { - case STARTUP: - if (rising) - ret = request_threaded_irq(irq_to_rising(irq), - NULL, handle_rising, - IRQF_TRIGGER_RISING, - "ab8500-gpio-r", ab8500_gpio); - if (falling) - ret = request_threaded_irq(irq_to_falling(irq), - NULL, handle_falling, - IRQF_TRIGGER_FALLING, - "ab8500-gpio-f", ab8500_gpio); - break; - case SHUTDOWN: - if (rising) - free_irq(irq_to_rising(irq), ab8500_gpio); - if (falling) - free_irq(irq_to_falling(irq), ab8500_gpio); - break; - case MASK: - if (rising) - disable_irq(irq_to_rising(irq)); - if (falling) - disable_irq(irq_to_falling(irq)); - break; - case UNMASK: - if (rising) - enable_irq(irq_to_rising(irq)); - if (falling) - enable_irq(irq_to_falling(irq)); - break; - case NONE: - break; - } - ab8500_gpio->irq_action = NONE; - ab8500_gpio->rising &= ~(BIT(offset)); - ab8500_gpio->falling &= ~(BIT(offset)); - mutex_unlock(&ab8500_gpio->lock); -} - - -static void ab8500_gpio_irq_mask(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = MASK; -} - -static void ab8500_gpio_irq_unmask(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = UNMASK; -} - -static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - int offset = irq - ab8500_gpio->irq_base; - - if (type == IRQ_TYPE_EDGE_BOTH) { - ab8500_gpio->rising = BIT(offset); - ab8500_gpio->falling = BIT(offset); - } else if (type == IRQ_TYPE_EDGE_RISING) { - ab8500_gpio->rising = BIT(offset); - } else { - ab8500_gpio->falling = BIT(offset); - } - return 0; -} - -unsigned int ab8500_gpio_irq_startup(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = STARTUP; - return 0; -} - -void ab8500_gpio_irq_shutdown(unsigned int irq) -{ - struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq); - ab8500_gpio->irq_action = SHUTDOWN; -} - -static struct irq_chip ab8500_gpio_irq_chip = { - .name = "ab8500-gpio", - .startup = ab8500_gpio_irq_startup, - .shutdown = ab8500_gpio_irq_shutdown, - .bus_lock = ab8500_gpio_irq_lock, - .bus_sync_unlock = ab8500_gpio_irq_sync_unlock, - .mask = ab8500_gpio_irq_mask, - .unmask = ab8500_gpio_irq_unmask, - .set_type = ab8500_gpio_irq_set_type, -}; - -static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio) -{ - u32 base = ab8500_gpio->irq_base; - int irq; - - for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) { - set_irq_chip_data(irq, ab8500_gpio); - set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip, - handle_simple_irq); - set_irq_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - set_irq_noprobe(irq); -#endif - } - - return 0; -} - -static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio) -{ - int base = ab8500_gpio->irq_base; - int irq; - - for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif - set_irq_chip_and_handler(irq, NULL, NULL); - set_irq_chip_data(irq, NULL); - } -} - -static int ab8500_gpio_probe(struct platform_device *pdev) -{ - struct ab8500_platform_data *ab8500_pdata = - dev_get_platdata(pdev->dev.parent); - struct ab8500_gpio_platform_data *pdata; - struct ab8500_gpio *ab8500_gpio; - int ret; - int i; - - pdata = ab8500_pdata->gpio; - if (!pdata) { - dev_err(&pdev->dev, "gpio platform data missing\n"); - return -ENODEV; - } - - ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL); - if (ab8500_gpio == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - ab8500_gpio->dev = &pdev->dev; - ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent); - ab8500_gpio->chip = ab8500gpio_chip; - ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO; - ab8500_gpio->chip.dev = &pdev->dev; - ab8500_gpio->chip.base = pdata->gpio_base; - ab8500_gpio->irq_base = pdata->irq_base; - /* initialize the lock */ - mutex_init(&ab8500_gpio->lock); - /* - * AB8500 core will handle and clear the IRQ - * configre GPIO based on config-reg value. - * These values are for selecting the PINs as - * GPIO or alternate function - */ - for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++) { - ret = abx500_set_register_interruptible(ab8500_gpio->dev, - AB8500_MISC, i, - pdata->config_reg[i]); - if (ret < 0) - goto out_free; - } - ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC, - AB8500_GPIO_ALTFUN_REG, - pdata->config_reg[ALTFUN_REG_INDEX]); - if (ret < 0) - goto out_free; - - ret = ab8500_gpio_irq_init(ab8500_gpio); - if (ret) - goto out_free; - ret = gpiochip_add(&ab8500_gpio->chip); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", - ret); - goto out_rem_irq; - } - platform_set_drvdata(pdev, ab8500_gpio); - return 0; - -out_rem_irq: - ab8500_gpio_irq_remove(ab8500_gpio); -out_free: - mutex_destroy(&ab8500_gpio->lock); - kfree(ab8500_gpio); - return ret; -} - -/* - * ab8500_gpio_remove() - remove Ab8500-gpio driver - * @pdev : Platform device registered - */ -static int ab8500_gpio_remove(struct platform_device *pdev) -{ - struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&ab8500_gpio->chip); - if (ret < 0) { - dev_err(ab8500_gpio->dev, "unable to remove gpiochip: %d\n", - ret); - return ret; - } - - platform_set_drvdata(pdev, NULL); - mutex_destroy(&ab8500_gpio->lock); - kfree(ab8500_gpio); - - return 0; -} - -static struct platform_driver ab8500_gpio_driver = { - .driver = { - .name = "ab8500-gpio", - .owner = THIS_MODULE, - }, - .probe = ab8500_gpio_probe, - .remove = ab8500_gpio_remove, -}; - -static int __init ab8500_gpio_init(void) -{ - return platform_driver_register(&ab8500_gpio_driver); -} -arch_initcall(ab8500_gpio_init); - -static void __exit ab8500_gpio_exit(void) -{ - platform_driver_unregister(&ab8500_gpio_driver); -} -module_exit(ab8500_gpio_exit); - -MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>"); -MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins to be used as GPIO"); -MODULE_ALIAS("platform:ab8500-gpio"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 6819d63cb16..7472182967c 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -33,6 +33,7 @@ * interrupts. */ +#include <linux/err.h> #include <linux/module.h> #include <linux/gpio.h> #include <linux/irq.h> @@ -544,11 +545,9 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip->chip.of_node = np; spin_lock_init(&mvchip->lock); - mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); - if (! mvchip->membase) { - dev_err(&pdev->dev, "Cannot ioremap\n"); - return -ENOMEM; - } + mvchip->membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mvchip->membase)) + return PTR_ERR(mvchip->membase); /* The Armada XP has a second range of registers for the * per-CPU registers */ @@ -559,11 +558,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev) return -ENODEV; } - mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); - if (! mvchip->percpu_membase) { - dev_err(&pdev->dev, "Cannot ioremap\n"); - return -ENOMEM; - } + mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev, + res); + if (IS_ERR(mvchip->percpu_membase)) + return PTR_ERR(mvchip->percpu_membase); } /* diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 859b6fabc7b..25000b0f845 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -20,6 +20,7 @@ * MA 02110-1301, USA. */ +#include <linux/err.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -284,12 +285,14 @@ static int mxs_gpio_probe(struct platform_device *pdev) parent = of_get_parent(np); base = of_iomap(parent, 0); of_node_put(parent); + if (!base) + return -EADDRNOTAVAIL; } else { iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_request_and_ioremap(&pdev->dev, iores); + base = devm_ioremap_resource(&pdev->dev, iores); + if (IS_ERR(base)) + return PTR_ERR(base); } - if (!base) - return -EADDRNOTAVAIL; } port->base = base; diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c new file mode 100644 index 00000000000..e3a4e56f5a4 --- /dev/null +++ b/drivers/gpio/gpio-palmas.c @@ -0,0 +1,184 @@ +/* + * TI Palma series PMIC's GPIO driver. + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * Author: Laxman Dewangan <ldewangan@nvidia.com> + * + * 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/>. + */ + +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mfd/palmas.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +struct palmas_gpio { + struct gpio_chip gpio_chip; + struct palmas *palmas; +}; + +static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct palmas_gpio, gpio_chip); +} + +static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct palmas_gpio *pg = to_palmas_gpio(gc); + struct palmas *palmas = pg->palmas; + unsigned int val; + int ret; + + ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_IN, &val); + if (ret < 0) { + dev_err(gc->dev, "GPIO_DATA_IN read failed, err = %d\n", ret); + return ret; + } + return !!(val & BIT(offset)); +} + +static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct palmas_gpio *pg = to_palmas_gpio(gc); + struct palmas *palmas = pg->palmas; + int ret; + + if (value) + ret = palmas_write(palmas, PALMAS_GPIO_BASE, + PALMAS_GPIO_SET_DATA_OUT, BIT(offset)); + else + ret = palmas_write(palmas, PALMAS_GPIO_BASE, + PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset)); + if (ret < 0) + dev_err(gc->dev, "%s write failed, err = %d\n", + (value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT", + ret); +} + +static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct palmas_gpio *pg = to_palmas_gpio(gc); + struct palmas *palmas = pg->palmas; + int ret; + + /* Set the initial value */ + palmas_gpio_set(gc, offset, value); + + ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, + PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset)); + if (ret < 0) + dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); + return ret; +} + +static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset) +{ + struct palmas_gpio *pg = to_palmas_gpio(gc); + struct palmas *palmas = pg->palmas; + int ret; + + ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, + PALMAS_GPIO_DATA_DIR, BIT(offset), 0); + if (ret < 0) + dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); + return ret; +} + +static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +{ + struct palmas_gpio *pg = to_palmas_gpio(gc); + struct palmas *palmas = pg->palmas; + + return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset); +} + +static int palmas_gpio_probe(struct platform_device *pdev) +{ + struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); + struct palmas_platform_data *palmas_pdata; + struct palmas_gpio *palmas_gpio; + int ret; + + palmas_gpio = devm_kzalloc(&pdev->dev, + sizeof(*palmas_gpio), GFP_KERNEL); + if (!palmas_gpio) { + dev_err(&pdev->dev, "Could not allocate palmas_gpio\n"); + return -ENOMEM; + } + + palmas_gpio->palmas = palmas; + palmas_gpio->gpio_chip.owner = THIS_MODULE; + palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); + palmas_gpio->gpio_chip.ngpio = 8; + palmas_gpio->gpio_chip.can_sleep = 1; + palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; + palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; + palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; + palmas_gpio->gpio_chip.set = palmas_gpio_set; + palmas_gpio->gpio_chip.get = palmas_gpio_get; + palmas_gpio->gpio_chip.dev = &pdev->dev; +#ifdef CONFIG_OF_GPIO + palmas_gpio->gpio_chip.of_node = palmas->dev->of_node; +#endif + palmas_pdata = dev_get_platdata(palmas->dev); + if (palmas_pdata && palmas_pdata->gpio_base) + palmas_gpio->gpio_chip.base = palmas_pdata->gpio_base; + else + palmas_gpio->gpio_chip.base = -1; + + ret = gpiochip_add(&palmas_gpio->gpio_chip); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, palmas_gpio); + return ret; +} + +static int palmas_gpio_remove(struct platform_device *pdev) +{ + struct palmas_gpio *palmas_gpio = platform_get_drvdata(pdev); + + return gpiochip_remove(&palmas_gpio->gpio_chip); +} + +static struct platform_driver palmas_gpio_driver = { + .driver.name = "palmas-gpio", + .driver.owner = THIS_MODULE, + .probe = palmas_gpio_probe, + .remove = palmas_gpio_remove, +}; + +static int __init palmas_gpio_init(void) +{ + return platform_driver_register(&palmas_gpio_driver); +} +subsys_initcall(palmas_gpio_init); + +static void __exit palmas_gpio_exit(void) +{ + platform_driver_unregister(&palmas_gpio_driver); +} +module_exit(palmas_gpio_exit); + +MODULE_ALIAS("platform:palmas-gpio"); +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); +MODULE_DESCRIPTION("GPIO driver for TI Palmas series PMICs"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 76be7eed79d..b3643ff007e 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -38,7 +38,6 @@ #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> #include <plat/gpio-cfg-helpers.h> -#include <plat/gpio-fns.h> #include <plat/pm.h> int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip, @@ -3023,9 +3022,9 @@ static __init int samsung_gpiolib_init(void) */ struct device_node *pctrl_np; static const struct of_device_id exynos_pinctrl_ids[] = { - { .compatible = "samsung,pinctrl-exynos4210", }, - { .compatible = "samsung,pinctrl-exynos4x12", }, - { .compatible = "samsung,pinctrl-exynos5440", }, + { .compatible = "samsung,exynos4210-pinctrl", }, + { .compatible = "samsung,exynos4x12-pinctrl", }, + { .compatible = "samsung,exynos5440-pinctrl", }, }; for_each_matching_node(pctrl_np, exynos_pinctrl_ids) if (pctrl_np && of_device_is_available(pctrl_np)) diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index 5f45fc4ed5d..7a4bf7c0d98 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -140,11 +140,9 @@ static int spics_gpio_probe(struct platform_device *pdev) return -ENOMEM; } - spics->base = devm_request_and_ioremap(&pdev->dev, res); - if (!spics->base) { - dev_err(&pdev->dev, "request and ioremap fail\n"); - return -ENOMEM; - } + spics->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(spics->base)) + return PTR_ERR(spics->base); if (of_property_read_u32(np, "st-spics,peripcfg-reg", &spics->perip_cfg)) diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 85841ee70b1..c20e0515121 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -214,11 +214,10 @@ static int xway_stp_probe(struct platform_device *pdev) if (!chip) return -ENOMEM; - chip->virt = devm_request_and_ioremap(&pdev->dev, res); - if (!chip->virt) { - dev_err(&pdev->dev, "failed to remap STP memory\n"); - return -ENOMEM; - } + chip->virt = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(chip->virt)) + return PTR_ERR(chip->virt); + chip->gc.dev = &pdev->dev; chip->gc.label = "stp-xway"; chip->gc.direction_output = xway_stp_dir_out; diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 63cb643d4b5..414ad912232 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -17,6 +17,7 @@ * */ +#include <linux/err.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/interrupt.h> @@ -450,11 +451,9 @@ static int tegra_gpio_probe(struct platform_device *pdev) return -ENODEV; } - regs = devm_request_and_ioremap(&pdev->dev, res); - if (!regs) { - dev_err(&pdev->dev, "Couldn't ioremap regs\n"); - return -ENODEV; - } + regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); for (i = 0; i < tegra_gpio_bank_count; i++) { for (j = 0; j < 4; j++) { diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index d542a141811..a71a54a3e3f 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -89,41 +89,6 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname, EXPORT_SYMBOL(of_get_named_gpio_flags); /** - * of_gpio_named_count - Count GPIOs for a device - * @np: device node to count GPIOs for - * @propname: property name containing gpio specifier(s) - * - * The function returns the count of GPIOs specified for a node. - * - * Note that the empty GPIO specifiers counts too. For example, - * - * gpios = <0 - * &pio1 1 2 - * 0 - * &pio2 3 4>; - * - * defines four GPIOs (so this function will return 4), two of which - * are not specified. - */ -unsigned int of_gpio_named_count(struct device_node *np, const char* propname) -{ - unsigned int cnt = 0; - - do { - int ret; - - ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", - cnt, NULL); - /* A hole in the gpios = <> counts anyway. */ - if (ret < 0 && ret != -EEXIST) - break; - } while (++cnt); - - return cnt; -} -EXPORT_SYMBOL(of_gpio_named_count); - -/** * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags * @gc: pointer to the gpio_chip structure * @np: device node of the GPIO chip @@ -250,7 +215,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) * on the same GPIO chip. */ ret = gpiochip_add_pin_range(chip, - pinctrl_dev_get_name(pctldev), + pinctrl_dev_get_devname(pctldev), 0, /* offset in gpiochip */ pinspec.args[0], pinspec.args[1]); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4b3f388bcc6..4828fe7c66c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -830,7 +830,7 @@ int gpio_export(unsigned gpio, bool direction_may_change) } EXPORT_SYMBOL_GPL(gpio_export); -static int match_export(struct device *dev, void *data) +static int match_export(struct device *dev, const void *data) { return dev_get_drvdata(dev) == data; } |