aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@pengutronix.de>2008-02-06 04:39:04 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:15 -0500
commitf5e8ff483266e2913bd676d520f46b5675a18e7a (patch)
tree54c0212d51fb53fb1f301530649dfcd5247bd8b3
parentf3dc3630f687aa4664b663143f69d99d83195c54 (diff)
gpio: handle pca953{4,5,6,7,8} too
This third part of an extension to support more pca953x chips updates the logic to handle the smaller register widths used by the 4-bit and 8-bit parts, and to use the chip type to determine how many GPIOs it provides. As long as we don't support interrupt and reset capabilities, those size issues are the only software-visible differences between these parts. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/gpio/pca953x.c71
1 files changed, 54 insertions, 17 deletions
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index ef1fe24bcbaf..92583cd4bffd 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * pca953x.c - 16-bit I/O port with interrupt and reset 2 * pca953x.c - 4/8/16 bit I/O ports
3 * 3 *
4 * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> 4 * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
5 * Copyright (C) 2007 Marvell International Ltd. 5 * Copyright (C) 2007 Marvell International Ltd.
@@ -18,13 +18,26 @@
18 18
19#include <asm/gpio.h> 19#include <asm/gpio.h>
20 20
21#define PCA953X_INPUT 0
22#define PCA953X_OUTPUT 1
23#define PCA953X_INVERT 2
24#define PCA953X_DIRECTION 3
21 25
22#define NR_PCA953X_GPIOS 16 26/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */
27struct pca953x_desc {
28 char name[I2C_NAME_SIZE];
29 unsigned long driver_data;
30};
23 31
24#define PCA953X_INPUT 0 32static const struct pca953x_desc pca953x_descs[] = {
25#define PCA953X_OUTPUT 2 33 { "pca9534", 8, },
26#define PCA953X_INVERT 4 34 { "pca9535", 16, },
27#define PCA953X_DIRECTION 6 35 { "pca9536", 4, },
36 { "pca9537", 4, },
37 { "pca9538", 8, },
38 { "pca9539", 16, },
39 /* REVISIT several pca955x parts should work here too */
40};
28 41
29struct pca953x_chip { 42struct pca953x_chip {
30 unsigned gpio_start; 43 unsigned gpio_start;
@@ -40,17 +53,30 @@ struct pca953x_chip {
40 */ 53 */
41static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) 54static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
42{ 55{
43 if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) 56 int ret;
44 return -EIO; 57
58 if (chip->gpio_chip.ngpio <= 8)
59 ret = i2c_smbus_write_byte_data(chip->client, reg, val);
45 else 60 else
46 return 0; 61 ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
62
63 if (ret < 0) {
64 dev_err(&chip->client->dev, "failed writing register\n");
65 return -EIO;
66 }
67
68 return 0;
47} 69}
48 70
49static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) 71static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
50{ 72{
51 int ret; 73 int ret;
52 74
53 ret = i2c_smbus_read_word_data(chip->client, reg); 75 if (chip->gpio_chip.ngpio <= 8)
76 ret = i2c_smbus_read_byte_data(chip->client, reg);
77 else
78 ret = i2c_smbus_read_word_data(chip->client, reg << 1);
79
54 if (ret < 0) { 80 if (ret < 0) {
55 dev_err(&chip->client->dev, "failed reading register\n"); 81 dev_err(&chip->client->dev, "failed reading register\n");
56 return -EIO; 82 return -EIO;
@@ -148,7 +174,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
148 chip->reg_output = reg_val; 174 chip->reg_output = reg_val;
149} 175}
150 176
151static int pca953x_init_gpio(struct pca953x_chip *chip) 177static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
152{ 178{
153 struct gpio_chip *gc; 179 struct gpio_chip *gc;
154 180
@@ -160,22 +186,30 @@ static int pca953x_init_gpio(struct pca953x_chip *chip)
160 gc->set = pca953x_gpio_set_value; 186 gc->set = pca953x_gpio_set_value;
161 187
162 gc->base = chip->gpio_start; 188 gc->base = chip->gpio_start;
163 gc->ngpio = NR_PCA953X_GPIOS; 189 gc->ngpio = gpios;
164 gc->label = "pca953x"; 190 gc->label = chip->client->name;
165
166 return gpiochip_add(gc);
167} 191}
168 192
169static int __devinit pca953x_probe(struct i2c_client *client) 193static int __devinit pca953x_probe(struct i2c_client *client)
170{ 194{
171 struct pca953x_platform_data *pdata; 195 struct pca953x_platform_data *pdata;
172 struct pca953x_chip *chip; 196 struct pca953x_chip *chip;
173 int ret; 197 int ret, i;
198 const struct pca953x_desc *id = NULL;
174 199
175 pdata = client->dev.platform_data; 200 pdata = client->dev.platform_data;
176 if (pdata == NULL) 201 if (pdata == NULL)
177 return -ENODEV; 202 return -ENODEV;
178 203
204 /* this loop vanishes when we get i2c_device_id */
205 for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++)
206 if (!strcmp(pca953x_descs[i].name, client->name)) {
207 id = pca953x_descs + i;
208 break;
209 }
210 if (!id)
211 return -ENODEV;
212
179 chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); 213 chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
180 if (chip == NULL) 214 if (chip == NULL)
181 return -ENOMEM; 215 return -ENOMEM;
@@ -187,6 +221,8 @@ static int __devinit pca953x_probe(struct i2c_client *client)
187 /* initialize cached registers from their original values. 221 /* initialize cached registers from their original values.
188 * we can't share this chip with another i2c master. 222 * we can't share this chip with another i2c master.
189 */ 223 */
224 pca953x_setup_gpio(chip, id->driver_data);
225
190 ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); 226 ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
191 if (ret) 227 if (ret)
192 goto out_failed; 228 goto out_failed;
@@ -200,7 +236,8 @@ static int __devinit pca953x_probe(struct i2c_client *client)
200 if (ret) 236 if (ret)
201 goto out_failed; 237 goto out_failed;
202 238
203 ret = pca953x_init_gpio(chip); 239
240 ret = gpiochip_add(&chip->gpio_chip);
204 if (ret) 241 if (ret)
205 goto out_failed; 242 goto out_failed;
206 243