regulator: tps80031: Support for delay configuration
Laxman Dewangan [Tue, 19 Jul 2011 14:04:57 +0000 (19:04 +0530)]
Adding support for delay configuration after setting the voltage
from platform data based on board behavior.
Also providing flag to enable the VBUS discharging though internal
pull down.

bug 853393

Change-Id: I27e7ae1eab9893241e775e17ec7b98afac71195b
Reviewed-on: http://git-master/r/41886
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>

Rebase-Id: R395c7ac35ccfabbea8de403d0db3cc4708981ab8

drivers/regulator/tps80031-regulator.c
include/linux/regulator/tps80031-regulator.h

index aeb672b..41c9b8f 100644 (file)
 #define OPA_MODE_EN            BIT(6)
 #define OPA_MODE_EN_MASK       BIT(6)
 
+#define USB_VBUS_CTRL_SET      0x04
+#define USB_VBUS_CTRL_CLR      0x05
+#define VBUS_DISCHRG           0x20
+
 #define EXT_PWR_REQ (PWR_REQ_INPUT_PREQ1 | PWR_REQ_INPUT_PREQ2 | \
                        PWR_REQ_INPUT_PREQ3)
 #define TPS80031_PREQ1_RES_ASS_A       0xD7
@@ -93,7 +97,7 @@ struct tps80031_regulator {
        u16                     max_mV;
 
        /* regulator specific turn-on delay */
-       u16                     delay;
+       int                     delay;
 
        u8                      flags;
        unsigned int            platform_flags;
@@ -550,6 +554,11 @@ static int tps80031ldo_get_voltage(struct regulator_dev *rdev)
 }
 
 /* VBUS */
+static int tps80031_vbus_enable_time(struct regulator_dev *rdev)
+{
+       /* Enable and settling time for vbus is 3ms */
+       return 3000;
+}
 static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
 {
        struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
@@ -603,19 +612,28 @@ static int tps80031_vbus_disable(struct regulator_dev *rdev)
 {
        struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
        struct device *parent = to_tps80031_dev(rdev);
-       int ret;
+       int ret = 0;
 
        if (ri->platform_flags & VBUS_SW_ONLY) {
-               ret = tps80031_clr_bits(parent, SLAVE_ID2,
+
+               if (ri->platform_flags & VBUS_DISCHRG_EN_PDN)
+                       ret = tps80031_write(parent, SLAVE_ID2,
+                               USB_VBUS_CTRL_SET, VBUS_DISCHRG);
+               if (!ret)
+                       ret = tps80031_clr_bits(parent, SLAVE_ID2,
                                CHARGERUSB_CTRL1_ADD,  OPA_MODE_EN);
                if (!ret)
                        ret = tps80031_clr_bits(parent, SLAVE_ID2,
                                        CHARGERUSB_CTRL3_ADD, BOOST_HW_PWR_EN);
-               if (ret < 0) {
+               if (!ret)
+                       mdelay((ri->delay + 999)/1000);
+
+               if (ri->platform_flags & VBUS_DISCHRG_EN_PDN)
+                       tps80031_write(parent, SLAVE_ID2,
+                               USB_VBUS_CTRL_CLR, VBUS_DISCHRG);
+
+               if (ret < 0)
                        dev_err(&rdev->dev, "Error in reading control reg\n");
-                       return ret;
-               }
-               udelay(ri->delay);
                return ret;
        }
        dev_err(&rdev->dev, "%s() is not supported with flag 0x%08x\n",
@@ -657,7 +675,7 @@ static struct regulator_ops tps80031vbus_ops = {
        .enable         = tps80031_vbus_enable,
        .disable        = tps80031_vbus_disable,
        .is_enabled     = tps80031_vbus_is_enabled,
-       .enable_time    = tps80031_regulator_enable_time,
+       .enable_time    = tps80031_vbus_enable_time,
 };
 
 #define TPS80031_REG(_id, _trans_reg, _state_reg, _force_reg, _volt_reg, \
@@ -717,7 +735,7 @@ static struct tps80031_regulator tps80031_regulator[] = {
        TPS80031_REG(VANA,   0x81, 0x82, 0x00, 0x83, SLAVE_ID1, 1000, 3300,
                                tps80031ldo_ops, 25, 500, -1),
        TPS80031_REG(VBUS,   0x0,  0x0,  0x00, 0x0,  SLAVE_ID1, 0,    5000,
-                               tps80031vbus_ops, 2, 500, -1),
+                               tps80031vbus_ops, 2, 200000, -1),
 };
 
 static int tps80031_power_req_config(struct device *parent,
@@ -925,6 +943,8 @@ static int __devinit tps80031_regulator_probe(struct platform_device *pdev)
        }
        tps_pdata = pdev->dev.platform_data;
        ri->dev = &pdev->dev;
+       if (tps_pdata->delay_us > 0)
+               ri->delay = tps_pdata->delay_us;
 
        check_smps_mode_mult(pdev->dev.parent, ri);
        ri->platform_flags = tps_pdata->flags;
index ed0838a..e76c4b8 100644 (file)
@@ -58,6 +58,7 @@ enum {
        LDO3_OUTPUT_VIB         = 0x00000004,
 
        /* VBUS configuration */
+       VBUS_DISCHRG_EN_PDN     = 0x00000004,
        VBUS_SW_ONLY            = 0x00000008,
        VBUS_SW_N_ID            = 0x00000010,
 
@@ -76,6 +77,7 @@ enum {
  * @init_apply: Init parameter applied or not.
  * @flags: Configuration flag to configure the rails. It should be ORed of
  *      above enums.
+ * @delay_us: Delay in microsecond after setting the desired voltage.
  */
 
 struct tps80031_regulator_platform_data {
@@ -84,6 +86,7 @@ struct tps80031_regulator_platform_data {
        unsigned init_enable:1;
        unsigned init_apply:1;
        unsigned int flags;
+       int delay_us;
 };
 
 #endif /* __REGULATOR_TPS80031_H */