From 6e66a6599a813abfc9ebe2e295c9d557c434812a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 23 Mar 2016 19:49:41 +0800 Subject: [PATCH] gpio: tpic2810: Make sure cached buffer has consistent status with h/w status i2c_smbus_write_byte_data() can fail. To ensure the cached buffer has consistent status with h/w status, don't update the cached gpio->buffer if write fails. Also refactor the code a bit by adding a tpic2810_set_mask_bits() helper and use it to simplify the code. Signed-off-by: Axel Lin Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tpic2810.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/drivers/gpio/gpio-tpic2810.c b/drivers/gpio/gpio-tpic2810.c index 9f020aa4..cace79c 100644 --- a/drivers/gpio/gpio-tpic2810.c +++ b/drivers/gpio/gpio-tpic2810.c @@ -57,39 +57,34 @@ static int tpic2810_direction_output(struct gpio_chip *chip, return 0; } -static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value) +static void tpic2810_set_mask_bits(struct gpio_chip *chip, u8 mask, u8 bits) { struct tpic2810 *gpio = gpiochip_get_data(chip); + u8 buffer; + int err; mutex_lock(&gpio->lock); - if (value) - gpio->buffer |= BIT(offset); - else - gpio->buffer &= ~BIT(offset); + buffer = gpio->buffer & ~mask; + buffer |= (mask & bits); - i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, - gpio->buffer); + err = i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, + buffer); + if (!err) + gpio->buffer = buffer; mutex_unlock(&gpio->lock); } +static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value) +{ + tpic2810_set_mask_bits(chip, BIT(offset), value ? BIT(offset) : 0); +} + static void tpic2810_set_multiple(struct gpio_chip *chip, unsigned long *mask, unsigned long *bits) { - struct tpic2810 *gpio = gpiochip_get_data(chip); - - mutex_lock(&gpio->lock); - - /* clear bits under mask */ - gpio->buffer &= ~(*mask); - /* set bits under mask */ - gpio->buffer |= ((*mask) & (*bits)); - - i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND, - gpio->buffer); - - mutex_unlock(&gpio->lock); + tpic2810_set_mask_bits(chip, *mask, *bits); } static struct gpio_chip template_chip = { -- 2.7.4