diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 9 | ||||
-rw-r--r-- | drivers/gpio/gpio-104-dio-48e.c | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-104-idi-48.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-bcm-kona.c | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-lpc32xx.c | 48 | ||||
-rw-r--r-- | drivers/gpio/gpio-zynq.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 78 |
8 files changed, 80 insertions, 72 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 48da857f4774..cebcb405812e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -33,6 +33,7 @@ config ARCH_REQUIRE_GPIOLIB menuconfig GPIOLIB bool "GPIO Support" + select ANON_INODES help This enables GPIO support through the generic GPIO library. You only need to enable this, if you also want to enable @@ -530,7 +531,7 @@ menu "Port-mapped I/O GPIO drivers" config GPIO_104_DIO_48E tristate "ACCES 104-DIO-48E GPIO support" - depends on ISA + depends on ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E, @@ -540,7 +541,7 @@ config GPIO_104_DIO_48E config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" - depends on ISA + depends on ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, @@ -551,7 +552,7 @@ config GPIO_104_IDIO_16 config GPIO_104_IDI_48 tristate "ACCES 104-IDI-48 GPIO support" - depends on ISA + depends on ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A, @@ -627,7 +628,7 @@ config GPIO_TS5500 config GPIO_WS16C48 tristate "WinSystems WS16C48 GPIO support" - depends on ISA + depends on ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the WinSystems WS16C48. The base port diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 1a647c07be67..fcf776971ca9 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -75,7 +75,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); const unsigned io_port = offset / 8; - const unsigned control_port = io_port / 2; + const unsigned int control_port = io_port / 3; const unsigned control_addr = dio48egpio->base + 3 + control_port*4; unsigned long flags; unsigned control; @@ -115,7 +115,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset, { struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); const unsigned io_port = offset / 8; - const unsigned control_port = io_port / 2; + const unsigned int control_port = io_port / 3; const unsigned mask = BIT(offset % 8); const unsigned control_addr = dio48egpio->base + 3 + control_port*4; const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port; diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index 6c75c83baf5a..2d2763ea1a68 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -247,6 +247,7 @@ static int idi_48_probe(struct device *dev, unsigned int id) idi48gpio->irq = irq[id]; spin_lock_init(&idi48gpio->lock); + spin_lock_init(&idi48gpio->ack_lock); dev_set_drvdata(dev, idi48gpio); diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 9aabc48ff5de..953e4b829e32 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -547,11 +547,11 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio) /* disable interrupts and clear status */ for (i = 0; i < kona_gpio->num_bank; i++) { /* Unlock the entire bank first */ - bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE); + bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE); writel(0xffffffff, reg_base + GPIO_INT_MASK(i)); writel(0xffffffff, reg_base + GPIO_INT_STATUS(i)); /* Now re-lock the bank */ - bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE); + bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE); } } diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index d39014daeef9..fc5f197906ac 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -29,7 +29,6 @@ #include <mach/hardware.h> #include <mach/platform.h> -#include <mach/irqs.h> #define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) #define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) @@ -371,61 +370,16 @@ static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin) static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset) { - return IRQ_LPC32XX_P0_P1_IRQ; + return -ENXIO; } -static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = { - IRQ_LPC32XX_GPIO_00, - IRQ_LPC32XX_GPIO_01, - IRQ_LPC32XX_GPIO_02, - IRQ_LPC32XX_GPIO_03, - IRQ_LPC32XX_GPIO_04, - IRQ_LPC32XX_GPIO_05, -}; - static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset) { - if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table)) - return lpc32xx_gpio_to_irq_gpio_p3_table[offset]; return -ENXIO; } -static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = { - IRQ_LPC32XX_GPI_00, - IRQ_LPC32XX_GPI_01, - IRQ_LPC32XX_GPI_02, - IRQ_LPC32XX_GPI_03, - IRQ_LPC32XX_GPI_04, - IRQ_LPC32XX_GPI_05, - IRQ_LPC32XX_GPI_06, - IRQ_LPC32XX_GPI_07, - IRQ_LPC32XX_GPI_08, - IRQ_LPC32XX_GPI_09, - -ENXIO, /* 10 */ - -ENXIO, /* 11 */ - -ENXIO, /* 12 */ - -ENXIO, /* 13 */ - -ENXIO, /* 14 */ - -ENXIO, /* 15 */ - -ENXIO, /* 16 */ - -ENXIO, /* 17 */ - -ENXIO, /* 18 */ - IRQ_LPC32XX_GPI_19, - -ENXIO, /* 20 */ - -ENXIO, /* 21 */ - -ENXIO, /* 22 */ - -ENXIO, /* 23 */ - -ENXIO, /* 24 */ - -ENXIO, /* 25 */ - -ENXIO, /* 26 */ - -ENXIO, /* 27 */ - IRQ_LPC32XX_GPI_28, -}; - static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset) { - if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table)) - return lpc32xx_gpio_to_irq_gpi_p3_table[offset]; return -ENXIO; } diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 75c6355b018d..e72794e463aa 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -709,7 +709,13 @@ static int zynq_gpio_probe(struct platform_device *pdev) dev_err(&pdev->dev, "input clock not found.\n"); return PTR_ERR(gpio->clk); } + ret = clk_prepare_enable(gpio->clk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable clock.\n"); + return ret; + } + pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) @@ -747,6 +753,7 @@ err_pm_put: pm_runtime_put(&pdev->dev); err_pm_dis: pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(gpio->clk); return ret; } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index d22dcc38179d..4aabddb38b59 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -16,6 +16,7 @@ #include <linux/errno.h> #include <linux/module.h> #include <linux/io.h> +#include <linux/io-mapping.h> #include <linux/gpio/consumer.h> #include <linux/of.h> #include <linux/of_address.h> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d407f904a31c..570771ed19e6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -20,6 +20,7 @@ #include <linux/cdev.h> #include <linux/fs.h> #include <linux/uaccess.h> +#include <linux/compat.h> #include <uapi/linux/gpio.h> #include "gpiolib.h" @@ -316,7 +317,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct gpio_device *gdev = filp->private_data; struct gpio_chip *chip = gdev->chip; - int __user *ip = (int __user *)arg; + void __user *ip = (void __user *)arg; /* We fail any subsequent ioctl():s when the chip is gone */ if (!chip) @@ -388,6 +389,14 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -EINVAL; } +#ifdef CONFIG_COMPAT +static long gpio_ioctl_compat(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + return gpio_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + /** * gpio_chrdev_open() - open the chardev for ioctl operations * @inode: inode for this chardev @@ -431,14 +440,15 @@ static const struct file_operations gpio_fileops = { .owner = THIS_MODULE, .llseek = noop_llseek, .unlocked_ioctl = gpio_ioctl, - .compat_ioctl = gpio_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gpio_ioctl_compat, +#endif }; static void gpiodevice_release(struct device *dev) { struct gpio_device *gdev = dev_get_drvdata(dev); - cdev_del(&gdev->chrdev); list_del(&gdev->list); ida_simple_remove(&gpio_ida, gdev->id); kfree(gdev->label); @@ -471,7 +481,6 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) /* From this point, the .release() function cleans up gpio_device */ gdev->dev.release = gpiodevice_release; - get_device(&gdev->dev); pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n", __func__, gdev->base, gdev->base + gdev->ngpio - 1, dev_name(&gdev->dev), gdev->chip->label ? : "generic"); @@ -618,6 +627,8 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) goto err_free_label; } + spin_unlock_irqrestore(&gpio_lock, flags); + for (i = 0; i < chip->ngpio; i++) { struct gpio_desc *desc = &gdev->descs[i]; @@ -649,8 +660,6 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) } } - spin_unlock_irqrestore(&gpio_lock, flags); - #ifdef CONFIG_PINCTRL INIT_LIST_HEAD(&gdev->pin_ranges); #endif @@ -759,6 +768,8 @@ void gpiochip_remove(struct gpio_chip *chip) * be removed, else it will be dangling until the last user is * gone. */ + cdev_del(&gdev->chrdev); + device_del(&gdev->dev); put_device(&gdev->dev); } EXPORT_SYMBOL_GPL(gpiochip_remove); @@ -858,7 +869,7 @@ struct gpio_chip *gpiochip_find(void *data, spin_lock_irqsave(&gpio_lock, flags); list_for_each_entry(gdev, &gpio_devices, list) - if (match(gdev->chip, data)) + if (gdev->chip && match(gdev->chip, data)) break; /* No match? */ @@ -1356,11 +1367,18 @@ done: /* * This descriptor validation needs to be inserted verbatim into each * function taking a descriptor, so we need to use a preprocessor - * macro to avoid endless duplication. + * macro to avoid endless duplication. If the desc is NULL it is an + * optional GPIO and calls should just bail out. */ #define VALIDATE_DESC(desc) do { \ - if (!desc || !desc->gdev) { \ - pr_warn("%s: invalid GPIO\n", __func__); \ + if (!desc) \ + return 0; \ + if (IS_ERR(desc)) { \ + pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \ + return PTR_ERR(desc); \ + } \ + if (!desc->gdev) { \ + pr_warn("%s: invalid GPIO (no device)\n", __func__); \ return -EINVAL; \ } \ if ( !desc->gdev->chip ) { \ @@ -1370,8 +1388,14 @@ done: } } while (0) #define VALIDATE_DESC_VOID(desc) do { \ - if (!desc || !desc->gdev) { \ - pr_warn("%s: invalid GPIO\n", __func__); \ + if (!desc) \ + return; \ + if (IS_ERR(desc)) { \ + pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \ + return; \ + } \ + if (!desc->gdev) { \ + pr_warn("%s: invalid GPIO (no device)\n", __func__); \ return; \ } \ if (!desc->gdev->chip) { \ @@ -2040,7 +2064,14 @@ int gpiod_to_irq(const struct gpio_desc *desc) struct gpio_chip *chip; int offset; - VALIDATE_DESC(desc); + /* + * Cannot VALIDATE_DESC() here as gpiod_to_irq() consumer semantics + * requires this function to not return zero on an invalid descriptor + * but rather a negative error number. + */ + if (!desc || IS_ERR(desc) || !desc->gdev || !desc->gdev->chip) + return -EINVAL; + chip = desc->gdev->chip; offset = gpio_chip_hwgpio(desc); if (chip->to_irq) { @@ -2066,17 +2097,30 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq); */ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) { - if (offset >= chip->ngpio) - return -EINVAL; + struct gpio_desc *desc; + + desc = gpiochip_get_desc(chip, offset); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + /* Flush direction if something changed behind our back */ + if (chip->get_direction) { + int dir = chip->get_direction(chip, offset); + + if (dir) + clear_bit(FLAG_IS_OUT, &desc->flags); + else + set_bit(FLAG_IS_OUT, &desc->flags); + } - if (test_bit(FLAG_IS_OUT, &chip->gpiodev->descs[offset].flags)) { + if (test_bit(FLAG_IS_OUT, &desc->flags)) { chip_err(chip, "%s: tried to flag a GPIO set as output for IRQ\n", __func__); return -EIO; } - set_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags); + set_bit(FLAG_USED_AS_IRQ, &desc->flags); return 0; } EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq); |