aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorMatthias Kaehlcke <mka@chromium.org>2016-09-14 12:52:08 -0400
committerMark Brown <broonie@kernel.org>2016-09-16 13:38:22 -0400
commit73e705bf81ceb84b39ef9cf6ffb8d12ca0c58a23 (patch)
treed9b12334afd63697d21e46788c7a79c80abd0da7 /drivers/regulator
parentd89564efe79419a093e966a959bf5ba2c94e693f (diff)
regulator: core: Add set_voltage_time op
The new op is analogous to set_voltage_time_sel. It can be used by regulators which don't have a table of discrete voltages. The function returns the time for the regulator output voltage to stabilize after being set to a new value, in microseconds. If the op is not set a default implementation is used to calculate the delay. This change also removes the ramp_delay calculation in the PWM regulator, since the driver now uses the core code for the calculation of the delay. Signed-off-by: Matthias Kaehlcke <mka@chromium.org> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c86
-rw-r--r--drivers/regulator/pwm-regulator.c10
2 files changed, 59 insertions, 37 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index df3028b2a8e9..c52fc0ce2693 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2743,6 +2743,24 @@ static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
2743 return ret; 2743 return ret;
2744} 2744}
2745 2745
2746static int _regulator_set_voltage_time(struct regulator_dev *rdev,
2747 int old_uV, int new_uV)
2748{
2749 unsigned int ramp_delay = 0;
2750
2751 if (rdev->constraints->ramp_delay)
2752 ramp_delay = rdev->constraints->ramp_delay;
2753 else if (rdev->desc->ramp_delay)
2754 ramp_delay = rdev->desc->ramp_delay;
2755
2756 if (ramp_delay == 0) {
2757 rdev_warn(rdev, "ramp_delay not set\n");
2758 return 0;
2759 }
2760
2761 return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
2762}
2763
2746static int _regulator_do_set_voltage(struct regulator_dev *rdev, 2764static int _regulator_do_set_voltage(struct regulator_dev *rdev,
2747 int min_uV, int max_uV) 2765 int min_uV, int max_uV)
2748{ 2766{
@@ -2752,6 +2770,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
2752 unsigned int selector; 2770 unsigned int selector;
2753 int old_selector = -1; 2771 int old_selector = -1;
2754 const struct regulator_ops *ops = rdev->desc->ops; 2772 const struct regulator_ops *ops = rdev->desc->ops;
2773 int old_uV = _regulator_get_voltage(rdev);
2755 2774
2756 trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 2775 trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
2757 2776
@@ -2803,23 +2822,37 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
2803 if (ret) 2822 if (ret)
2804 goto out; 2823 goto out;
2805 2824
2806 /* Call set_voltage_time_sel if successfully obtained old_selector */ 2825 if (ops->set_voltage_time_sel) {
2807 if (!old_selector >= 0 && old_selector != selector) { 2826 /*
2808 delay = ops->set_voltage_time_sel(rdev, 2827 * Call set_voltage_time_sel if successfully obtained
2809 old_selector, selector); 2828 * old_selector
2810 if (delay < 0) { 2829 */
2811 rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2830 if (old_selector >= 0 && old_selector != selector)
2812 delay); 2831 delay = ops->set_voltage_time_sel(rdev, old_selector,
2813 delay = 0; 2832 selector);
2833 } else {
2834 if (old_uV != best_val) {
2835 if (ops->set_voltage_time)
2836 delay = ops->set_voltage_time(rdev, old_uV,
2837 best_val);
2838 else
2839 delay = _regulator_set_voltage_time(rdev,
2840 old_uV,
2841 best_val);
2814 } 2842 }
2843 }
2815 2844
2816 /* Insert any necessary delays */ 2845 if (delay < 0) {
2817 if (delay >= 1000) { 2846 rdev_warn(rdev, "failed to get delay: %d\n", delay);
2818 mdelay(delay / 1000); 2847 delay = 0;
2819 udelay(delay % 1000); 2848 }
2820 } else if (delay) { 2849
2821 udelay(delay); 2850 /* Insert any necessary delays */
2822 } 2851 if (delay >= 1000) {
2852 mdelay(delay / 1000);
2853 udelay(delay % 1000);
2854 } else if (delay) {
2855 udelay(delay);
2823 } 2856 }
2824 2857
2825 if (best_val >= 0) { 2858 if (best_val >= 0) {
@@ -3000,9 +3033,13 @@ int regulator_set_voltage_time(struct regulator *regulator,
3000 int voltage; 3033 int voltage;
3001 int i; 3034 int i;
3002 3035
3036 if (ops->set_voltage_time)
3037 return ops->set_voltage_time(rdev, old_uV, new_uV);
3038 else if (!ops->set_voltage_time_sel)
3039 return _regulator_set_voltage_time(rdev, old_uV, new_uV);
3040
3003 /* Currently requires operations to do this */ 3041 /* Currently requires operations to do this */
3004 if (!ops->list_voltage || !ops->set_voltage_time_sel 3042 if (!ops->list_voltage || !rdev->desc->n_voltages)
3005 || !rdev->desc->n_voltages)
3006 return -EINVAL; 3043 return -EINVAL;
3007 3044
3008 for (i = 0; i < rdev->desc->n_voltages; i++) { 3045 for (i = 0; i < rdev->desc->n_voltages; i++) {
@@ -3041,17 +3078,8 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
3041 unsigned int old_selector, 3078 unsigned int old_selector,
3042 unsigned int new_selector) 3079 unsigned int new_selector)
3043{ 3080{
3044 unsigned int ramp_delay = 0;
3045 int old_volt, new_volt; 3081 int old_volt, new_volt;
3046 3082
3047 if (rdev->constraints->ramp_delay)
3048 ramp_delay = rdev->constraints->ramp_delay;
3049 else if (rdev->desc->ramp_delay)
3050 ramp_delay = rdev->desc->ramp_delay;
3051
3052 if (ramp_delay == 0)
3053 return 0;
3054
3055 /* sanity check */ 3083 /* sanity check */
3056 if (!rdev->desc->ops->list_voltage) 3084 if (!rdev->desc->ops->list_voltage)
3057 return -EINVAL; 3085 return -EINVAL;
@@ -3059,7 +3087,11 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
3059 old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3087 old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
3060 new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3088 new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
3061 3089
3062 return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 3090 if (rdev->desc->ops->set_voltage_time)
3091 return rdev->desc->ops->set_voltage_time(rdev, old_volt,
3092 new_volt);
3093 else
3094 return _regulator_set_voltage_time(rdev, old_volt, new_volt);
3063} 3095}
3064EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 3096EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
3065 3097
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index c24524242da2..1b88e0e15a70 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -10,7 +10,6 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/delay.h>
14#include <linux/module.h> 13#include <linux/module.h>
15#include <linux/init.h> 14#include <linux/init.h>
16#include <linux/err.h> 15#include <linux/err.h>
@@ -194,12 +193,10 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
194 unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 193 unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle;
195 unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 194 unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle;
196 unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 195 unsigned int duty_unit = drvdata->continuous.dutycycle_unit;
197 unsigned int ramp_delay = rdev->constraints->ramp_delay;
198 int min_uV = rdev->constraints->min_uV; 196 int min_uV = rdev->constraints->min_uV;
199 int max_uV = rdev->constraints->max_uV; 197 int max_uV = rdev->constraints->max_uV;
200 int diff_uV = max_uV - min_uV; 198 int diff_uV = max_uV - min_uV;
201 struct pwm_state pstate; 199 struct pwm_state pstate;
202 int old_uV = pwm_regulator_get_voltage(rdev);
203 unsigned int diff_duty; 200 unsigned int diff_duty;
204 unsigned int dutycycle; 201 unsigned int dutycycle;
205 int ret; 202 int ret;
@@ -233,13 +230,6 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
233 return ret; 230 return ret;
234 } 231 }
235 232
236 if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev))
237 return 0;
238
239 /* Ramp delay is in uV/uS. Adjust to uS and delay */
240 ramp_delay = DIV_ROUND_UP(abs(req_min_uV - old_uV), ramp_delay);
241 usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10));
242
243 return 0; 233 return 0;
244} 234}
245 235