diff options
author | Matthias Kaehlcke <mka@chromium.org> | 2016-09-14 12:52:08 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-09-16 13:38:22 -0400 |
commit | 73e705bf81ceb84b39ef9cf6ffb8d12ca0c58a23 (patch) | |
tree | d9b12334afd63697d21e46788c7a79c80abd0da7 /drivers/regulator | |
parent | d89564efe79419a093e966a959bf5ba2c94e693f (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.c | 86 | ||||
-rw-r--r-- | drivers/regulator/pwm-regulator.c | 10 |
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 | ||
2746 | static 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 | |||
2746 | static int _regulator_do_set_voltage(struct regulator_dev *rdev, | 2764 | static 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 | } |
3064 | EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); | 3096 | EXPORT_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 | ||