diff options
Diffstat (limited to 'drivers/gpio/pca953x.c')
-rw-r--r-- | drivers/gpio/pca953x.c | 80 |
1 files changed, 75 insertions, 5 deletions
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 8dc0164bd51e..cdb6574d25a6 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
@@ -15,6 +15,10 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/i2c/pca953x.h> | 17 | #include <linux/i2c/pca953x.h> |
18 | #ifdef CONFIG_OF_GPIO | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/of_gpio.h> | ||
21 | #endif | ||
18 | 22 | ||
19 | #include <asm/gpio.h> | 23 | #include <asm/gpio.h> |
20 | 24 | ||
@@ -32,6 +36,7 @@ static const struct i2c_device_id pca953x_id[] = { | |||
32 | { "pca9539", 16, }, | 36 | { "pca9539", 16, }, |
33 | { "pca9554", 8, }, | 37 | { "pca9554", 8, }, |
34 | { "pca9555", 16, }, | 38 | { "pca9555", 16, }, |
39 | { "pca9556", 8, }, | ||
35 | { "pca9557", 8, }, | 40 | { "pca9557", 8, }, |
36 | 41 | ||
37 | { "max7310", 8, }, | 42 | { "max7310", 8, }, |
@@ -49,7 +54,9 @@ struct pca953x_chip { | |||
49 | uint16_t reg_direction; | 54 | uint16_t reg_direction; |
50 | 55 | ||
51 | struct i2c_client *client; | 56 | struct i2c_client *client; |
57 | struct pca953x_platform_data *dyn_pdata; | ||
52 | struct gpio_chip gpio_chip; | 58 | struct gpio_chip gpio_chip; |
59 | char **names; | ||
53 | }; | 60 | }; |
54 | 61 | ||
55 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) | 62 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) |
@@ -192,8 +199,57 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | |||
192 | gc->label = chip->client->name; | 199 | gc->label = chip->client->name; |
193 | gc->dev = &chip->client->dev; | 200 | gc->dev = &chip->client->dev; |
194 | gc->owner = THIS_MODULE; | 201 | gc->owner = THIS_MODULE; |
202 | gc->names = chip->names; | ||
195 | } | 203 | } |
196 | 204 | ||
205 | /* | ||
206 | * Handlers for alternative sources of platform_data | ||
207 | */ | ||
208 | #ifdef CONFIG_OF_GPIO | ||
209 | /* | ||
210 | * Translate OpenFirmware node properties into platform_data | ||
211 | */ | ||
212 | static struct pca953x_platform_data * | ||
213 | pca953x_get_alt_pdata(struct i2c_client *client) | ||
214 | { | ||
215 | struct pca953x_platform_data *pdata; | ||
216 | struct device_node *node; | ||
217 | const uint16_t *val; | ||
218 | |||
219 | node = dev_archdata_get_node(&client->dev.archdata); | ||
220 | if (node == NULL) | ||
221 | return NULL; | ||
222 | |||
223 | pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL); | ||
224 | if (pdata == NULL) { | ||
225 | dev_err(&client->dev, "Unable to allocate platform_data\n"); | ||
226 | return NULL; | ||
227 | } | ||
228 | |||
229 | pdata->gpio_base = -1; | ||
230 | val = of_get_property(node, "linux,gpio-base", NULL); | ||
231 | if (val) { | ||
232 | if (*val < 0) | ||
233 | dev_warn(&client->dev, | ||
234 | "invalid gpio-base in device tree\n"); | ||
235 | else | ||
236 | pdata->gpio_base = *val; | ||
237 | } | ||
238 | |||
239 | val = of_get_property(node, "polarity", NULL); | ||
240 | if (val) | ||
241 | pdata->invert = *val; | ||
242 | |||
243 | return pdata; | ||
244 | } | ||
245 | #else | ||
246 | static struct pca953x_platform_data * | ||
247 | pca953x_get_alt_pdata(struct i2c_client *client) | ||
248 | { | ||
249 | return NULL; | ||
250 | } | ||
251 | #endif | ||
252 | |||
197 | static int __devinit pca953x_probe(struct i2c_client *client, | 253 | static int __devinit pca953x_probe(struct i2c_client *client, |
198 | const struct i2c_device_id *id) | 254 | const struct i2c_device_id *id) |
199 | { | 255 | { |
@@ -201,20 +257,32 @@ static int __devinit pca953x_probe(struct i2c_client *client, | |||
201 | struct pca953x_chip *chip; | 257 | struct pca953x_chip *chip; |
202 | int ret; | 258 | int ret; |
203 | 259 | ||
260 | chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); | ||
261 | if (chip == NULL) | ||
262 | return -ENOMEM; | ||
263 | |||
204 | pdata = client->dev.platform_data; | 264 | pdata = client->dev.platform_data; |
205 | if (pdata == NULL) { | 265 | if (pdata == NULL) { |
206 | dev_dbg(&client->dev, "no platform data\n"); | 266 | pdata = pca953x_get_alt_pdata(client); |
207 | return -EINVAL; | 267 | /* |
268 | * Unlike normal platform_data, this is allocated | ||
269 | * dynamically and must be freed in the driver | ||
270 | */ | ||
271 | chip->dyn_pdata = pdata; | ||
208 | } | 272 | } |
209 | 273 | ||
210 | chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); | 274 | if (pdata == NULL) { |
211 | if (chip == NULL) | 275 | dev_dbg(&client->dev, "no platform data\n"); |
212 | return -ENOMEM; | 276 | ret = -EINVAL; |
277 | goto out_failed; | ||
278 | } | ||
213 | 279 | ||
214 | chip->client = client; | 280 | chip->client = client; |
215 | 281 | ||
216 | chip->gpio_start = pdata->gpio_base; | 282 | chip->gpio_start = pdata->gpio_base; |
217 | 283 | ||
284 | chip->names = pdata->names; | ||
285 | |||
218 | /* initialize cached registers from their original values. | 286 | /* initialize cached registers from their original values. |
219 | * we can't share this chip with another i2c master. | 287 | * we can't share this chip with another i2c master. |
220 | */ | 288 | */ |
@@ -249,6 +317,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, | |||
249 | return 0; | 317 | return 0; |
250 | 318 | ||
251 | out_failed: | 319 | out_failed: |
320 | kfree(chip->dyn_pdata); | ||
252 | kfree(chip); | 321 | kfree(chip); |
253 | return ret; | 322 | return ret; |
254 | } | 323 | } |
@@ -276,6 +345,7 @@ static int pca953x_remove(struct i2c_client *client) | |||
276 | return ret; | 345 | return ret; |
277 | } | 346 | } |
278 | 347 | ||
348 | kfree(chip->dyn_pdata); | ||
279 | kfree(chip); | 349 | kfree(chip); |
280 | return 0; | 350 | return 0; |
281 | } | 351 | } |