regulator: palmas: preserve mode configuration across enable/disable
Laxman Dewangan [Mon, 11 Feb 2013 13:13:56 +0000 (18:13 +0530)]
If regulator rail is configured for a desired mode and
if this rail get disable and again enable then mode
get reset to normal.

Store the desired mode locally and when it enabled, use the stored
preconfigured mode for enabling regulator.

bug 1231293

Change-Id: I396d91609dd91a4f3c682e1279c6f851cda4b94f
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/199434
Reviewed-by: Riham Haidar <rhaidar@nvidia.com>
Tested-by: Riham Haidar <rhaidar@nvidia.com>

drivers/regulator/palmas-regulator.c
include/linux/mfd/palmas.h

index 5c233bf..b543df1 100644 (file)
@@ -305,7 +305,10 @@ static int palmas_enable_smps(struct regulator_dev *dev)
        palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
 
        reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
-       reg |= SMPS_CTRL_MODE_ON;
+       if (pmic->current_mode_reg[id])
+               reg |= pmic->current_mode_reg[id];
+       else
+               reg |= SMPS_CTRL_MODE_ON;
 
        palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg);
 
@@ -327,16 +330,19 @@ static int palmas_disable_smps(struct regulator_dev *dev)
        return 0;
 }
 
-
 static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
 {
        struct palmas_pmic *pmic = rdev_get_drvdata(dev);
        int id = rdev_get_id(dev);
        unsigned int reg;
+       int avoid_update = 0;
 
        palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
        reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 
+       if (reg == SMPS_CTRL_MODE_OFF)
+               avoid_update = 1;
+
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
                reg |= SMPS_CTRL_MODE_ON;
@@ -347,11 +353,16 @@ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
        case REGULATOR_MODE_FAST:
                reg |= SMPS_CTRL_MODE_PWM;
                break;
+       case REGULATOR_MODE_STANDBY:
+               reg |= SMPS_CTRL_MODE_OFF;
+               break;
        default:
                return -EINVAL;
        }
-       palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg);
-
+       pmic->current_mode_reg[id] = reg & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
+       if (!avoid_update)
+               palmas_smps_write(pmic->palmas,
+                       palmas_regs_info[id].ctrl_addr, reg);
        return 0;
 }
 
@@ -361,9 +372,7 @@ static unsigned int palmas_get_mode_smps(struct regulator_dev *dev)
        int id = rdev_get_id(dev);
        unsigned int reg;
 
-       palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
-       reg &= PALMAS_SMPS12_CTRL_STATUS_MASK;
-       reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
+       reg = pmic->current_mode_reg[id] & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 
        switch (reg) {
        case SMPS_CTRL_MODE_ON:
@@ -372,6 +381,8 @@ static unsigned int palmas_get_mode_smps(struct regulator_dev *dev)
                return REGULATOR_MODE_IDLE;
        case SMPS_CTRL_MODE_PWM:
                return REGULATOR_MODE_FAST;
+       case SMPS_CTRL_MODE_OFF:
+               return REGULATOR_MODE_STANDBY;
        }
 
        return 0;
@@ -1337,6 +1348,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                 * read and store the RANGE bit for later use
                 * This must be done before regulator is probed otherwise
                 * we error in probe with unsuportable ranges.
+                * Read the smps mode for later use.
                 */
                if (id != PALMAS_REG_SMPS10) {
                        addr = palmas_regs_info[id].vsel_addr;
@@ -1346,6 +1358,14 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                goto err_unregister_regulator;
                        if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
                                pmic->range[id] = 1;
+
+                       /* Read the smps mode for later use. */
+                       addr = palmas_regs_info[id].ctrl_addr;
+                       ret = palmas_smps_read(pmic->palmas, addr, &reg);
+                       if (ret)
+                               goto err_unregister_regulator;
+                       pmic->current_mode_reg[id] = reg &
+                                       PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
                }
 
                rdev = regulator_register(&pmic->desc[id],
index 4dfc50b..3c21eaa 100644 (file)
@@ -279,6 +279,7 @@ struct palmas_pmic {
        int smps457;
 
        unsigned int ramp_delay[PALMAS_NUM_REGS];
+       unsigned int current_mode_reg[PALMAS_NUM_REGS];
 
        int range[PALMAS_REG_SMPS10];
 };