summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/pfuze100-regulator.c85
1 files changed, 82 insertions, 3 deletions
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index 34ca0fb45961..4458d3def6a2 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -526,6 +526,24 @@ pfuze100_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
}
+static int pfuze100_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ int ret;
+
+ dev_dbg(rdev_get_dev(rdev), "%s id: %d vol: %d\n",
+ __func__, id, pfuze100_regulators[id].voltages[selector]);
+
+ pfuze_lock(priv->pfuze);
+ ret = pfuze_reg_rmw(priv->pfuze, pfuze100_regulators[id].reg,
+ pfuze100_regulators[id].vsel_mask,
+ selector << pfuze100_regulators[id].vsel_shift);
+ pfuze_unlock(priv->pfuze);
+ return ret;
+}
+
static int pfuze100_regulator_get_voltage(struct regulator_dev *rdev)
{
struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev);
@@ -545,6 +563,66 @@ static int pfuze100_regulator_get_voltage(struct regulator_dev *rdev)
return pfuze100_regulators[id].voltages[val];
}
+static int pfuze100_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ int ret;
+ unsigned char val;
+
+ pfuze_lock(priv->pfuze);
+ ret = pfuze_reg_read(priv->pfuze, pfuze100_regulators[id].reg, &val);
+ pfuze_unlock(priv->pfuze);
+ if (ret)
+ return ret;
+
+ val &= pfuze100_regulators[id].vsel_mask;
+ val >>= pfuze100_regulators[id].vsel_shift;
+ dev_dbg(rdev_get_dev(rdev), "%s id: %d, vol=%d\n", __func__, id,
+ pfuze100_regulators[id].voltages[val]);
+ return (int) val;
+}
+
+static int pfuze100_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_sel,
+ unsigned int new_sel)
+{
+ struct pfuze_regulator_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ int ret;
+ unsigned char step_delay;
+
+ pfuze_lock(priv->pfuze);
+ /*read SWxDVSSPEED from SWxCONF,got ramp step value*/
+ ret = pfuze_reg_read(priv->pfuze, pfuze100_regulators[id].reg + 0x4,
+ &step_delay);
+ pfuze_unlock(priv->pfuze);
+
+ if (ret)
+ return ret;
+ /*
+ * one step
+ * 00: 2us,
+ * 01: 4us,
+ * 02: 8us,
+ * 03: 16us,
+ */
+ step_delay >>= 5;
+ step_delay &= 0x3;
+ step_delay <<= 1;
+
+ if (pfuze100_regulators[id].voltages[old_sel] <
+ pfuze100_regulators[id].voltages[new_sel])
+ ret = DIV_ROUND_UP(pfuze100_regulators[id].voltages[new_sel] -
+ pfuze100_regulators[id].voltages[old_sel], 25000)
+ * step_delay;
+ else
+ ret = 0; /* no delay if voltage drop */
+ dev_dbg(rdev_get_dev(rdev), "%s id: %d, new_sel = %d, old_sel = %d, \
+ delay = %d\n", __func__, id, new_sel, old_sel, ret);
+ return ret;
+}
+
static struct regulator_ops pfuze100_ldo_regulator_ops = {
.enable = pfuze100_regulator_enable,
.disable = pfuze100_regulator_disable,
@@ -594,8 +672,9 @@ static int pfuze100_sw_regulator_is_enabled(struct regulator_dev *rdev)
static struct regulator_ops pfuze100_sw_regulator_ops = {
.is_enabled = pfuze100_sw_regulator_is_enabled,
.list_voltage = pfuze100_regulator_list_voltage,
- .set_voltage = pfuze100_regulator_set_voltage,
- .get_voltage = pfuze100_regulator_get_voltage,
+ .set_voltage_sel = pfuze100_regulator_set_voltage_sel,
+ .get_voltage_sel = pfuze100_regulator_get_voltage_sel,
+ .set_voltage_time_sel = pfuze100_regulator_set_voltage_time_sel,
};
static int __devinit pfuze100_regulator_probe(struct platform_device *pdev)