]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
regulator: tps65090: Retry FET enable in case of failure
authorSimon Glass <sjg@chromium.org>
Mon, 26 Nov 2012 22:59:01 +0000 (14:59 -0800)
committerGerrit <chrome-bot@google.com>
Tue, 27 Nov 2012 23:24:30 +0000 (15:24 -0800)
Sometimes the FET fails to enable but instead gives a timeout error. This
may be a fault with the TPS65090. Turning off the FET and trying again seems
to clear the fault, so do this.

BUG=chrome-os-partner:16222
TEST=manual
Build and boot kernel using a firmware which does not enable the backlight.
See that LCD backlight turns on.

Also need to test on a unit which enhibits the 'no backlight on resume'
problem.

Change-Id: Idb5d867d32b4a290c6afd3d326e8c8f8678588d3
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/38679
Reviewed-by: Michael Spang <spang@chromium.org>
Tested-by: Michael Spang <spang@chromium.org>
Reviewed-by: Doug Anderson <dianders@chromium.org>
drivers/regulator/tps65090-regulator.c

index 58213dd2796f5da91c8e076f4970bae0b76e5e58..9376c7e3220c82f6d658d67a4a703ec604fc56ba 100644 (file)
@@ -32,6 +32,7 @@
 
 #define MAX_REGULATORS         10
 #define MAX_CTRL_READ_TRIES    5
+#define MAX_FET_ENABLE_TRIES   5
 
 #define CTRL_EN_BIT            0 /* Regulator enable bit, active high */
 #define CTRL_WT_BIT            2 /* Regulator wait time 0 bit */
@@ -76,13 +77,13 @@ static int tps65090_reg_read_ctrl(struct regulator_dev *rdev, uint8_t *ctrl)
 static int tps65090_reg_is_enabled(struct regulator_dev *rdev)
 {
        int ret;
-       uint8_t control;
+       uint8_t control, expected = (1 << CTRL_EN_BIT) | (1 << CTRL_PG_BIT);
 
        ret = tps65090_reg_read_ctrl(rdev, &control);
        if (ret < 0)
                return ret;
 
-       return (((control >> CTRL_EN_BIT) & 1) == 1);
+       return (control & expected) == expected;
 }
 
 static int tps65090_reg_set_overcurrent_wait(struct regulator_dev *rdev)
@@ -104,16 +105,20 @@ static int tps65090_reg_set_overcurrent_wait(struct regulator_dev *rdev)
        return ret;
 }
 
-static int tps65090_reg_enable(struct regulator_dev *rdev)
+/**
+ * tps6090_try_enable_fet - Try to enable a FET
+ *
+ * @rdev:      Regulator device
+ * @ri:                Our regulator info structure
+ * @parent:    Parent device (in this case a tps65090 mfd parent)
+ * @return 0 if ok, -ENOTRECOVERABLE if the FET power good bit did not get set,
+ * or some other -ve value if another error occurred (e.g. i2c error)
+ */
+static int tps6090_try_enable_fet(struct regulator_dev *rdev,
+               struct tps65090_regulator *ri, struct device *parent)
 {
-       struct tps65090_regulator *ri = rdev_get_drvdata(rdev);
-       struct device *parent = to_tps65090_dev(rdev);
-       int ret, i;
        uint8_t control;
-
-       ret = tps65090_reg_set_overcurrent_wait(rdev);
-       if (ret)
-               return ret;
+       int ret, i;
 
        ret = tps65090_set_bits(parent, ri->reg_en_reg, CTRL_EN_BIT);
        if (ret < 0) {
@@ -133,12 +138,50 @@ static int tps65090_reg_enable(struct regulator_dev *rdev)
                usleep_range(1000, 1500);
        }
        if (!(control & (1 << CTRL_PG_BIT)))
-               dev_warn(&rdev->dev, "reg 0x%x enable failed\n",
-                        ri->reg_en_reg);
+               return -ENOTRECOVERABLE;
 
        return 0;
 }
 
+static int tps65090_reg_enable(struct regulator_dev *rdev)
+{
+       struct tps65090_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps65090_dev(rdev);
+       int ret, tries;
+
+       ret = tps65090_reg_set_overcurrent_wait(rdev);
+       if (ret)
+               goto err;
+
+       /*
+        * Try enabling multiple times until we succeed since sometimes the
+        * first try times out.
+        */
+       for (tries = 0; ; tries++) {
+               ret = tps6090_try_enable_fet(rdev, ri, parent);
+               if (!ret)
+                       break;
+               if (ret != -ENOTRECOVERABLE || tries == MAX_FET_ENABLE_TRIES)
+                       goto err;
+
+               /* Try turning the FET off (and then on again) */
+               ret = tps65090_clr_bits(parent, ri->reg_en_reg, CTRL_EN_BIT);
+               if (ret)
+                       goto err;
+       }
+
+       if (tries) {
+               dev_warn(&rdev->dev, "reg 0x%x enable ok after %d tries\n",
+                        ri->reg_en_reg, tries);
+       }
+
+       return 0;
+err:
+       dev_warn(&rdev->dev, "reg 0x%x enable failed\n", ri->reg_en_reg);
+
+       return ret;
+}
+
 static int tps65090_reg_disable(struct regulator_dev *rdev)
 {
        struct tps65090_regulator *ri = rdev_get_drvdata(rdev);