regulator: palmas: implement errata for ES1.0,ES2.0 and ES2.1
[linux-2.6.git] / drivers / regulator / tps80031-regulator.c
index 704de70..1a6e970 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/regulator/tps80031-regulator.h>
 #include <linux/mfd/tps80031.h>
+#include <linux/module.h>
 
 /* Flags for DCDC Voltage reading */
 #define DCDC_OFFSET_EN         BIT(0)
 #define DCDC_EXTENDED_EN       BIT(1)
+#define TRACK_MODE_ENABLE      BIT(2)
 
 #define SMPS_MULTOFFSET_VIO    BIT(1)
 #define SMPS_MULTOFFSET_SMPS1  BIT(3)
 
 #define EXT_PWR_REQ (PWR_REQ_INPUT_PREQ1 | PWR_REQ_INPUT_PREQ2 | \
                        PWR_REQ_INPUT_PREQ3)
-#define TPS80031_PREQ1_RES_ASS_A       0xD7
-#define TPS80031_PREQ2_RES_ASS_A       0xDA
-#define TPS80031_PREQ3_RES_ASS_A       0xDD
-#define TPS80031_PHOENIX_MSK_TRANSITION        0x20
-
-struct tps80031_regulator {
 
+struct tps80031_regulator_info {
        /* Regulator register address.*/
        u8              trans_reg;
        u8              state_reg;
        u8              force_reg;
        u8              volt_reg;
        u8              volt_id;
-       uint8_t         trans_reg_cache;
-       uint8_t         state_reg_cache;
-       uint8_t         force_reg_cache;
-       uint8_t         volt_reg_cache;
-
-       /* twl resource ID, for resource control state machine */
-       u8                      id;
 
        /* chip constraints on regulator behavior */
        u16                     min_mV;
        u16                     max_mV;
 
-       /* regulator specific turn-on delay */
+       /* regulator specific turn-on delay as per datasheet*/
        int                     delay;
 
-       u8                      flags;
-       unsigned int            platform_flags;
-
        /* used by regulator core */
        struct regulator_desc   desc;
 
-       /* Device */
-       struct device           *dev;
-
        /*Power request bits */
        int preq_bit;
 };
 
+struct tps80031_regulator {
+       struct device                   *dev;
+       struct regulator_dev            *rdev;
+       struct tps80031_regulator_info  *rinfo;
+       unsigned int                    tolerance_uv;
+
+       /* Regulator specific turn-on delay if board file provided */
+       int                             delay;
+
+       u8                              flags;
+       unsigned int                    platform_flags;
+       unsigned int                    ext_ctrl_flag;
+
+       /* Cached register */
+       uint8_t         trans_reg_cache;
+       uint8_t         state_reg_cache;
+       uint8_t         force_reg_cache;
+       uint8_t         volt_reg_cache;
+};
+
 static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
 {
        return rdev_get_dev(rdev)->parent->parent;
@@ -162,7 +166,7 @@ static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
 {
        struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
 
-       if (ri->platform_flags & EXT_PWR_REQ)
+       if (ri->ext_ctrl_flag & EXT_PWR_REQ)
                return true;
        return ((ri->state_reg_cache & STATE_MASK) == STATE_ON);
 }
@@ -174,12 +178,12 @@ static int tps80031_reg_enable(struct regulator_dev *rdev)
        int ret;
        uint8_t reg_val;
 
-       if (ri->platform_flags & EXT_PWR_REQ)
+       if (ri->ext_ctrl_flag & EXT_PWR_REQ)
                return 0;
 
        reg_val = (ri->state_reg_cache & ~STATE_MASK) |
                                        (STATE_ON & STATE_MASK);
-       ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+       ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->state_reg, reg_val);
        if (ret < 0) {
                dev_err(&rdev->dev, "Error in writing the STATE register\n");
                return ret;
@@ -196,12 +200,12 @@ static int tps80031_reg_disable(struct regulator_dev *rdev)
        int ret;
        uint8_t reg_val;
 
-       if (ri->platform_flags & EXT_PWR_REQ)
+       if (ri->ext_ctrl_flag & EXT_PWR_REQ)
                return 0;
 
        reg_val = (ri->state_reg_cache & ~STATE_MASK) |
                                        (STATE_OFF & STATE_MASK);
-       ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+       ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->state_reg, reg_val);
        if (ret < 0)
                dev_err(&rdev->dev, "Error in writing the STATE register\n");
        else
@@ -222,7 +226,7 @@ static int tps80031dcdc_list_voltage(struct regulator_dev *rdev, unsigned index)
                if (index == 0)
                        voltage = 0;
                else if (index < 58)
-                       voltage = (600000 + (12500 * (index - 1)));
+                       voltage = (607700 + (12660 * (index - 1)));
                else if (index == 58)
                        voltage = 1350 * 1000;
                else if (index == 59)
@@ -300,14 +304,21 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
 
        switch (ri->flags) {
        case 0:
+               if (min_uV >= (607700 + ri->tolerance_uv))
+                       min_uV = min_uV - ri->tolerance_uv;
+
                if (min_uV == 0)
                        vsel = 0;
-               else if ((min_uV >= 600000) && (max_uV <= 1300000)) {
-                       vsel = (min_uV - 600000) / 125;
+               else if ((min_uV >= 607700) && (min_uV <= 1300000)) {
+                       int cal_volt;
+                       vsel = (10 * (min_uV - 607700)) / 1266;
                        if (vsel % 100)
                                vsel += 100;
                        vsel /= 100;
                        vsel++;
+                       cal_volt = (607700 + (12660 * (vsel - 1)));
+                       if (cal_volt > max_uV)
+                               return -EINVAL;
                } else if ((min_uV > 1900000) && (max_uV >= 2100000))
                        vsel = 62;
                else if ((min_uV > 1800000) && (max_uV >= 1900000))
@@ -323,19 +334,25 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
                break;
 
        case DCDC_OFFSET_EN:
+               if (min_uV >= (700000 + ri->tolerance_uv))
+                       min_uV = min_uV - ri->tolerance_uv;
                if (min_uV == 0)
                        vsel = 0;
-               else if ((min_uV >= 700000) && (max_uV <= 1420000)) {
-                       vsel = (min_uV - 600000) / 125;
+               else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
+                       int cal_volt;
+                       vsel = (min_uV - 700000) / 125;
                        if (vsel % 100)
                                vsel += 100;
                        vsel /= 100;
                        vsel++;
+                       cal_volt = (700000 + (12500 * (vsel - 1)));
+                       if (cal_volt > max_uV)
+                               return -EINVAL;
                } else if ((min_uV > 1900000) && (max_uV >= 2100000))
                        vsel = 62;
                else if ((min_uV > 1800000) && (max_uV >= 1900000))
                        vsel = 61;
-               else if ((min_uV > 1350000) && (max_uV >= 1800000))
+               else if ((min_uV > 1500000) && (max_uV >= 1800000))
                        vsel = 60;
                else if ((min_uV > 1350000) && (max_uV >= 1500000))
                        vsel = 59;
@@ -346,22 +363,25 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
                break;
 
        case DCDC_EXTENDED_EN:
+               if (min_uV >= (1852000 + ri->tolerance_uv))
+                       min_uV = min_uV - ri->tolerance_uv;
                if (min_uV == 0)
                        vsel = 0;
                else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
                        vsel = (min_uV - 1852000) / 386;
                        if (vsel % 100)
                                vsel += 100;
-                       vsel /= 100;
                        vsel++;
                }
                break;
 
        case DCDC_OFFSET_EN|DCDC_EXTENDED_EN:
+               if (min_uV >= (2161000 + ri->tolerance_uv))
+                       min_uV = min_uV - ri->tolerance_uv;
                if (min_uV == 0)
                        vsel = 0;
                else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
-                       vsel = (min_uV - 1852000) / 386;
+                       vsel = (min_uV - 2161000) / 386;
                        if (vsel % 100)
                                vsel += 100;
                        vsel /= 100;
@@ -373,10 +393,10 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
        if (selector)
                *selector = vsel;
 
-       if (ri->force_reg) {
+       if (ri->rinfo->force_reg) {
                if (((ri->force_reg_cache >> 6) & 0x3) == 0) {
-                       ret = tps80031_write(parent, ri->volt_id,
-                                               ri->force_reg, vsel);
+                       ret = tps80031_write(parent, ri->rinfo->volt_id,
+                                               ri->rinfo->force_reg, vsel);
                        if (ret < 0)
                                dev_err(ri->dev, "Error in writing the "
                                                "force register\n");
@@ -385,7 +405,8 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
                        return ret;
                }
        }
-       ret = tps80031_write(parent, ri->volt_id, ri->volt_reg, vsel);
+       ret = tps80031_write(parent, ri->rinfo->volt_id,
+                                       ri->rinfo->volt_reg, vsel);
        if (ret < 0)
                dev_err(ri->dev, "Error in writing the Voltage register\n");
        else
@@ -408,7 +429,7 @@ static int tps80031dcdc_get_voltage(struct regulator_dev *rdev)
        uint8_t vsel = 0;
        int voltage = 0;
 
-       if (ri->force_reg) {
+       if (ri->rinfo->force_reg) {
                vsel  = ri->force_reg_cache;
                if ((vsel & SMPS_CMD_MASK) == 0)
                        goto decode;
@@ -424,7 +445,7 @@ decode:
                if (vsel == 0)
                        voltage = 0;
                else if (vsel < 58)
-                       voltage = (600000 + (12500 * (vsel - 1)));
+                       voltage = (607700 + (12660 * (vsel - 1)));
                else if (vsel == 58)
                        voltage = 1350 * 1000;
                else if (vsel == 59)
@@ -499,9 +520,54 @@ static int tps80031ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
        if (index == 0)
                return 0;
 
-       return (ri->min_mV + ((index - 1) * 100)) * 1000;
+       if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+                       (ri->flags &  TRACK_MODE_ENABLE))
+               return (ri->rinfo->min_mV + (((index - 1) * 125))/10) * 1000;
+
+       return (ri->rinfo->min_mV + ((index - 1) * 100)) * 1000;
+}
+
+static int __tps80031_ldo2_set_voltage_track_mode(struct device *parent,
+               struct tps80031_regulator *ri, int min_uV, int max_uV)
+{
+       int vsel = 0;
+       int ret;
+       int nvsel;
+
+       if (min_uV < 600000) {
+               vsel = 0;
+       } else if ((min_uV >= 600000) && (max_uV <= 1300000)) {
+               vsel = (min_uV - 600000) / 125;
+               if (vsel % 100)
+                       vsel += 100;
+               vsel /= 100;
+               vsel++;
+       } else {
+               return -EINVAL;
+       }
+
+       /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */
+       if ((tps80031_get_chip_info(parent) == TPS80031) ||
+               ((tps80031_get_chip_info(parent) == TPS80032) &&
+               (tps80031_get_pmu_version(parent) == 0x0))) {
+               nvsel = vsel & 0x1F;
+               if ((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F)) {
+                       dev_err(ri->dev, "Invalid value for track mode LDO2 "
+                               "configuration for TPS8003x PMU\n");
+                       return -EINVAL;
+               }
+       }
+
+       ret = tps80031_write(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, vsel);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in writing the Voltage register\n");
+       else
+               ri->volt_reg_cache = vsel;
+       return ret;
 }
 
+
 static int __tps80031_ldo_set_voltage(struct device *parent,
                                      struct tps80031_regulator *ri,
                                      int min_uV, int max_uV,
@@ -510,15 +576,24 @@ static int __tps80031_ldo_set_voltage(struct device *parent,
        int vsel;
        int ret;
 
-       if ((min_uV/1000 < ri->min_mV) || (max_uV/1000 > ri->max_mV))
+       if ((min_uV/1000 < ri->rinfo->min_mV) ||
+                       (max_uV/1000 > ri->rinfo->max_mV))
                return -EDOM;
 
+       if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+                       (ri->flags &  TRACK_MODE_ENABLE))
+               return __tps80031_ldo2_set_voltage_track_mode(parent, ri,
+                               min_uV, max_uV);
+
        /*
         * Use the below formula to calculate vsel
         * mV = 1000mv + 100mv * (vsel - 1)
         */
        vsel = (min_uV/1000 - 1000)/100 + 1;
-       ret = tps80031_write(parent, ri->volt_id, ri->volt_reg, vsel);
+       if (selector)
+               *selector = vsel;
+       ret = tps80031_write(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, vsel);
        if (ret < 0)
                dev_err(ri->dev, "Error in writing the Voltage register\n");
        else
@@ -541,8 +616,14 @@ static int tps80031ldo_get_voltage(struct regulator_dev *rdev)
        struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
        uint8_t vsel;
 
-       vsel = ri->volt_reg_cache & LDO_VSEL_MASK;
 
+       if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+                       (ri->flags &  TRACK_MODE_ENABLE)) {
+               vsel = ri->volt_reg_cache & 0x3F;
+               return (ri->rinfo->min_mV + (((vsel - 1) * 125))/10) * 1000;
+       }
+
+       vsel = ri->volt_reg_cache & LDO_VSEL_MASK;
        /*
         * Use the below formula to calculate vsel
         * mV = 1000mv + 100mv * (vsel - 1)
@@ -647,6 +728,22 @@ static int tps80031vbus_get_voltage(struct regulator_dev *rdev)
        return ret;
 }
 
+static int tps80031_extreg_enable_time(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       return ri->delay;
+}
+
+static int tps80031_extreg_get_voltage(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       int ret;
+       ret = tps80031_reg_is_enabled(rdev);
+       if (ret > 0)
+               return ri->rinfo->max_mV * 1000;
+       return 0;
+}
+
 static struct regulator_ops tps80031dcdc_ops = {
        .list_voltage   = tps80031dcdc_list_voltage,
        .set_voltage    = tps80031dcdc_set_voltage,
@@ -675,6 +772,16 @@ static struct regulator_ops tps80031vbus_ops = {
        .enable_time    = tps80031_vbus_enable_time,
 };
 
+static struct regulator_ops tps80031_ext_reg_ops = {
+       .enable         = tps80031_reg_enable,
+       .disable        = tps80031_reg_disable,
+       .is_enabled     = tps80031_reg_is_enabled,
+       .enable_time    = tps80031_extreg_enable_time,
+       .get_voltage    = tps80031_extreg_get_voltage,
+};
+
+
+
 #define TPS80031_REG(_id, _trans_reg, _state_reg, _force_reg, _volt_reg, \
                _volt_id, min_mVolts, max_mVolts, _ops, _n_volt, _delay, \
                _preq_bit)                                               \
@@ -684,12 +791,11 @@ static struct regulator_ops tps80031vbus_ops = {
        .force_reg = _force_reg,                                \
        .volt_reg = _volt_reg,                                  \
        .volt_id = _volt_id,                                    \
-       .id = TPS80031_ID_##_id,                                \
        .min_mV = min_mVolts,                                   \
        .max_mV = max_mVolts,                                   \
        .desc = {                                               \
                .name = tps80031_rails(_id),                    \
-               .id = TPS80031_ID_##_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
                .n_voltages = _n_volt,                          \
                .ops = &_ops,                                   \
                .type = REGULATOR_VOLTAGE,                      \
@@ -699,7 +805,7 @@ static struct regulator_ops tps80031vbus_ops = {
        .preq_bit = _preq_bit,                                  \
 }
 
-static struct tps80031_regulator tps80031_regulator[] = {
+static struct tps80031_regulator_info tps80031_regulator_info[] = {
        TPS80031_REG(VIO,   0x47, 0x48, 0x49, 0x4A, SLAVE_ID0, 600, 2100,
                                tps80031dcdc_ops, 63, 500, 4),
        TPS80031_REG(SMPS1, 0x53, 0x54, 0x55, 0x56, SLAVE_ID0, 600, 2100,
@@ -733,88 +839,51 @@ static struct tps80031_regulator tps80031_regulator[] = {
                                tps80031ldo_ops, 25, 500, -1),
        TPS80031_REG(VBUS,   0x0,  0x0,  0x00, 0x0,  SLAVE_ID1, 0,    5000,
                                tps80031vbus_ops, 2, 200000, -1),
+       TPS80031_REG(REGEN1, 0xAE,  0xAF,  0x00, 0x0,  SLAVE_ID1, 0,    3300,
+                               tps80031_ext_reg_ops, 2, 500, 16),
+       TPS80031_REG(REGEN2, 0xB1,  0xB2,  0x00, 0x0,  SLAVE_ID1, 0,    3300,
+                               tps80031_ext_reg_ops, 2, 500, 17),
+       TPS80031_REG(SYSEN,  0xB4,  0xB5,  0x00, 0x0,  SLAVE_ID1, 0,    3300,
+                               tps80031_ext_reg_ops, 2, 500, 18),
 };
 
 static int tps80031_power_req_config(struct device *parent,
                struct tps80031_regulator *ri,
                struct tps80031_regulator_platform_data *tps80031_pdata)
 {
-       u8 res_ass_reg;
-       int preq_bit;
-       int preq_mask_bit;
-       int ret;
+       int ret = 0;
        uint8_t reg_val;
 
-       /* Clear all external control for this rail */
-       ret = tps80031_clr_bits(parent, SLAVE_ID1,
-                       TPS80031_PREQ1_RES_ASS_A + (ri->preq_bit >> 3),
-                       BIT(ri->preq_bit & 0x7));
-       if (!ret)
-               ret = tps80031_clr_bits(parent, SLAVE_ID1,
-                               TPS80031_PREQ2_RES_ASS_A + (ri->preq_bit >> 3),
-                               BIT(ri->preq_bit & 0x7));
-       if (!ret)
-               ret = tps80031_clr_bits(parent, SLAVE_ID1,
-                               TPS80031_PREQ3_RES_ASS_A + (ri->preq_bit >> 3),
-                               BIT(ri->preq_bit & 0x7));
-       if (ret < 0) {
-               dev_err(ri->dev, "%s() Not able to clr bit %d of "
-                       "TPS80031_PREQ_RES_ASS error %d\n",
-                       __func__, preq_bit, ret);
-               return ret;
-       }
-
-       if (!(ri->platform_flags & EXT_PWR_REQ))
-               return 0;
+       if (ri->rinfo->preq_bit < 0)
+               goto skip_pwr_req_config;
 
-       preq_bit = ri->preq_bit & 0x7;
-       if (ri->platform_flags & PWR_REQ_INPUT_PREQ1) {
-               res_ass_reg = TPS80031_PREQ1_RES_ASS_A + (ri->preq_bit >> 3);
-               preq_mask_bit = 5;
-       } else if (ri->platform_flags & PWR_REQ_INPUT_PREQ2) {
-               res_ass_reg = TPS80031_PREQ2_RES_ASS_A + (ri->preq_bit >> 3);
-               preq_mask_bit = 6;
-       } else if (ri->platform_flags & PWR_REQ_INPUT_PREQ3) {
-               res_ass_reg = TPS80031_PREQ3_RES_ASS_A + (ri->preq_bit >> 3);
-               preq_mask_bit = 7;
-       }
+       ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
+                       ri->rinfo->preq_bit, ri->rinfo->state_reg,
+                       ri->rinfo->trans_reg);
+       if (!ret)
+               ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->trans_reg,
+                       &ri->trans_reg_cache);
 
-       /* Configure REQ_ASS registers */
-       ret = tps80031_set_bits(parent, SLAVE_ID1, res_ass_reg, BIT(preq_bit));
+       if (!ret && ri->rinfo->state_reg)
+               ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->state_reg,
+                       &ri->state_reg_cache);
        if (ret < 0) {
-               dev_err(ri->dev, "%s() Not able to set bit %d of "
-                       "reg %d error %d\n",
-                       __func__, preq_bit, res_ass_reg, ret);
+               dev_err(ri->dev, "%s() fails\n", __func__);
                return ret;
        }
 
