diff options
-rw-r--r-- | drivers/regulator/pfuze100-regulator.c | 85 |
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) |