regulator: tps65090: Set overcurrent wait time
authorSean Paul <seanpaul@chromium.org>
Thu, 9 Aug 2012 21:20:14 +0000 (14:20 -0700)
committerGerrit <chrome-bot@google.com>
Fri, 10 Aug 2012 00:40:28 +0000 (17:40 -0700)
Get the overcurrent wait time for regulators out of the device tree and
set it when enabling the regulator. This fixes some errors observed
where the rail wasn't always recovering from suspend. The scope trace
showed a 500us plateau in the voltage when it was ramping up to full.

BUG=chrome-os-partner:12360
TEST=Multiple suspend/resume cycles with no issues

Change-Id: Ice37298a435e0b5f25cf307b0620319f6dbc75f7
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/29659
Reviewed-by: Doug Anderson <dianders@chromium.org>
drivers/mfd/tps65090.c
drivers/regulator/tps65090-regulator.c
include/linux/mfd/tps65090.h

index 07629a1..6e71907 100644 (file)
@@ -109,6 +109,14 @@ int tps65090_read(struct device *dev, int reg, uint8_t *val)
 }
 EXPORT_SYMBOL_GPL(tps65090_read);
 
+int tps65090_update_bits(struct device *dev, int reg, unsigned int mask,
+                        unsigned int val)
+{
+       struct tps65090 *tps = dev_get_drvdata(dev);
+       return regmap_update_bits(tps->rmap, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(tps65090_update_bits);
+
 int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num)
 {
        struct tps65090 *tps = dev_get_drvdata(dev);
index 17d89e4..433b180 100644 (file)
 #define MAX_REGULATORS         10
 
 #define CTRL_EN_BIT            0 /* Regulator enable bit, active high */
+#define CTRL_WT_BIT            2 /* Regulator wait time 0 bit */
+
+#define MAX_OVERCURRENT_WAIT   3 /* Overcurrent wait must be less than this */
 
 struct tps65090_regulator {
        /* Regulator register address.*/
        u32             reg_en_reg;
+       u32             reg_overcurrent_wait;
 
        /* used by regulator core */
        struct regulator_desc   desc;
@@ -69,12 +73,35 @@ static int tps65090_reg_is_enabled(struct regulator_dev *rdev)
        return (((control >> CTRL_EN_BIT) & 1) == 1);
 }
 
+static int tps65090_reg_set_overcurrent_wait(struct regulator_dev *rdev)
+{
+       struct tps65090_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps65090_dev(rdev);
+       int ret;
+
+       if (ri->reg_overcurrent_wait > MAX_OVERCURRENT_WAIT)
+               return 0;
+
+       ret = tps65090_update_bits(parent, ri->reg_en_reg,
+                       MAX_OVERCURRENT_WAIT << CTRL_WT_BIT,
+                       ri->reg_overcurrent_wait << CTRL_WT_BIT);
+       if (ret)
+               dev_err(&rdev->dev, "Error updating overcurrent wait 0x%x\n",
+                       ri->reg_en_reg);
+
+       return ret;
+}
+
 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;
 
+       ret = tps65090_reg_set_overcurrent_wait(rdev);
+       if (ret)
+               return ret;
+
        ret = tps65090_set_bits(parent, ri->reg_en_reg, CTRL_EN_BIT);
        if (ret < 0)
                dev_err(&rdev->dev, "Error in updating reg 0x%x\n",
@@ -183,6 +210,12 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
                        goto out;
                }
 
+               if (of_property_read_u32(np, "tps65090-overcurrent-wait",
+                                        &reg->reg_overcurrent_wait)) {
+                       /* Overcurrent wait is optional, set to invalid */
+                       reg->reg_overcurrent_wait = MAX_OVERCURRENT_WAIT + 1;
+               }
+
                reg->desc.id = id;
                reg->desc.ops = &tps65090_ops;
                reg->desc.type = REGULATOR_VOLTAGE;
index 9dc2940..ccc1ed3 100644 (file)
@@ -28,6 +28,8 @@
  */
 extern int tps65090_write(struct device *dev, int reg, uint8_t val);
 extern int tps65090_read(struct device *dev, int reg, uint8_t *val);
+extern int tps65090_update_bits(struct device *dev, int reg, unsigned int mask,
+                               unsigned int val);
 extern int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num);
 extern int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num);