gpio: twl4030: Fix regression for twl gpio LED output
authorRoger Quadros <rogerq@ti.com>
Thu, 5 Dec 2013 09:23:35 +0000 (11:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jan 2014 20:25:15 +0000 (12:25 -0800)
commit f5837ec11f8cfa6d53ebc5806582771b2c9988c6 upstream.

Commit 0b2aa8be introduced a regression that causes failure
in setting LED GPO direction to OUT.

This causes USB host probe failures for Beagleboard C4.

platform usb_phy_gen_xceiv.2: Driver usb_phy_gen_xceiv requests probe deferral
hsusb2_vcc: Failed to request enable GPIO510: -22
reg-fixed-voltage reg-fixed-voltage.0.auto: Failed to register regulator: -22
reg-fixed-voltage: probe of reg-fixed-voltage.0.auto failed with error -22

direction_out/direction_in must return 0 if the operation succeeded.

Also, don't update direction flag and output data if twl4030_set_gpio_direction()
failed inside twl_direction_out();

Signed-off-by: Roger Quadros <rogerq@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpio/gpio-twl4030.c

index db2de1a..77d805a 100644 (file)
@@ -300,7 +300,7 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset)
        if (offset < TWL4030_GPIO_MAX)
                ret = twl4030_set_gpio_direction(offset, 1);
        else
-               ret = -EINVAL;
+               ret = -EINVAL;  /* LED outputs can't be set as input */
 
        if (!ret)
                priv->direction &= ~BIT(offset);
@@ -354,11 +354,20 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value)
 static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
-       int ret = -EINVAL;
+       int ret = 0;
 
        mutex_lock(&priv->mutex);
-       if (offset < TWL4030_GPIO_MAX)
+       if (offset < TWL4030_GPIO_MAX) {
                ret = twl4030_set_gpio_direction(offset, 0);
+               if (ret) {
+                       mutex_unlock(&priv->mutex);
+                       return ret;
+               }
+       }
+
+       /*
+        *  LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output
+        */
 
        priv->direction |= BIT(offset);
        mutex_unlock(&priv->mutex);