diff options
Diffstat (limited to 'drivers/gpio/gpio-twl4030.c')
-rw-r--r-- | drivers/gpio/gpio-twl4030.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 0c7e891c8651..f9996899c1f2 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c | |||
@@ -300,7 +300,7 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset) | |||
300 | if (offset < TWL4030_GPIO_MAX) | 300 | if (offset < TWL4030_GPIO_MAX) |
301 | ret = twl4030_set_gpio_direction(offset, 1); | 301 | ret = twl4030_set_gpio_direction(offset, 1); |
302 | else | 302 | else |
303 | ret = -EINVAL; | 303 | ret = -EINVAL; /* LED outputs can't be set as input */ |
304 | 304 | ||
305 | if (!ret) | 305 | if (!ret) |
306 | priv->direction &= ~BIT(offset); | 306 | priv->direction &= ~BIT(offset); |
@@ -354,17 +354,27 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value) | |||
354 | static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) | 354 | static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) |
355 | { | 355 | { |
356 | struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); | 356 | struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); |
357 | int ret = 0; | ||
357 | 358 | ||
358 | mutex_lock(&priv->mutex); | 359 | mutex_lock(&priv->mutex); |
359 | if (offset < TWL4030_GPIO_MAX) | 360 | if (offset < TWL4030_GPIO_MAX) { |
360 | twl4030_set_gpio_dataout(offset, value); | 361 | ret = twl4030_set_gpio_direction(offset, 0); |
362 | if (ret) { | ||
363 | mutex_unlock(&priv->mutex); | ||
364 | return ret; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output | ||
370 | */ | ||
361 | 371 | ||
362 | priv->direction |= BIT(offset); | 372 | priv->direction |= BIT(offset); |
363 | mutex_unlock(&priv->mutex); | 373 | mutex_unlock(&priv->mutex); |
364 | 374 | ||
365 | twl_set(chip, offset, value); | 375 | twl_set(chip, offset, value); |
366 | 376 | ||
367 | return 0; | 377 | return ret; |
368 | } | 378 | } |
369 | 379 | ||
370 | static int twl_to_irq(struct gpio_chip *chip, unsigned offset) | 380 | static int twl_to_irq(struct gpio_chip *chip, unsigned offset) |
@@ -435,7 +445,8 @@ static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) | |||
435 | 445 | ||
436 | static int gpio_twl4030_remove(struct platform_device *pdev); | 446 | static int gpio_twl4030_remove(struct platform_device *pdev); |
437 | 447 | ||
438 | static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev) | 448 | static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, |
449 | struct twl4030_gpio_platform_data *pdata) | ||
439 | { | 450 | { |
440 | struct twl4030_gpio_platform_data *omap_twl_info; | 451 | struct twl4030_gpio_platform_data *omap_twl_info; |
441 | 452 | ||
@@ -443,6 +454,9 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev) | |||
443 | if (!omap_twl_info) | 454 | if (!omap_twl_info) |
444 | return NULL; | 455 | return NULL; |
445 | 456 | ||
457 | if (pdata) | ||
458 | *omap_twl_info = *pdata; | ||
459 | |||
446 | omap_twl_info->use_leds = of_property_read_bool(dev->of_node, | 460 | omap_twl_info->use_leds = of_property_read_bool(dev->of_node, |
447 | "ti,use-leds"); | 461 | "ti,use-leds"); |
448 | 462 | ||
@@ -500,7 +514,7 @@ no_irqs: | |||
500 | mutex_init(&priv->mutex); | 514 | mutex_init(&priv->mutex); |
501 | 515 | ||
502 | if (node) | 516 | if (node) |
503 | pdata = of_gpio_twl4030(&pdev->dev); | 517 | pdata = of_gpio_twl4030(&pdev->dev, pdata); |
504 | 518 | ||
505 | if (pdata == NULL) { | 519 | if (pdata == NULL) { |
506 | dev_err(&pdev->dev, "Platform data is missing\n"); | 520 | dev_err(&pdev->dev, "Platform data is missing\n"); |