diff options
Diffstat (limited to 'drivers/gpio/gpio-adnp.c')
-rw-r--r-- | drivers/gpio/gpio-adnp.c | 138 |
1 files changed, 59 insertions, 79 deletions
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index 6dafab0cf964..dc2b941c3726 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -3,11 +3,13 @@ * Copyright (C) 2011-2012 Avionic Design GmbH */ +#include <linux/cleanup.h> #include <linux/gpio/driver.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/mod_devicetable.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/property.h> #include <linux/seq_file.h> #include <linux/slab.h> @@ -78,7 +80,7 @@ static int adnp_gpio_get(struct gpio_chip *chip, unsigned offset) return (value & BIT(pos)) ? 1 : 0; } -static void __adnp_gpio_set(struct adnp *adnp, unsigned offset, int value) +static int __adnp_gpio_set(struct adnp *adnp, unsigned int offset, int value) { unsigned int reg = offset >> adnp->reg_shift; unsigned int pos = offset & 7; @@ -87,23 +89,23 @@ static void __adnp_gpio_set(struct adnp *adnp, unsigned offset, int value) err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &val); if (err < 0) - return; + return err; if (value) val |= BIT(pos); else val &= ~BIT(pos); - adnp_write(adnp, GPIO_PLR(adnp) + reg, val); + return adnp_write(adnp, GPIO_PLR(adnp) + reg, val); } -static void adnp_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int adnp_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct adnp *adnp = gpiochip_get_data(chip); - mutex_lock(&adnp->i2c_lock); - __adnp_gpio_set(adnp, offset, value); - mutex_unlock(&adnp->i2c_lock); + guard(mutex)(&adnp->i2c_lock); + + return __adnp_gpio_set(adnp, offset, value); } static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset) @@ -114,32 +116,26 @@ static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset) u8 value; int err; - mutex_lock(&adnp->i2c_lock); + guard(mutex)(&adnp->i2c_lock); err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value); if (err < 0) - goto out; + return err; value &= ~BIT(pos); err = adnp_write(adnp, GPIO_DDR(adnp) + reg, value); if (err < 0) - goto out; + return err; err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value); if (err < 0) - goto out; - - if (value & BIT(pos)) { - err = -EPERM; - goto out; - } + return err; - err = 0; + if (value & BIT(pos)) + return -EPERM; -out: - mutex_unlock(&adnp->i2c_lock); - return err; + return 0; } static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset, @@ -151,33 +147,28 @@ static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int err; u8 val; - mutex_lock(&adnp->i2c_lock); + guard(mutex)(&adnp->i2c_lock); err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val); if (err < 0) - goto out; + return err; val |= BIT(pos); err = adnp_write(adnp, GPIO_DDR(adnp) + reg, val); if (err < 0) - goto out; + return err; err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val); if (err < 0) - goto out; + return err; - if (!(val & BIT(pos))) { - err = -EPERM; - goto out; - } + if (!(val & BIT(pos))) + return -EPERM; __adnp_gpio_set(adnp, offset, value); - err = 0; -out: - mutex_unlock(&adnp->i2c_lock); - return err; + return 0; } static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) @@ -187,27 +178,26 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) int err; for (i = 0; i < num_regs; i++) { - u8 ddr, plr, ier, isr; + u8 ddr = 0, plr = 0, ier = 0, isr = 0; - mutex_lock(&adnp->i2c_lock); + scoped_guard(mutex, &adnp->i2c_lock) { + err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr); + if (err < 0) + return; - err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr); - if (err < 0) - goto unlock; + err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr); + if (err < 0) + return; - err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr); - if (err < 0) - goto unlock; + err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier); + if (err < 0) + return; - err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier); - if (err < 0) - goto unlock; - - err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr); - if (err < 0) - goto unlock; + err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr); + if (err < 0) + return; - mutex_unlock(&adnp->i2c_lock); + } for (j = 0; j < 8; j++) { unsigned int bit = (i << adnp->reg_shift) + j; @@ -232,11 +222,6 @@ static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) direction, level, interrupt, pending); } } - - return; - -unlock: - mutex_unlock(&adnp->i2c_lock); } static irqreturn_t adnp_irq(int irq, void *data) @@ -248,32 +233,24 @@ static irqreturn_t adnp_irq(int irq, void *data) for (i = 0; i < num_regs; i++) { unsigned int base = i << adnp->reg_shift, bit; - u8 changed, level, isr, ier; + u8 changed, level = 0, isr = 0, ier = 0; unsigned long pending; int err; - mutex_lock(&adnp->i2c_lock); + scoped_guard(mutex, &adnp->i2c_lock) { + err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level); + if (err < 0) + continue; - err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level); - if (err < 0) { - mutex_unlock(&adnp->i2c_lock); - continue; - } + err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr); + if (err < 0) + continue; - err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr); - if (err < 0) { - mutex_unlock(&adnp->i2c_lock); - continue; + err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier); + if (err < 0) + continue; } - err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier); - if (err < 0) { - mutex_unlock(&adnp->i2c_lock); - continue; - } - - mutex_unlock(&adnp->i2c_lock); - /* determine pins that changed levels */ changed = level ^ adnp->irq_level[i]; @@ -365,12 +342,12 @@ static void adnp_irq_bus_unlock(struct irq_data *d) struct adnp *adnp = gpiochip_get_data(gc); unsigned int num_regs = 1 << adnp->reg_shift, i; - mutex_lock(&adnp->i2c_lock); - - for (i = 0; i < num_regs; i++) - adnp_write(adnp, GPIO_IER(adnp) + i, adnp->irq_enable[i]); + scoped_guard(mutex, &adnp->i2c_lock) { + for (i = 0; i < num_regs; i++) + adnp_write(adnp, GPIO_IER(adnp) + i, + adnp->irq_enable[i]); + } - mutex_unlock(&adnp->i2c_lock); mutex_unlock(&adnp->irq_lock); } @@ -453,7 +430,7 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios, chip->direction_input = adnp_gpio_direction_input; chip->direction_output = adnp_gpio_direction_output; chip->get = adnp_gpio_get; - chip->set = adnp_gpio_set; + chip->set_rv = adnp_gpio_set; chip->can_sleep = true; if (IS_ENABLED(CONFIG_DEBUG_FS)) @@ -506,7 +483,10 @@ static int adnp_i2c_probe(struct i2c_client *client) if (!adnp) return -ENOMEM; - mutex_init(&adnp->i2c_lock); + err = devm_mutex_init(&client->dev, &adnp->i2c_lock); + if (err) + return err; + adnp->client = client; err = adnp_gpio_setup(adnp, num_gpios, device_property_read_bool(dev, "interrupt-controller")); |