Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Matthias Kaehlcke and committed by
Mark Brown
73e705bf d89564ef

+67 -39
+59 -27
drivers/regulator/core.c
··· 2743 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 2764 static int _regulator_do_set_voltage(struct regulator_dev *rdev, 2747 2765 int min_uV, int max_uV) 2748 2766 { ··· 2770 2752 unsigned int selector; 2771 2753 int old_selector = -1; 2772 2754 const struct regulator_ops *ops = rdev->desc->ops; 2755 + int old_uV = _regulator_get_voltage(rdev); 2773 2756 2774 2757 trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 2775 2758 ··· 2822 2803 if (ret) 2823 2804 goto out; 2824 2805 2825 - /* Call set_voltage_time_sel if successfully obtained old_selector */ 2826 - if (!old_selector >= 0 && old_selector != selector) { 2827 - delay = ops->set_voltage_time_sel(rdev, 2828 - old_selector, selector); 2829 - if (delay < 0) { 2830 - rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2831 - delay); 2832 - delay = 0; 2806 + if (ops->set_voltage_time_sel) { 2807 + /* 2808 + * Call set_voltage_time_sel if successfully obtained 2809 + * old_selector 2810 + */ 2811 + if (old_selector >= 0 && old_selector != selector) 2812 + delay = ops->set_voltage_time_sel(rdev, old_selector, 2813 + selector); 2814 + } else { 2815 + if (old_uV != best_val) { 2816 + if (ops->set_voltage_time) 2817 + delay = ops->set_voltage_time(rdev, old_uV, 2818 + best_val); 2819 + else 2820 + delay = _regulator_set_voltage_time(rdev, 2821 + old_uV, 2822 + best_val); 2833 2823 } 2824 + } 2834 2825 2835 - /* Insert any necessary delays */ 2836 - if (delay >= 1000) { 2837 - mdelay(delay / 1000); 2838 - udelay(delay % 1000); 2839 - } else if (delay) { 2840 - udelay(delay); 2841 - } 2826 + if (delay < 0) { 2827 + rdev_warn(rdev, "failed to get delay: %d\n", delay); 2828 + delay = 0; 2829 + } 2830 + 2831 + /* Insert any necessary delays */ 2832 + if (delay >= 1000) { 2833 + mdelay(delay / 1000); 2834 + udelay(delay % 1000); 2835 + } else if (delay) { 2836 + udelay(delay); 2842 2837 } 2843 2838 2844 2839 if (best_val >= 0) { ··· 3033 3000 int voltage; 3034 3001 int i; 3035 3002 3003 + if (ops->set_voltage_time) 3004 + return ops->set_voltage_time(rdev, old_uV, new_uV); 3005 + else if (!ops->set_voltage_time_sel) 3006 + return _regulator_set_voltage_time(rdev, old_uV, new_uV); 3007 + 3036 3008 /* Currently requires operations to do this */ 3037 - if (!ops->list_voltage || !ops->set_voltage_time_sel 3038 - || !rdev->desc->n_voltages) 3009 + if (!ops->list_voltage || !rdev->desc->n_voltages) 3039 3010 return -EINVAL; 3040 3011 3041 3012 for (i = 0; i < rdev->desc->n_voltages; i++) { ··· 3078 3041 unsigned int old_selector, 3079 3042 unsigned int new_selector) 3080 3043 { 3081 - unsigned int ramp_delay = 0; 3082 3044 int old_volt, new_volt; 3083 - 3084 - if (rdev->constraints->ramp_delay) 3085 - ramp_delay = rdev->constraints->ramp_delay; 3086 - else if (rdev->desc->ramp_delay) 3087 - ramp_delay = rdev->desc->ramp_delay; 3088 - 3089 - if (ramp_delay == 0) 3090 - return 0; 3091 3045 3092 3046 /* sanity check */ 3093 3047 if (!rdev->desc->ops->list_voltage) ··· 3087 3059 old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3088 3060 new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3089 3061 3090 - return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 3062 + if (rdev->desc->ops->set_voltage_time) 3063 + return rdev->desc->ops->set_voltage_time(rdev, old_volt, 3064 + new_volt); 3065 + else 3066 + return _regulator_set_voltage_time(rdev, old_volt, new_volt); 3091 3067 } 3092 3068 EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 3093 3069
-10
drivers/regulator/pwm-regulator.c
··· 10 10 * published by the Free Software Foundation. 11 11 */ 12 12 13 - #include <linux/delay.h> 14 13 #include <linux/module.h> 15 14 #include <linux/init.h> 16 15 #include <linux/err.h> ··· 193 194 unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle; 194 195 unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle; 195 196 unsigned int duty_unit = drvdata->continuous.dutycycle_unit; 196 - unsigned int ramp_delay = rdev->constraints->ramp_delay; 197 197 int min_uV = rdev->constraints->min_uV; 198 198 int max_uV = rdev->constraints->max_uV; 199 199 int diff_uV = max_uV - min_uV; 200 200 struct pwm_state pstate; 201 - int old_uV = pwm_regulator_get_voltage(rdev); 202 201 unsigned int diff_duty; 203 202 unsigned int dutycycle; 204 203 int ret; ··· 229 232 dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret); 230 233 return ret; 231 234 } 232 - 233 - if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev)) 234 - return 0; 235 - 236 - /* Ramp delay is in uV/uS. Adjust to uS and delay */ 237 - ramp_delay = DIV_ROUND_UP(abs(req_min_uV - old_uV), ramp_delay); 238 - usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10)); 239 235 240 236 return 0; 241 237 }
+8 -2
include/linux/regulator/driver.h
··· 113 113 * stabilise after being enabled, in microseconds. 114 114 * @set_ramp_delay: Set the ramp delay for the regulator. The driver should 115 115 * select ramp delay equal to or less than(closest) ramp_delay. 116 + * @set_voltage_time: Time taken for the regulator voltage output voltage 117 + * to stabilise after being set to a new value, in microseconds. 118 + * The function receives the from and to voltage as input, it 119 + * should return the worst case. 116 120 * @set_voltage_time_sel: Time taken for the regulator voltage output voltage 117 121 * to stabilise after being set to a new value, in microseconds. 118 - * The function provides the from and to voltage selector, the 119 - * function should return the worst case. 122 + * The function receives the from and to voltage selector as 123 + * input, it should return the worst case. 120 124 * @set_soft_start: Enable soft start for the regulator. 121 125 * 122 126 * @set_suspend_voltage: Set the voltage for the regulator when the system ··· 172 168 /* Time taken to enable or set voltage on the regulator */ 173 169 int (*enable_time) (struct regulator_dev *); 174 170 int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay); 171 + int (*set_voltage_time) (struct regulator_dev *, int old_uV, 172 + int new_uV); 175 173 int (*set_voltage_time_sel) (struct regulator_dev *, 176 174 unsigned int old_selector, 177 175 unsigned int new_selector);