Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 296899
b: refs/heads/master
c: b8589e2
h: refs/heads/master
i:
  296897: 110f2c9
  296895: ddf26a4
v: v3
  • Loading branch information
Benoit Cousson authored and Samuel Ortiz committed Mar 22, 2012
1 parent 65c6947 commit 1e3c1dc
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2d9dd99b4470a2ef05509435465e055f50456330
refs/heads/master: b8589e2a8065b8e7773742b60ae96b63b757bb69
23 changes: 23 additions & 0 deletions trunk/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
twl4030 GPIO controller bindings

Required properties:
- compatible:
- "ti,twl4030-gpio" for twl4030 GPIO controller
- #gpio-cells : Should be two.
- first cell is the pin number
- second cell is used to specify optional parameters (unused)
- gpio-controller : Marks the device node as a GPIO controller.
- #interrupt-cells : Should be 2.
- interrupt-controller: Mark the device node as an interrupt controller
The first cell is the GPIO number.
The second cell is not used.

Example:

twl_gpio: gpio {
compatible = "ti,twl4030-gpio";
#gpio-cells = <2>;
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
};
79 changes: 50 additions & 29 deletions trunk/drivers/gpio/gpio-twl4030.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/irqdomain.h>

#include <linux/i2c/twl.h>

Expand Down Expand Up @@ -256,7 +258,8 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
* and vMMC2 power supplies based on card presence.
*/
pdata = chip->dev->platform_data;
value |= pdata->mmc_cd & 0x03;
if (pdata)
value |= pdata->mmc_cd & 0x03;

status = gpio_twl4030_write(REG_GPIO_CTRL, value);
}
Expand Down Expand Up @@ -395,6 +398,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev);
static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
int ret, irq_base;

/* maybe setup IRQs */
Expand All @@ -409,47 +413,55 @@ static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
return irq_base;
}

irq_domain_add_legacy(node, TWL4030_GPIO_MAX, irq_base, 0,
&irq_domain_simple_ops, NULL);

ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base);
if (ret < 0)
return ret;

twl4030_gpio_irq_base = irq_base;

no_irqs:
/*
* NOTE: boards may waste power if they don't set pullups
* and pulldowns correctly ... default for non-ULPI pins is
* pulldown, and some other pins may have external pullups
* or pulldowns. Careful!
*/
ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
if (ret)
dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
pdata->pullups, pdata->pulldowns,
ret);

ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
if (ret)
dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
pdata->debounce, pdata->mmc_cd,
ret);

twl_gpiochip.base = pdata->gpio_base;
twl_gpiochip.base = -1;
twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
twl_gpiochip.dev = &pdev->dev;

/* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
* is (still) clear if use_leds is set.
*/
if (pdata->use_leds)
twl_gpiochip.ngpio += 2;
if (pdata) {
twl_gpiochip.base = pdata->gpio_base;

/*
* NOTE: boards may waste power if they don't set pullups
* and pulldowns correctly ... default for non-ULPI pins is
* pulldown, and some other pins may have external pullups
* or pulldowns. Careful!
*/
ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
if (ret)
dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
pdata->pullups, pdata->pulldowns,
ret);

ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
if (ret)
dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
pdata->debounce, pdata->mmc_cd,
ret);

/*
* NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
* is (still) clear if use_leds is set.
*/
if (pdata->use_leds)
twl_gpiochip.ngpio += 2;
}

ret = gpiochip_add(&twl_gpiochip);
if (ret < 0) {
dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
twl_gpiochip.ngpio = 0;
gpio_twl4030_remove(pdev);
} else if (pdata->setup) {
} else if (pdata && pdata->setup) {
int status;

status = pdata->setup(&pdev->dev,
Expand All @@ -467,7 +479,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
int status;

if (pdata->teardown) {
if (pdata && pdata->teardown) {
status = pdata->teardown(&pdev->dev,
pdata->gpio_base, TWL4030_GPIO_MAX);
if (status) {
Expand All @@ -488,12 +500,21 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
return -EIO;
}

static const struct of_device_id twl_gpio_match[] = {
{ .compatible = "ti,twl4030-gpio", },
{ },
};
MODULE_DEVICE_TABLE(of, twl_gpio_match);

/* Note: this hardware lives inside an I2C-based multi-function device. */
MODULE_ALIAS("platform:twl4030_gpio");

static struct platform_driver gpio_twl4030_driver = {
.driver.name = "twl4030_gpio",
.driver.owner = THIS_MODULE,
.driver = {
.name = "twl4030_gpio",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(twl_gpio_match),
},
.probe = gpio_twl4030_probe,
.remove = gpio_twl4030_remove,
};
Expand Down

0 comments on commit 1e3c1dc

Please sign in to comment.