summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-twl4030.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-twl4030.c')
-rw-r--r--drivers/gpio/gpio-twl4030.c90
1 files changed, 61 insertions, 29 deletions
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index 94256fe7bf36..c5f8ca233e1f 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -51,6 +51,7 @@
static struct gpio_chip twl_gpiochip;
+static int twl4030_gpio_base;
static int twl4030_gpio_irq_base;
/* genirq interfaces are not available to modules */
@@ -395,6 +396,29 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
static int gpio_twl4030_remove(struct platform_device *pdev);
+static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
+{
+ struct twl4030_gpio_platform_data *omap_twl_info;
+
+ omap_twl_info = devm_kzalloc(dev, sizeof(*omap_twl_info), GFP_KERNEL);
+ if (!omap_twl_info)
+ return NULL;
+
+ omap_twl_info->use_leds = of_property_read_bool(dev->of_node,
+ "ti,use-leds");
+
+ of_property_read_u32(dev->of_node, "ti,debounce",
+ &omap_twl_info->debounce);
+ of_property_read_u32(dev->of_node, "ti,mmc-cd",
+ (u32 *)&omap_twl_info->mmc_cd);
+ of_property_read_u32(dev->of_node, "ti,pullups",
+ &omap_twl_info->pullups);
+ of_property_read_u32(dev->of_node, "ti,pulldowns",
+ &omap_twl_info->pulldowns);
+
+ return omap_twl_info;
+}
+
static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -427,49 +451,57 @@ no_irqs:
twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
twl_gpiochip.dev = &pdev->dev;
- if (pdata) {
- twl_gpiochip.base = pdata->gpio_base;
+ if (node)
+ pdata = of_gpio_twl4030(&pdev->dev);
- /*
- * 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;
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "Platform data is missing\n");
+ return -ENXIO;
}
+ /*
+ * 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 && pdata->setup) {
+ goto out;
+ }
+
+ twl4030_gpio_base = twl_gpiochip.base;
+
+ if (pdata && pdata->setup) {
int status;
status = pdata->setup(&pdev->dev,
- pdata->gpio_base, TWL4030_GPIO_MAX);
+ twl4030_gpio_base, TWL4030_GPIO_MAX);
if (status)
dev_dbg(&pdev->dev, "setup --> %d\n", status);
}
+out:
return ret;
}
@@ -481,7 +513,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
if (pdata && pdata->teardown) {
status = pdata->teardown(&pdev->dev,
- pdata->gpio_base, TWL4030_GPIO_MAX);
+ twl4030_gpio_base, TWL4030_GPIO_MAX);
if (status) {
dev_dbg(&pdev->dev, "teardown --> %d\n", status);
return status;