summaryrefslogtreecommitdiff
path: root/drivers/regulator/tps80031-regulator.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2011-09-14 16:47:50 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:14 -0800
commit71247849dd7c3c23bf0c6c214995a74aa7ff4ed6 (patch)
treea89f02cb2cfe1c4b5b988107692f4e33d06de255 /drivers/regulator/tps80031-regulator.c
parent9ab2d755d9ec61c6cc30c01b3d08f98e79e5d2ca (diff)
regulator: tps80031: Optimize voltage change by register cache
Using the register caching for optimizing the update of pmu register through i2c. In this way, the frequent read of pmu register is avoided. bug 870689 Reviewed-on: http://git-master/r/56617 (cherry picked from commit 59426b56710e06b075769b4eb73723c3dcf28710) Change-Id: I9fc339587c8c5c82443bb99489992d608fd3534e Reviewed-on: http://git-master/r/56872 Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> Tested-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Bitan Biswas <bbiswas@nvidia.com> Rebase-Id: Reb0312eaaa88f9b082c540b752663089964ffee8
Diffstat (limited to 'drivers/regulator/tps80031-regulator.c')
-rw-r--r--drivers/regulator/tps80031-regulator.c132
1 files changed, 73 insertions, 59 deletions
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index 41c9b8fe7d07..2cb0e6df1ef8 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -88,6 +88,10 @@ struct tps80031_regulator {
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;
@@ -153,19 +157,10 @@ static u8 tps80031_get_smps_mult(struct device *parent)
static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
{
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
- struct device *parent = to_tps80031_dev(rdev);
- uint8_t state;
- int ret;
if (ri->platform_flags & EXT_PWR_REQ)
return true;
-
- ret = tps80031_read(parent, SLAVE_ID1, ri->state_reg, &state);
- if (ret < 0) {
- dev_err(&rdev->dev, "Error in reading the STATE register\n");
- return ret;
- }
- return ((state & STATE_MASK) == STATE_ON);
+ return ((ri->state_reg_cache & STATE_MASK) == STATE_ON);
}
static int tps80031_reg_enable(struct regulator_dev *rdev)
@@ -173,16 +168,19 @@ static int tps80031_reg_enable(struct regulator_dev *rdev)
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps80031_dev(rdev);
int ret;
+ uint8_t reg_val;
if (ri->platform_flags & EXT_PWR_REQ)
return 0;
- ret = tps80031_force_update(parent, SLAVE_ID1, ri->state_reg, STATE_ON,
- STATE_MASK);
+ reg_val = (ri->state_reg_cache & ~STATE_MASK) |
+ (STATE_ON & STATE_MASK);
+ ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
if (ret < 0) {
- dev_err(&rdev->dev, "Error in updating the STATE register\n");
+ dev_err(&rdev->dev, "Error in writing the STATE register\n");
return ret;
}
+ ri->state_reg_cache = reg_val;
udelay(ri->delay);
return ret;
}
@@ -192,15 +190,18 @@ static int tps80031_reg_disable(struct regulator_dev *rdev)
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps80031_dev(rdev);
int ret;
+ uint8_t reg_val;
if (ri->platform_flags & EXT_PWR_REQ)
return 0;
- ret = tps80031_force_update(parent, SLAVE_ID1, ri->state_reg, STATE_OFF,
- STATE_MASK);
+ reg_val = (ri->state_reg_cache & ~STATE_MASK) |
+ (STATE_OFF & STATE_MASK);
+ ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
if (ret < 0)
- dev_err(&rdev->dev, "Error in updating the STATE register\n");
-
+ dev_err(&rdev->dev, "Error in writing the STATE register\n");
+ else
+ ri->state_reg_cache = reg_val;
return ret;
}
@@ -290,7 +291,6 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
{
int vsel = 0;
int ret;
- uint8_t force = 0;
switch (ri->flags) {
case 0:
@@ -365,23 +365,22 @@ static int __tps80031_dcdc_set_voltage(struct device *parent,
}
if (ri->force_reg) {
- ret = tps80031_read(parent, ri->volt_id, ri->force_reg,
- &force);
- if (ret < 0) {
- dev_err(ri->dev, "Error in reading the force register\n");
- return ret;
- }
- if (((force >> 6) & 0x3) == 0) {
+ if (((ri->force_reg_cache >> 6) & 0x3) == 0) {
ret = tps80031_write(parent, ri->volt_id,
ri->force_reg, vsel);
- goto out;
+ if (ret < 0)
+ dev_err(ri->dev, "Error in writing the "
+ "force register\n");
+ else
+ ri->force_reg_cache = vsel;
+ return ret;
}
}
ret = tps80031_write(parent, ri->volt_id, ri->volt_reg, vsel);
-
-out:
if (ret < 0)
- dev_err(ri->dev, "Error in updating the Voltage register\n");
+ dev_err(ri->dev, "Error in writing the Voltage register\n");
+ else
+ ri->volt_reg_cache = vsel;
return ret;
}
@@ -396,26 +395,16 @@ static int tps80031dcdc_set_voltage(struct regulator_dev *rdev,
static int tps80031dcdc_get_voltage(struct regulator_dev *rdev)
{
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
- struct device *parent = to_tps80031_dev(rdev);
uint8_t vsel = 0;
- int ret;
int voltage = 0;
if (ri->force_reg) {
- ret = tps80031_read(parent, ri->volt_id, ri->force_reg, &vsel);
- if (ret < 0) {
- dev_err(&rdev->dev, "Error in reading the force register\n");
- return ret;
- }
+ vsel = ri->force_reg_cache;
if ((vsel & SMPS_CMD_MASK) == 0)
goto decode;
}
- ret = tps80031_read(parent, ri->volt_id, ri->volt_reg, &vsel);
- if (ret < 0) {
- dev_err(&rdev->dev, "Error in reading the Voltage register\n");
- return ret;
- }
+ vsel = ri->volt_reg_cache;
decode:
vsel &= SMPS_VSEL_MASK;
@@ -520,6 +509,8 @@ static int __tps80031_ldo_set_voltage(struct device *parent,
ret = tps80031_write(parent, ri->volt_id, ri->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;
}
@@ -535,16 +526,9 @@ static int tps80031ldo_set_voltage(struct regulator_dev *rdev,
static int tps80031ldo_get_voltage(struct regulator_dev *rdev)
{
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
- struct device *parent = to_tps80031_dev(rdev);
uint8_t vsel;
- int ret;
- ret = tps80031_read(parent, ri->volt_id, ri->volt_reg, &vsel);
- if (ret < 0) {
- dev_err(&rdev->dev, "Error in reading the Voltage register\n");
- return ret;
- }
- vsel &= LDO_VSEL_MASK;
+ vsel = ri->volt_reg_cache & LDO_VSEL_MASK;
/*
* Use the below formula to calculate vsel
@@ -746,6 +730,7 @@ static int tps80031_power_req_config(struct device *parent,
int preq_bit;
int preq_mask_bit;
int ret;
+ uint8_t reg_val;
if (!(ri->platform_flags & EXT_PWR_REQ))
return 0;
@@ -783,13 +768,13 @@ static int tps80031_power_req_config(struct device *parent,
}
/* Switch regulator control to resource now */
- ret = tps80031_update(parent, SLAVE_ID1, ri->state_reg, 0x0,
- STATE_MASK);
- if (ret < 0) {
- dev_err(ri->dev, "%s() Error in updating the STATE "
+ reg_val = (ri->state_reg_cache & ~STATE_MASK);
+ ret = tps80031_write(parent, SLAVE_ID1, ri->state_reg, reg_val);
+ if (ret < 0)
+ dev_err(ri->dev, "%s() Error in writing the STATE "
"register error %d\n", __func__, ret);
- return ret;
- }
+ else
+ ri->state_reg_cache = reg_val;
return ret;
}
@@ -798,6 +783,7 @@ static int tps80031_regulator_preinit(struct device *parent,
struct tps80031_regulator_platform_data *tps80031_pdata)
{
int ret = 0;
+ uint8_t reg_val;
if (ri->desc.id == TPS80031_ID_LDOUSB) {
if (ri->platform_flags & USBLDO_INPUT_VSYS)
@@ -871,15 +857,19 @@ static int tps80031_regulator_preinit(struct device *parent,
}
if (tps80031_pdata->init_enable)
- ret = tps80031_force_update(parent, SLAVE_ID1, ri->state_reg,
- STATE_ON, STATE_MASK);
+ reg_val = (ri->state_reg_cache & ~STATE_MASK) |
+ (STATE_ON & STATE_MASK);
else
- ret = tps80031_force_update(parent, SLAVE_ID1, ri->state_reg,
- STATE_OFF, STATE_MASK);
+ reg_val = (ri->state_reg_cache & ~STATE_MASK) |
+ (STATE_OFF & STATE_MASK);
+
+ ret = tps80031_write(parent, SLAVE_ID1, ri->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);
+ else
+ ri->state_reg_cache = reg_val;
return ret;
}
@@ -926,6 +916,25 @@ static void check_smps_mode_mult(struct device *parent,
return;
}
+static inline int tps80031_cache_regulator_register(struct device *parent,
+ struct tps80031_regulator *ri)
+{
+ int ret;
+
+ ret = tps80031_read(parent, SLAVE_ID1, ri->trans_reg,
+ &ri->trans_reg_cache);
+ if (!ret && ri->state_reg)
+ ret = tps80031_read(parent, SLAVE_ID1, ri->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);
+ return ret;
+}
+
static int __devinit tps80031_regulator_probe(struct platform_device *pdev)
{
struct tps80031_regulator *ri = NULL;
@@ -949,6 +958,11 @@ static int __devinit tps80031_regulator_probe(struct platform_device *pdev)
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;