-       /* Unmask the PREQ */
-       ret = tps80031_clr_bits(parent, SLAVE_ID1,
-                       TPS80031_PHOENIX_MSK_TRANSITION, BIT(preq_mask_bit));
-       if (ret < 0) {
-               dev_err(ri->dev, "%s() Not able to clear bit %d of "
-                       "reg %d error %d\n",
-                        __func__, preq_mask_bit,
-                       TPS80031_PHOENIX_MSK_TRANSITION, ret);
-               return ret;
-       }
+skip_pwr_req_config:
+       if (tps80031_pdata->ext_ctrl_flag &
+                       (PWR_OFF_ON_SLEEP | PWR_ON_ON_SLEEP)) {
+               reg_val = (ri->trans_reg_cache & ~0xC);
+               if (tps80031_pdata->ext_ctrl_flag & PWR_ON_ON_SLEEP)
+                       reg_val |= 0x4;
 
-       /* Switch regulator control to resource now */
-       if (ri->platform_flags &  (PWR_REQ_INPUT_PREQ2 | PWR_REQ_INPUT_PREQ3)) {
-               reg_val = (ri->state_reg_cache & ~STATE_MASK);
-               ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+               ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->trans_reg,
+                       reg_val);
                if (ret < 0)
-                       dev_err(ri->dev, "%s() Error in writing the STATE "
-                               "register error %d\n", __func__, ret);
-               else
-                       ri->state_reg_cache = reg_val;
-       } else {
-               reg_val = (ri->trans_reg_cache & ~TRANS_SLEEP_MASK) |
-                                       TRANS_SLEEP_OFF;
-               ret = tps80031_write(parent, SLAVE_ID1, ri->trans_reg, reg_val);
-               if (ret < 0)
-                       dev_err(ri->dev, "%s() Error in writing the TRANS "
-                               "register error %d\n", __func__, ret);
+                       dev_err(ri->dev, "Not able to write reg 0x%02x\n",
+                               ri->rinfo->trans_reg);
                else
                        ri->trans_reg_cache = reg_val;
        }
