]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpio/pca953x.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / gpio / pca953x.c
index 501866662e055131bc3dad3f4a5fb0b104913060..b473429eee75157a105c7144bb3cbc9dcd4d2cde 100644 (file)
@@ -60,6 +60,7 @@ struct pca953x_chip {
        unsigned gpio_start;
        uint16_t reg_output;
        uint16_t reg_direction;
+       struct mutex i2c_lock;
 
 #ifdef CONFIG_GPIO_PCA953X_IRQ
        struct mutex irq_lock;
@@ -119,13 +120,17 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+       mutex_lock(&chip->i2c_lock);
        reg_val = chip->reg_direction | (1u << off);
        ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
        if (ret)
-               return ret;
+               goto exit;
 
        chip->reg_direction = reg_val;
-       return 0;
+       ret = 0;
+exit:
+       mutex_unlock(&chip->i2c_lock);
+       return ret;
 }
 
 static int pca953x_gpio_direction_output(struct gpio_chip *gc,
@@ -137,6 +142,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+       mutex_lock(&chip->i2c_lock);
        /* set output level */
        if (val)
                reg_val = chip->reg_output | (1u << off);
@@ -145,7 +151,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
 
        ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
        if (ret)
-               return ret;
+               goto exit;
 
        chip->reg_output = reg_val;
 
@@ -153,10 +159,13 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
        reg_val = chip->reg_direction & ~(1u << off);
        ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
        if (ret)
-               return ret;
+               goto exit;
 
        chip->reg_direction = reg_val;
-       return 0;
+       ret = 0;
+exit:
+       mutex_unlock(&chip->i2c_lock);
+       return ret;
 }
 
 static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
@@ -167,7 +176,9 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+       mutex_lock(&chip->i2c_lock);
        ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
+       mutex_unlock(&chip->i2c_lock);
        if (ret < 0) {
                /* NOTE:  diagnostic already emitted; that's all we should
                 * do unless gpio_*_value_cansleep() calls become different
@@ -187,6 +198,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
+       mutex_lock(&chip->i2c_lock);
        if (val)
                reg_val = chip->reg_output | (1u << off);
        else
@@ -194,9 +206,11 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 
        ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
        if (ret)
-               return;
+               goto exit;
 
        chip->reg_output = reg_val;
+exit:
+       mutex_unlock(&chip->i2c_lock);
 }
 
 static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
@@ -228,30 +242,30 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
        return chip->irq_base + off;
 }
 
-static void pca953x_irq_mask(unsigned int irq)
+static void pca953x_irq_mask(struct irq_data *d)
 {
-       struct pca953x_chip *chip = get_irq_chip_data(irq);
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-       chip->irq_mask &= ~(1 << (irq - chip->irq_base));
+       chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
 }
 
-static void pca953x_irq_unmask(unsigned int irq)
+static void pca953x_irq_unmask(struct irq_data *d)
 {
-       struct pca953x_chip *chip = get_irq_chip_data(irq);
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
-       chip->irq_mask |= 1 << (irq - chip->irq_base);
+       chip->irq_mask |= 1 << (d->irq - chip->irq_base);
 }
 
-static void pca953x_irq_bus_lock(unsigned int irq)
+static void pca953x_irq_bus_lock(struct irq_data *d)
 {
-       struct pca953x_chip *chip = get_irq_chip_data(irq);
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
 
        mutex_lock(&chip->irq_lock);
 }
 
-static void pca953x_irq_bus_sync_unlock(unsigned int irq)
+static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
 {
-       struct pca953x_chip *chip = get_irq_chip_data(irq);
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
        uint16_t new_irqs;
        uint16_t level;
 
@@ -268,15 +282,15 @@ static void pca953x_irq_bus_sync_unlock(unsigned int irq)
        mutex_unlock(&chip->irq_lock);
 }
 
-static int pca953x_irq_set_type(unsigned int irq, unsigned int type)
+static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
 {
-       struct pca953x_chip *chip = get_irq_chip_data(irq);
-       uint16_t level = irq - chip->irq_base;
+       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       uint16_t level = d->irq - chip->irq_base;
        uint16_t mask = 1 << level;
 
        if (!(type & IRQ_TYPE_EDGE_BOTH)) {
                dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
-                       irq, type);
+                       d->irq, type);
                return -EINVAL;
        }
 
@@ -295,11 +309,11 @@ static int pca953x_irq_set_type(unsigned int irq, unsigned int type)
 
 static struct irq_chip pca953x_irq_chip = {
        .name                   = "pca953x",
-       .mask                   = pca953x_irq_mask,
-       .unmask                 = pca953x_irq_unmask,
-       .bus_lock               = pca953x_irq_bus_lock,
-       .bus_sync_unlock        = pca953x_irq_bus_sync_unlock,
-       .set_type               = pca953x_irq_set_type,
+       .irq_mask               = pca953x_irq_mask,
+       .irq_unmask             = pca953x_irq_unmask,
+       .irq_bus_lock           = pca953x_irq_bus_lock,
+       .irq_bus_sync_unlock    = pca953x_irq_bus_sync_unlock,
+       .irq_set_type           = pca953x_irq_set_type,
 };
 
 static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
@@ -517,6 +531,8 @@ static int __devinit pca953x_probe(struct i2c_client *client,
 
        chip->names = pdata->names;
 
+       mutex_init(&chip->i2c_lock);
+
        /* initialize cached registers from their original values.
         * we can't share this chip with another i2c master.
         */