|
@@ -60,6 +60,7 @@ struct pca953x_chip {
|
|
unsigned gpio_start;
|
|
unsigned gpio_start;
|
|
uint16_t reg_output;
|
|
uint16_t reg_output;
|
|
uint16_t reg_direction;
|
|
uint16_t reg_direction;
|
|
|
|
+ struct mutex i2c_lock;
|
|
|
|
|
|
#ifdef CONFIG_GPIO_PCA953X_IRQ
|
|
#ifdef CONFIG_GPIO_PCA953X_IRQ
|
|
struct mutex irq_lock;
|
|
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);
|
|
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
|
|
|
|
|
|
|
+ mutex_lock(&chip->i2c_lock);
|
|
reg_val = chip->reg_direction | (1u << off);
|
|
reg_val = chip->reg_direction | (1u << off);
|
|
ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
|
|
ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
|
|
if (ret)
|
|
if (ret)
|
|
- return ret;
|
|
|
|
|
|
+ goto exit;
|
|
|
|
|
|
chip->reg_direction = reg_val;
|
|
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,
|
|
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);
|
|
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
|
|
|
|
|
|
|
+ mutex_lock(&chip->i2c_lock);
|
|
/* set output level */
|
|
/* set output level */
|
|
if (val)
|
|
if (val)
|
|
reg_val = chip->reg_output | (1u << off);
|
|
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);
|
|
ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
|
|
if (ret)
|
|
if (ret)
|
|
- return ret;
|
|
|
|
|
|
+ goto exit;
|
|
|
|
|
|
chip->reg_output = reg_val;
|
|
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);
|
|
reg_val = chip->reg_direction & ~(1u << off);
|
|
ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
|
|
ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
|
|
if (ret)
|
|
if (ret)
|
|
- return ret;
|
|
|
|
|
|
+ goto exit;
|
|
|
|
|
|
chip->reg_direction = reg_val;
|
|
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)
|
|
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);
|
|
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
|
|
|
|
|
|
|
+ mutex_lock(&chip->i2c_lock);
|
|
ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val);
|
|
ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val);
|
|
|
|
+ mutex_unlock(&chip->i2c_lock);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
/* NOTE: diagnostic already emitted; that's all we should
|
|
/* NOTE: diagnostic already emitted; that's all we should
|
|
* do unless gpio_*_value_cansleep() calls become different
|
|
* 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);
|
|
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
|
|
|
|
|
|
|
+ mutex_lock(&chip->i2c_lock);
|
|
if (val)
|
|
if (val)
|
|
reg_val = chip->reg_output | (1u << off);
|
|
reg_val = chip->reg_output | (1u << off);
|
|
else
|
|
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);
|
|
ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
|
|
if (ret)
|
|
if (ret)
|
|
- return;
|
|
|
|
|
|
+ goto exit;
|
|
|
|
|
|
chip->reg_output = reg_val;
|
|
chip->reg_output = reg_val;
|
|
|
|
+exit:
|
|
|
|
+ mutex_unlock(&chip->i2c_lock);
|
|
}
|
|
}
|
|
|
|
|
|
static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
|
|
static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
|
|
@@ -517,6 +531,8 @@ static int __devinit pca953x_probe(struct i2c_client *client,
|
|
|
|
|
|
chip->names = pdata->names;
|
|
chip->names = pdata->names;
|
|
|
|
|
|
|
|
+ mutex_init(&chip->i2c_lock);
|
|
|
|
+
|
|
/* initialize cached registers from their original values.
|
|
/* initialize cached registers from their original values.
|
|
* we can't share this chip with another i2c master.
|
|
* we can't share this chip with another i2c master.
|
|
*/
|
|
*/
|