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 | |
| 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>
| -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); |
