summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2014-01-21 14:30:36 -0800
committerAleksandr Frid <afrid@nvidia.com>2014-01-29 16:58:19 -0800
commite7143e1500ef8662f45d90ccfe720be4622eed94 (patch)
tree20c9603f427e6b18bfd08a637ddb2d330558493f /drivers/regulator
parentb067377b3199247f5ee12f5d0ac38b379819999a (diff)
regulator: Change DFLL bypass voltage interfaces
Switched DFLL bypass regulator from set_voltage_sel/get_voltage_sel interfaces to set_voltage/get_voltage. This is done to avoid usage of stale selector value by regulator framework in set_voltage interface, since DFLL in closed loop mode changes voltage underneath regulator driver. Bug 1442709 Change-Id: I56f119399aeedfc794ebdbae65c91812179b74d4 Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/358583 Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/tegra-dfll-bypass-regulator.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/regulator/tegra-dfll-bypass-regulator.c b/drivers/regulator/tegra-dfll-bypass-regulator.c
index e77f62e8a66d..3b5a2bc8ea58 100644
--- a/drivers/regulator/tegra-dfll-bypass-regulator.c
+++ b/drivers/regulator/tegra-dfll-bypass-regulator.c
@@ -24,6 +24,7 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/tegra-dfll-bypass-regulator.h>
#include <linux/gpio.h>
+#include <linux/delay.h>
struct tegra_dfll_bypass_regulator {
struct device *dev;
@@ -31,23 +32,46 @@ struct tegra_dfll_bypass_regulator {
struct tegra_dfll_bypass_platform_data *pdata;
};
-static int tegra_dfll_bypass_set_voltage_sel(struct regulator_dev *reg,
- unsigned int selector)
+static int tegra_dfll_bypass_set_voltage(struct regulator_dev *reg,
+ int min_uV, int max_uV, unsigned int *selector)
{
- int ret;
+ int ret, delay;
struct tegra_dfll_bypass_regulator *tdb = rdev_get_drvdata(reg);
- ret = tdb->pdata->set_bypass_sel(tdb->pdata->dfll_data, selector);
- if (ret)
- dev_err(tdb->dev, "set selector failed, err %d\n", ret);
+ ret = regulator_map_voltage_linear(reg, min_uV, max_uV);
+ if (ret < 0) {
+ dev_err(tdb->dev, "failed map [%duV, %duV]\n", min_uV, max_uV);
+ return ret;
+ }
+
+ *selector = ret;
+ ret = tdb->pdata->set_bypass_sel(tdb->pdata->dfll_data, *selector);
+ if (ret) {
+ dev_err(tdb->dev, "failed to set selector %u\n", *selector);
+ return ret;
+ }
+
+ /* add voltage settling delay */
+ delay = tdb->pdata->voltage_time_sel;
+ if (delay > 1000)
+ mdelay(delay / 1000);
+ udelay(delay % 1000);
- return ret;
+ return 0;
}
-static int tegra_dfll_bypass_get_voltage_sel(struct regulator_dev *reg)
+static int tegra_dfll_bypass_get_voltage(struct regulator_dev *reg)
{
+ int sel;
struct tegra_dfll_bypass_regulator *tdb = rdev_get_drvdata(reg);
- return tdb->pdata->get_bypass_sel(tdb->pdata->dfll_data);
+
+ sel = tdb->pdata->get_bypass_sel(tdb->pdata->dfll_data);
+ if (sel < 0) {
+ dev_err(tdb->dev, "failed to get selector\n");
+ return sel;
+ }
+
+ return regulator_list_voltage_linear(reg, sel);
}
static int tegra_dfll_bypass_set_voltage_time_sel(struct regulator_dev *reg,
@@ -93,8 +117,8 @@ static unsigned int tegra_dfll_bypass_get_mode(struct regulator_dev *reg)
}
static struct regulator_ops tegra_dfll_bypass_rops = {
- .set_voltage_sel = tegra_dfll_bypass_set_voltage_sel,
- .get_voltage_sel = tegra_dfll_bypass_get_voltage_sel,
+ .set_voltage = tegra_dfll_bypass_set_voltage,
+ .get_voltage = tegra_dfll_bypass_get_voltage,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.set_voltage_time_sel = tegra_dfll_bypass_set_voltage_time_sel,