aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorNate Case <ncase@xes-inc.com>2009-06-17 19:26:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-18 16:03:44 -0400
commit1965d30356c1c65660ba3330927671cfe81acdd5 (patch)
tree7690fe5353333aa3a21e0b77b69505a79d601ff7 /drivers/gpio
parentde3483b071d9f75490f52c1be78434ac4eeccea5 (diff)
gpio: pca953x: Get platform_data from OpenFirmware
On OpenFirmware platforms, it makes the most sense to get platform_data from the device tree. Make an attempt to translate OF node properties into platform_data struct before bailing out. Note that the implementation approach taken differs from other device drivers that make use of device tree information. This is because I2C chips are already registered automatically by of_i2c, so we can get by with a small translator function in the driver. [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: kfree(NULL) is legal] Signed-off-by: Nate Case <ncase@xes-inc.com> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/pca953x.c75
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 */
211static struct pca953x_platform_data *
212pca953x_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
245static struct pca953x_platform_data *
246pca953x_get_alt_pdata(struct i2c_client *client)
247{
248 return NULL;
249}
250#endif
251
199static int __devinit pca953x_probe(struct i2c_client *client, 252static 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
255out_failed: 318out_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}