aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/core.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index f15b04548715..771c6235cced 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2769,6 +2769,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
2769 int ret = 0; 2769 int ret = 0;
2770 int old_min_uV, old_max_uV; 2770 int old_min_uV, old_max_uV;
2771 int current_uV; 2771 int current_uV;
2772 int best_supply_uV = 0;
2773 int supply_change_uV = 0;
2772 2774
2773 /* If we're setting the same range as last time the change 2775 /* If we're setting the same range as last time the change
2774 * should be a noop (some cpufreq implementations use the same 2776 * should be a noop (some cpufreq implementations use the same
@@ -2812,10 +2814,58 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
2812 if (ret < 0) 2814 if (ret < 0)
2813 goto out2; 2815 goto out2;
2814 2816
2817 if (rdev->supply && (rdev->desc->min_dropout_uV ||
2818 !rdev->desc->ops->get_voltage)) {
2819 int current_supply_uV;
2820 int selector;
2821
2822 selector = regulator_map_voltage(rdev, min_uV, max_uV);
2823 if (selector < 0) {
2824 ret = selector;
2825 goto out2;
2826 }
2827
2828 best_supply_uV = _regulator_list_voltage(regulator, selector, 0);
2829 if (best_supply_uV < 0) {
2830 ret = best_supply_uV;
2831 goto out2;
2832 }
2833
2834 best_supply_uV += rdev->desc->min_dropout_uV;
2835
2836 current_supply_uV = _regulator_get_voltage(rdev->supply->rdev);
2837 if (current_supply_uV < 0) {
2838 ret = current_supply_uV;
2839 goto out2;
2840 }
2841
2842 supply_change_uV = best_supply_uV - current_supply_uV;
2843 }
2844
2845 if (supply_change_uV > 0) {
2846 ret = regulator_set_voltage_unlocked(rdev->supply,
2847 best_supply_uV, INT_MAX);
2848 if (ret) {
2849 dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
2850 ret);
2851 goto out2;
2852 }
2853 }
2854
2815 ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2855 ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
2816 if (ret < 0) 2856 if (ret < 0)
2817 goto out2; 2857 goto out2;
2818 2858
2859 if (supply_change_uV < 0) {
2860 ret = regulator_set_voltage_unlocked(rdev->supply,
2861 best_supply_uV, INT_MAX);
2862 if (ret)
2863 dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n",
2864 ret);
2865 /* No need to fail here */
2866 ret = 0;
2867 }
2868
2819out: 2869out:
2820 return ret; 2870 return ret;
2821out2: 2871out2:
@@ -2847,11 +2897,11 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
2847{ 2897{
2848 int ret = 0; 2898 int ret = 0;
2849 2899
2850 mutex_lock(&regulator->rdev->mutex); 2900 regulator_lock_supply(regulator->rdev);
2851 2901
2852 ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); 2902 ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV);
2853 2903
2854 mutex_unlock(&regulator->rdev->mutex); 2904 regulator_unlock_supply(regulator->rdev);
2855 2905
2856 return ret; 2906 return ret;
2857} 2907}