From 0c36ec31473593aa937ff04f3b3b630e81512734 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Mon, 21 Jul 2008 14:21:34 -0700 Subject: gpio: gpio driver for max7301 SPI GPIO expander Maxim's MAX7301 is an SPI GPIO expander with 28 GPIOs. Note: MAX7301's interrupt feature is not supported yet. [akpm@linux-foundation.org: coding-style fixes] [g.liakhovetski@pengutronix.de: Fix inaccuracies in comments, check spi_setup() return code, mask off high byte in max7301_read()] Signed-off-by: Juergen Beisert Signed-off-by: Guennadi Liakhovetski Cc: Russell King Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 008c38ba774f..9e0c4fbfc51a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -69,6 +69,12 @@ config GPIO_PCF857X comment "SPI GPIO expanders:" +config GPIO_MAX7301 + tristate "Maxim MAX7301 GPIO expander" + depends on SPI_MASTER + help + gpio driver for Maxim MAX7301 SPI GPIO expander. + config GPIO_MCP23S08 tristate "Microchip MCP23S08 I/O expander" depends on SPI_MASTER -- cgit v1.2.3 From 1673ad52bd9a3c747e596a76e65c55981ea651e3 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 21 Jul 2008 14:21:34 -0700 Subject: gpio: pcf857x: add lock and handle more chips Two small updates to the pcf857x driver: (a) the max732[89] chips are also second sources for the pcf8574/a, and (b) add a mutex to prevent trashing the cached state. Adding the lock is effectively a bugfix, although it seems unlikely that anyone would have run into the issue it protects against. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/Kconfig | 5 +++-- drivers/gpio/pcf857x.c | 33 +++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9e0c4fbfc51a..fced1909cbba 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -45,7 +45,7 @@ config GPIO_PCA953X will be called pca953x. config GPIO_PCF857X - tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders" + tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" depends on I2C help Say yes here to provide access to most "quasi-bidirectional" I2C @@ -54,7 +54,8 @@ config GPIO_PCF857X some of them. Compatible models include: 8 bits: pcf8574, pcf8574a, pca8574, pca8574a, - pca9670, pca9672, pca9674, pca9674a + pca9670, pca9672, pca9674, pca9674a, + max7328, max7329 16 bits: pcf8575, pcf8575c, pca8575, pca9671, pca9673, pca9675 diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index aa6cc8b2a2bc..d25d356c4f20 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c @@ -37,6 +37,8 @@ static const struct i2c_device_id pcf857x_id[] = { { "pca9671", 16 }, { "pca9673", 16 }, { "pca9675", 16 }, + { "max7328", 8 }, + { "max7329", 8 }, { } }; MODULE_DEVICE_TABLE(i2c, pcf857x_id); @@ -56,6 +58,7 @@ MODULE_DEVICE_TABLE(i2c, pcf857x_id); struct pcf857x { struct gpio_chip chip; struct i2c_client *client; + struct mutex lock; /* protect 'out' */ unsigned out; /* software latch */ }; @@ -66,9 +69,14 @@ struct pcf857x { static int pcf857x_input8(struct gpio_chip *chip, unsigned offset) { struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); + int status; + mutex_lock(&gpio->lock); gpio->out |= (1 << offset); - return i2c_smbus_write_byte(gpio->client, gpio->out); + status = i2c_smbus_write_byte(gpio->client, gpio->out); + mutex_unlock(&gpio->lock); + + return status; } static int pcf857x_get8(struct gpio_chip *chip, unsigned offset) @@ -84,12 +92,17 @@ static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value) { struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); unsigned bit = 1 << offset; + int status; + mutex_lock(&gpio->lock); if (value) gpio->out |= bit; else gpio->out &= ~bit; - return i2c_smbus_write_byte(gpio->client, gpio->out); + status = i2c_smbus_write_byte(gpio->client, gpio->out); + mutex_unlock(&gpio->lock); + + return status; } static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value) @@ -124,9 +137,14 @@ static int i2c_read_le16(struct i2c_client *client) static int pcf857x_input16(struct gpio_chip *chip, unsigned offset) { struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); + int status; + mutex_lock(&gpio->lock); gpio->out |= (1 << offset); - return i2c_write_le16(gpio->client, gpio->out); + status = i2c_write_le16(gpio->client, gpio->out); + mutex_unlock(&gpio->lock); + + return status; } static int pcf857x_get16(struct gpio_chip *chip, unsigned offset) @@ -142,12 +160,17 @@ static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value) { struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); unsigned bit = 1 << offset; + int status; + mutex_lock(&gpio->lock); if (value) gpio->out |= bit; else gpio->out &= ~bit; - return i2c_write_le16(gpio->client, gpio->out); + status = i2c_write_le16(gpio->client, gpio->out); + mutex_unlock(&gpio->lock); + + return status; } static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value) @@ -173,6 +196,8 @@ static int pcf857x_probe(struct i2c_client *client, if (!gpio) return -ENOMEM; + mutex_init(&gpio->lock); + gpio->chip.base = pdata->gpio_base; gpio->chip.can_sleep = 1; gpio->chip.owner = THIS_MODULE; -- cgit v1.2.3