@@ -828,7 +897,7 @@ static int tps80031_regulator_preinit(struct device *parent,
        int ret = 0;
        uint8_t reg_val;
 
-       if (ri->desc.id == TPS80031_ID_LDOUSB) {
+       if (ri->rinfo->desc.id == TPS80031_REGULATOR_LDOUSB) {
                if (ri->platform_flags & USBLDO_INPUT_VSYS)
                        ret = tps80031_update(parent, SLAVE_ID1,
                                TPS80031_MISC2_ADD,
@@ -844,7 +913,7 @@ static int tps80031_regulator_preinit(struct device *parent,
                }
        }
 
-       if (ri->desc.id == TPS80031_ID_LDO3) {
+       if (ri->rinfo->desc.id == TPS80031_REGULATOR_LDO3) {
                if (ri->platform_flags & LDO3_OUTPUT_VIB)
                        ret = tps80031_update(parent, SLAVE_ID1,
                                TPS80031_MISC2_ADD,
@@ -857,31 +926,59 @@ static int tps80031_regulator_preinit(struct device *parent,
                }
        }
 
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_REGEN1:
+       case TPS80031_REGULATOR_REGEN2:
+       case TPS80031_REGULATOR_SYSEN:
+               if (tps80031_pdata->reg_init_data->constraints.always_on ||
+                       tps80031_pdata->reg_init_data->constraints.boot_on)
+                       ret = tps80031_update(parent, SLAVE_ID1,
+                               ri->rinfo->state_reg, STATE_ON, STATE_MASK);
+               else
+                       ret = tps80031_update(parent, SLAVE_ID1,
+                               ri->rinfo->state_reg, STATE_OFF, STATE_MASK);
+               if (ret < 0) {
+                       dev_err(ri->dev,
+                               "state reg update failed, e %d\n", ret);
+                       return ret;
+               }
+               ret = tps80031_update(parent, SLAVE_ID1,
+                                       ri->rinfo->trans_reg, 1, 0x3);
+               if (ret < 0) {
+                       dev_err(ri->dev,
+                               "trans reg update failed, e %d\n", ret);
+                       return ret;
+               }
+               break;
+       default:
+               break;
+       }
+
        if (!tps80031_pdata->init_apply)
                return 0;
 
        if (tps80031_pdata->init_uV >= 0) {
-               switch (ri->desc.id) {
-               case TPS80031_ID_VIO:
-               case TPS80031_ID_SMPS1:
-               case TPS80031_ID_SMPS2:
-               case TPS80031_ID_SMPS3:
-               case TPS80031_ID_SMPS4:
+               switch (ri->rinfo->desc.id) {
+               case TPS80031_REGULATOR_VIO:
+               case TPS80031_REGULATOR_SMPS1:
+               case TPS80031_REGULATOR_SMPS2:
+               case TPS80031_REGULATOR_SMPS3:
+               case TPS80031_REGULATOR_SMPS4:
                        ret = __tps80031_dcdc_set_voltage(parent, ri,
                                        tps80031_pdata->init_uV,
                                        tps80031_pdata->init_uV, 0);
                        break;
 
-               case TPS80031_ID_LDO1:
-               case TPS80031_ID_LDO2:
-               case TPS80031_ID_LDO3:
-               case TPS80031_ID_LDO4:
-               case TPS80031_ID_LDO5:
-               case TPS80031_ID_LDO6:
-               case TPS80031_ID_LDO7:
-               case TPS80031_ID_LDOUSB:
-               case TPS80031_ID_LDOLN:
-               case TPS80031_ID_VANA:
+               case TPS80031_REGULATOR_LDO1:
+               case TPS80031_REGULATOR_LDO2:
+               case TPS80031_REGULATOR_LDO3:
+               case TPS80031_REGULATOR_LDO4:
+               case TPS80031_REGULATOR_LDO5:
+               case TPS80031_REGULATOR_LDO6:
+               case TPS80031_REGULATOR_LDO7:
+               case TPS80031_REGULATOR_LDOUSB:
+               case TPS80031_REGULATOR_LDOLN:
+               case TPS80031_REGULATOR_VANA:
                        ret = __tps80031_ldo_set_voltage(parent, ri,
                                        tps80031_pdata->init_uV,
                                        tps80031_pdata->init_uV, 0);
@@ -894,7 +991,7 @@ static int tps80031_regulator_preinit(struct device *parent,
                if (ret < 0) {
                        dev_err(ri->dev, "Not able to initialize voltage %d "
                                "for rail %d err %d\n", tps80031_pdata->init_uV,
-                               ri->desc.id, ret);
+                               ri->rinfo->desc.id, ret);
                        return ret;
                }
        }
@@ -906,25 +1003,25 @@ static int tps80031_regulator_preinit(struct device *parent,
                reg_val = (ri->state_reg_cache & ~STATE_MASK) |
                                (STATE_OFF & STATE_MASK);
 
-       ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+       ret = tps80031_write(parent, SLAVE_ID1, ri->rinfo->state_reg, reg_val);
        if (ret < 0)
                dev_err(ri->dev, "Not able to %s rail %d err %d\n",
                        (tps80031_pdata->init_enable) ? "enable" : "disable",
-                       ri->desc.id, ret);
+                       ri->rinfo->desc.id, ret);
        else
                ri->state_reg_cache = reg_val;
        return ret;
 }
 
-static inline struct tps80031_regulator *find_regulator_info(int id)
+static inline struct tps80031_regulator_info *find_regulator_info(int id)
 {
-       struct tps80031_regulator *ri;
+       struct tps80031_regulator_info *rinfo;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(tps80031_regulator); i++) {
-               ri = &tps80031_regulator[i];
-               if (ri->desc.id == id)
-                       return ri;
+       for (i = 0; i < ARRAY_SIZE(tps80031_regulator_info); i++) {
+               rinfo = &tps80031_regulator_info[i];
+               if (rinfo->desc.id == id)
+                       return rinfo;
        }
        return NULL;
 }
@@ -932,22 +1029,32 @@ static void check_smps_mode_mult(struct device *parent,
        struct tps80031_regulator *ri)
 {
        int mult_offset;
-       switch (ri->desc.id) {
-       case TPS80031_ID_VIO:
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_VIO:
                mult_offset = SMPS_MULTOFFSET_VIO;
                break;
-       case TPS80031_ID_SMPS1:
+       case TPS80031_REGULATOR_SMPS1:
                mult_offset = SMPS_MULTOFFSET_SMPS1;
                break;
-       case TPS80031_ID_SMPS2:
+       case TPS80031_REGULATOR_SMPS2:
                mult_offset = SMPS_MULTOFFSET_SMPS2;
                break;
-       case TPS80031_ID_SMPS3:
+       case TPS80031_REGULATOR_SMPS3:
                mult_offset = SMPS_MULTOFFSET_SMPS3;
                break;
-       case TPS80031_ID_SMPS4:
+       case TPS80031_REGULATOR_SMPS4:
                mult_offset = SMPS_MULTOFFSET_SMPS4;
                break;
+       case TPS80031_REGULATOR_LDO2:
+               ri->flags = (tps80031_get_smps_mult(parent) & (1 << 5)) ?
+                                               TRACK_MODE_ENABLE : 0;
+               /* TRACK mode the ldo2 varies from 600mV to 1300mV */
+               if (ri->flags & TRACK_MODE_ENABLE) {
+                       ri->rinfo->min_mV = 600;
+                       ri->rinfo->max_mV = 1300;
+                       ri->rinfo->desc.n_voltages = 57;
+               }
+               return;
        default:
                return;
        }
@@ -964,80 +1071,136 @@ static inline int tps80031_cache_regulator_register(struct device *parent,
 {
        int ret;
 
-       ret = tps80031_read(parent, SLAVE_ID1, ri->trans_reg,
+       ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->trans_reg,
                        &ri->trans_reg_cache);
-       if (!ret && ri->state_reg)
-               ret = tps80031_read(parent, SLAVE_ID1, ri->state_reg,
+       if (!ret && ri->rinfo->state_reg)
+               ret = tps80031_read(parent, SLAVE_ID1, ri->rinfo->state_reg,
                        &ri->state_reg_cache);
-       if (!ret && ri->force_reg)
-               ret = tps80031_read(parent, ri->volt_id, ri->force_reg,
-                       &ri->force_reg_cache);
-       if (!ret && ri->volt_reg)
-               ret = tps80031_read(parent, ri->volt_id, ri->volt_reg,
-                       &ri->volt_reg_cache);
+       if (!ret && ri->rinfo->force_reg)
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->force_reg, &ri->force_reg_cache);
+       if (!ret && ri->rinfo->volt_reg)
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, &ri->volt_reg_cache);
        return ret;
 }
 
 static int __devinit tps80031_regulator_probe(struct platform_device *pdev)
 {
-       struct tps80031_regulator *ri = NULL;
-       struct regulator_dev *rdev;
+       struct tps80031_platform_data *pdata = dev_get_platdata(pdev->dev.parent);
        struct tps80031_regulator_platform_data *tps_pdata;
-       int id = pdev->id;
-       int err;
-
-       dev_dbg(&pdev->dev, "Probing reulator %d\n", id);
+       struct tps80031_regulator_info *rinfo;
+       struct tps80031_regulator *ri;
+       struct tps80031_regulator *pmic;
+       struct regulator_dev *rdev;
+       int id;
+       int ret;
+       int num;
 
-       ri = find_regulator_info(id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+       if (!pdata || !pdata->num_regulator_pdata) {
+               dev_err(&pdev->dev, "Number of regulator is 0\n");
                return -EINVAL;
        }
-       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;
-
-       err = tps80031_cache_regulator_register(pdev->dev.parent, ri);
-       if (err) {
-               dev_err(&pdev->dev, "Register access for caching is failed\n");
-               return err;
-       }
-       err = tps80031_regulator_preinit(pdev->dev.parent, ri, tps_pdata);
-       if (err)
-               return err;
-
-       err = tps80031_power_req_config(pdev->dev.parent, ri, tps_pdata);
-       if (err)
-               return err;
-
-       rdev = regulator_register(&ri->desc, &pdev->dev,
-                               &tps_pdata->regulator, ri);
-       if (IS_ERR_OR_NULL(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
+
+       pmic = devm_kzalloc(&pdev->dev,
+                       pdata->num_regulator_pdata * sizeof(*pmic), GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
        }
 
-       platform_set_drvdata(pdev, rdev);
+       for (num = 0; num < pdata->num_regulator_pdata; ++num) {
+               tps_pdata = pdata->regulator_pdata[num];
+               if (!tps_pdata->reg_init_data) {
+                       dev_err(&pdev->dev,
+                               "No regulator init data for index %d\n", num);
+                       ret = -EINVAL;
+                       goto fail;
+               }
+
+               id = tps_pdata->regulator_id;
+               rinfo = find_regulator_info(id);
+               if (!rinfo) {
+                       dev_err(&pdev->dev, "invalid regulator ID specified\n");
+                       ret = -EINVAL;
+                       goto fail;
+               }
+
+               ri = &pmic[num];
+               ri->rinfo = rinfo;
+               ri->dev = &pdev->dev;
+               if (tps_pdata->delay_us)
+                       ri->delay = tps_pdata->delay_us;
+               else
+                       ri->delay = rinfo->delay;
+               ri->tolerance_uv = tps_pdata->tolerance_uv;
+
+               check_smps_mode_mult(pdev->dev.parent, ri);
+               ri->platform_flags = tps_pdata->flags;
+               ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
 
+               ret = tps80031_cache_regulator_register(pdev->dev.parent, ri);
+               if (ret < 0) {
+                       dev_err(&pdev->dev,
+                               "Register cache failed, err %d\n", ret);
+                       goto fail;
+               }
+               ret = tps80031_regulator_preinit(pdev->dev.parent, ri, tps_pdata);
+               if (ret < 0) {
+                       dev_err(&pdev->dev,
+                               "regulator preinit failed, err %d\n", ret);
+                       goto fail;
+               }
+
+               ret = tps80031_power_req_config(pdev->dev.parent, ri, tps_pdata);
+               if (ret < 0) {
+                       dev_err(&pdev->dev,
+                               "power req config failed, err %d\n", ret);
+                       goto fail;
+               }
+
+               rdev = regulator_register(&ri->rinfo->desc, &pdev->dev,
+                               tps_pdata->reg_init_data, ri, NULL);
+               if (IS_ERR_OR_NULL(rdev)) {
+                       dev_err(&pdev->dev,
+                               "register regulator failed %s\n",
+                                       ri->rinfo->desc.name);
+                       ret = PTR_ERR(rdev);
+                       goto fail;
+               }
+               ri->rdev = rdev;
+       }
+
+       platform_set_drvdata(pdev, pmic);
        return 0;
+fail:
+       while(--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
 }
 
 static int __devexit tps80031_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct tps80031_platform_data *pdata = pdev->dev.parent->platform_data;
+       struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps80031_regulator *ri = NULL;
+       int num;
+
+       if (!pdata || !pdata->num_regulator_pdata)
+               return 0;
 
-       regulator_unregister(rdev);
+       for (num = 0; num < pdata->num_regulator_pdata; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
        return 0;
 }
 
 static struct platform_driver tps80031_regulator_driver = {
        .driver = {
-               .name   = "tps80031-regulator",
+               .name   = "tps80031-regulators",
                .owner  = THIS_MODULE,
        },
        .probe          = tps80031_regulator_probe,