diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/pca953x.c | 75 |
1 files changed, 70 insertions, 5 deletions
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 2dae94fbabf4..e9d6d5bdd300 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 | ||
@@ -49,6 +53,7 @@ struct pca953x_chip { | |||
49 | uint16_t reg_direction; | 53 | uint16_t reg_direction; |
50 | 54 | ||
51 | struct i2c_client *client; | 55 | struct i2c_client *client; |
56 | struct pca953x_platform_data *dyn_pdata; | ||
52 | struct gpio_chip gpio_chip; | 57 | struct gpio_chip gpio_chip; |
53 | char **names; | 58 | char **names; |
54 | }; | 59 | }; |
@@ -196,6 +201,54 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | |||
196 | gc->names = chip->names; | 201 | gc->names = chip->names; |
197 | } | 202 | } |
198 | 203 | ||
204 | /* | ||
205 | * Handlers for alternative sources of platform_data | ||
206 | */ | ||
207 | #ifdef CONFIG_OF_GPIO | ||
208 | /* | ||
209 | * Translate OpenFirmware node properties into platform_data | ||
210 | */ | ||
211 | static struct pca953x_platform_data * | ||
212 | pca953x_get_alt_pdata(struct i2c_client *client) | ||
213 | { | ||
214 | struct pca953x_platform_data *pdata; | ||
215 | struct device_node *node; | ||
216 | const uint16_t *val; | ||
217 | |||
218 | node = dev_archdata_get_node(&client->dev.archdata); | ||
219 | if (node == NULL) | ||
220 | return NULL; | ||
221 | |||
222 | pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL); | ||
223 | if (pdata == NULL) { | ||
224 | dev_err(&client->dev, "Unable to allocate platform_data\n"); | ||
225 | return NULL; | ||
226 | } | ||
227 | |||
228 | pdata->gpio_base = -1; | ||
229 | val = of_get_property(node, "linux,gpio-base", NULL); | ||
230 | if (val) { | ||
231 | if (*val < 0) | ||
232 | dev_warn(&client->dev, | ||
233 | "invalid gpio-base in device tree\n"); | ||
234 | else | ||
235 | pdata->gpio_base = *val; | ||
236 | } | ||
237 | |||
238 | val = of_get_property(node, "polarity", NULL); | ||
239 | if (val) | ||
240 | pdata->invert = *val; | ||
241 | |||
242 | return pdata; | ||
243 | } | ||
244 | #else | ||
245 | static struct pca953x_platform_data * | ||
246 | pca953x_get_alt_pdata(struct i2c_client *client) | ||
247 | { | ||
248 | return NULL; | ||
249 | } | ||
250 | #endif | ||
251 | |||
199 | static int __devinit pca953x_probe(struct i2c_client *client, | 252 | static int __devinit pca953x_probe(struct i2c_client *client, |
200 | const struct i2c_device_id *id) | 253 | const struct i2c_device_id *id) |
201 | { | 254 | { |
@@ -203,15 +256,25 @@ static int __devinit pca953x_probe(struct i2c_client *client, | |||
203 | struct pca953x_chip *chip; | 256 | struct pca953x_chip *chip; |
204 | int ret; | 257 | int ret; |
205 | 258 | ||
259 | chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); | ||
260 | if (chip == NULL) | ||
261 | return -ENOMEM; | ||
262 | |||
206 | pdata = client->dev.platform_data; | 263 | pdata = client->dev.platform_data; |
207 | if (pdata == NULL) { | 264 | if (pdata == NULL) { |
208 | dev_dbg(&client->dev, "no platform data\n"); | 265 | pdata = pca953x_get_alt_pdata(client); |
209 | return -EINVAL; | 266 | /* |
267 | * Unlike normal platform_data, this is allocated | ||
268 | * dynamically and must be freed in the driver | ||
269 | */ | ||
270 | chip->dyn_pdata = pdata; | ||
210 | } | 271 | } |
211 | 272 | ||
212 | chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); | 273 | if (pdata == NULL) { |
213 | if (chip == NULL) | 274 | dev_dbg(&client->dev, "no platform data\n"); |
214 | return -ENOMEM; | 275 | ret = -EINVAL; |
276 | goto out_failed; | ||
277 | } | ||
215 | 278 | ||
216 | chip->client = client; | 279 | chip->client = client; |
217 | 280 | ||
@@ -253,6 +316,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, | |||
253 | return 0; | 316 | return 0; |
254 | 317 | ||
255 | out_failed: | 318 | out_failed: |
319 | kfree(chip->dyn_pdata); | ||
256 | kfree(chip); | 320 | kfree(chip); |
257 | return ret; | 321 | return ret; |
258 | } | 322 | } |
@@ -280,6 +344,7 @@ static int pca953x_remove(struct i2c_client *client) | |||
280 | return ret; | 344 | return ret; |
281 | } | 345 | } |
282 | 346 | ||
347 | kfree(chip->dyn_pdata); | ||
283 | kfree(chip); | 348 | kfree(chip); |
284 | return 0; | 349 | return 0; |
285 | } | 350 | } |