diff options
author | Lee Jones <lee.jones@linaro.org> | 2012-09-07 07:14:59 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-09-12 17:15:46 -0400 |
commit | 3113e679021a3a6bace1c62a8432cc0ec27c09ab (patch) | |
tree | 4577064b83b9c7da36bc64f35e76b58107658b2d /drivers/gpio/gpio-tc3589x.c | |
parent | efe4c9496a80253492942624dd23caa3ca6782c8 (diff) |
gpio: Enable the tc3298x GPIO expander driver for Device Tree
Here we provide a means to probe and extract vital information
from Device Tree when booting with it enabled. Without this
patch sub-devices wouldn't be able to reference the tc3589x-gpio
expander from Device Tree.
CC: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpio-tc3589x.c')
-rw-r--r-- | drivers/gpio/gpio-tc3589x.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 6e8900933972..1e48317e70fb 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/gpio.h> | 13 | #include <linux/gpio.h> |
14 | #include <linux/of.h> | ||
14 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
15 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
@@ -286,7 +287,8 @@ static struct irq_domain_ops tc3589x_irq_ops = { | |||
286 | .xlate = irq_domain_xlate_twocell, | 287 | .xlate = irq_domain_xlate_twocell, |
287 | }; | 288 | }; |
288 | 289 | ||
289 | static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio) | 290 | static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio, |
291 | struct device_node *np) | ||
290 | { | 292 | { |
291 | int base = tc3589x_gpio->irq_base; | 293 | int base = tc3589x_gpio->irq_base; |
292 | 294 | ||
@@ -297,7 +299,7 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio) | |||
297 | } | 299 | } |
298 | else { | 300 | else { |
299 | tc3589x_gpio->domain = irq_domain_add_linear( | 301 | tc3589x_gpio->domain = irq_domain_add_linear( |
300 | NULL, tc3589x_gpio->chip.ngpio, | 302 | np, tc3589x_gpio->chip.ngpio, |
301 | &tc3589x_irq_ops, tc3589x_gpio); | 303 | &tc3589x_irq_ops, tc3589x_gpio); |
302 | } | 304 | } |
303 | 305 | ||
@@ -313,13 +315,17 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) | |||
313 | { | 315 | { |
314 | struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); | 316 | struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); |
315 | struct tc3589x_gpio_platform_data *pdata; | 317 | struct tc3589x_gpio_platform_data *pdata; |
318 | struct device_node *np = pdev->dev.of_node; | ||
316 | struct tc3589x_gpio *tc3589x_gpio; | 319 | struct tc3589x_gpio *tc3589x_gpio; |
317 | int ret; | 320 | int ret; |
318 | int irq; | 321 | int irq; |
319 | 322 | ||
320 | pdata = tc3589x->pdata->gpio; | 323 | pdata = tc3589x->pdata->gpio; |
321 | if (!pdata) | 324 | |
322 | return -ENODEV; | 325 | if (!(pdata || np)) { |
326 | dev_err(&pdev->dev, "No platform data or Device Tree found\n"); | ||
327 | return -EINVAL; | ||
328 | } | ||
323 | 329 | ||
324 | irq = platform_get_irq(pdev, 0); | 330 | irq = platform_get_irq(pdev, 0); |
325 | if (irq < 0) | 331 | if (irq < 0) |
@@ -337,9 +343,11 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) | |||
337 | tc3589x_gpio->chip = template_chip; | 343 | tc3589x_gpio->chip = template_chip; |
338 | tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; | 344 | tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; |
339 | tc3589x_gpio->chip.dev = &pdev->dev; | 345 | tc3589x_gpio->chip.dev = &pdev->dev; |
340 | tc3589x_gpio->chip.base = pdata->gpio_base; | 346 | tc3589x_gpio->chip.base = (pdata) ? pdata->gpio_base : -1; |
341 | 347 | ||
342 | tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0); | 348 | #ifdef CONFIG_OF_GPIO |
349 | tc3589x_gpio->chip.of_node = np; | ||
350 | #endif | ||
343 | 351 | ||
344 | tc3589x_gpio->irq_base = tc3589x->irq_base ? | 352 | tc3589x_gpio->irq_base = tc3589x->irq_base ? |
345 | tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0; | 353 | tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0; |
@@ -350,7 +358,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) | |||
350 | if (ret < 0) | 358 | if (ret < 0) |
351 | goto out_free; | 359 | goto out_free; |
352 | 360 | ||
353 | ret = tc3589x_gpio_irq_init(tc3589x_gpio); | 361 | ret = tc3589x_gpio_irq_init(tc3589x_gpio, np); |
354 | if (ret) | 362 | if (ret) |
355 | goto out_free; | 363 | goto out_free; |
356 | 364 | ||
@@ -367,7 +375,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) | |||
367 | goto out_freeirq; | 375 | goto out_freeirq; |
368 | } | 376 | } |
369 | 377 | ||
370 | if (pdata->setup) | 378 | if (pdata && pdata->setup) |
371 | pdata->setup(tc3589x, tc3589x_gpio->chip.base); | 379 | pdata->setup(tc3589x, tc3589x_gpio->chip.base); |
372 | 380 | ||
373 | platform_set_drvdata(pdev, tc3589x_gpio); | 381 | platform_set_drvdata(pdev, tc3589x_gpio); |
@@ -389,7 +397,7 @@ static int __devexit tc3589x_gpio_remove(struct platform_device *pdev) | |||
389 | int irq = platform_get_irq(pdev, 0); | 397 | int irq = platform_get_irq(pdev, 0); |
390 | int ret; | 398 | int ret; |
391 | 399 | ||
392 | if (pdata->remove) | 400 | if (pdata && pdata->remove) |
393 | pdata->remove(tc3589x, tc3589x_gpio->chip.base); | 401 | pdata->remove(tc3589x, tc3589x_gpio->chip.base); |
394 | 402 | ||
395 | ret = gpiochip_remove(&tc3589x_gpio->chip); | 403 | ret = gpiochip_remove(&tc3589x_gpio->chip); |