summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-pca953x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-pca953x.c')
-rw-r--r--drivers/gpio/gpio-pca953x.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index f6b870b7b352..aac9ea7520b6 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -604,20 +604,28 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *
return 0;
}
-static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+static int pca953x_gpio_direction_input_unlocked(struct gpio_chip *gc,
+ unsigned int off)
{
struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off);
u8 bit = pca953x_get_bit_mask(chip, off);
- guard(mutex)(&chip->i2c_lock);
-
if (PCA_CHIP_TYPE(chip->driver_data) == TCA6418_TYPE)
return regmap_update_bits(chip->regmap, dirreg, bit, 0);
return regmap_update_bits(chip->regmap, dirreg, bit, bit);
}
+static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
+{
+ struct pca953x_chip *chip = gpiochip_get_data(gc);
+
+ guard(mutex)(&chip->i2c_lock);
+
+ return pca953x_gpio_direction_input_unlocked(gc, off);
+}
+
static int pca953x_gpio_direction_output(struct gpio_chip *gc,
unsigned off, int val)
{
@@ -855,9 +863,10 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
DECLARE_BITMAP(reg_direction, MAX_LINE);
int level;
+ guard(mutex)(&chip->i2c_lock);
+
if (chip->driver_data & PCA_PCAL) {
DECLARE_BITMAP(latched_inputs, MAX_LINE);
- guard(mutex)(&chip->i2c_lock);
/* Enable latch on edge-triggered interrupt-enabled inputs */
bitmap_or(latched_inputs, chip->irq_trig_fall, chip->irq_trig_raise, gc->ngpio);
@@ -879,7 +888,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
/* Look for any newly setup interrupt */
for_each_andnot_bit(level, irq_mask, reg_direction, gc->ngpio)
- pca953x_gpio_direction_input(&chip->gpio_chip, level);
+ pca953x_gpio_direction_input_unlocked(&chip->gpio_chip, level);
mutex_unlock(&chip->irq_lock);
}
@@ -1369,9 +1378,20 @@ static int pca953x_restore_context(struct pca953x_chip *chip)
regcache_mark_dirty(chip->regmap);
ret = pca953x_regcache_sync(chip);
if (ret)
- return ret;
+ goto err;
+
+ ret = regcache_sync(chip->regmap);
+ if (ret)
+ goto err;
+
+ return 0;
- return regcache_sync(chip->regmap);
+err:
+ if (chip->client->irq > 0)
+ disable_irq(chip->client->irq);
+ regcache_cache_only(chip->regmap, true);
+
+ return ret;
}
static void pca953x_save_context(struct pca953x_chip *chip)