diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/pca953x.c | 71 |
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. */ |
27 | struct pca953x_desc { | ||
28 | char name[I2C_NAME_SIZE]; | ||
29 | unsigned long driver_data; | ||
30 | }; | ||
23 | 31 | ||
24 | #define PCA953X_INPUT 0 | 32 | static 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 | ||
29 | struct pca953x_chip { | 42 | struct pca953x_chip { |
30 | unsigned gpio_start; | 43 | unsigned gpio_start; |
@@ -40,17 +53,30 @@ struct pca953x_chip { | |||
40 | */ | 53 | */ |
41 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) | 54 | static 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 | ||
49 | static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) | 71 | static 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 | ||
151 | static int pca953x_init_gpio(struct pca953x_chip *chip) | 177 | static 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 | ||
169 | static int __devinit pca953x_probe(struct i2c_client *client) | 193 | static 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 | ||