diff options
author | Mark Brown <broonie@kernel.org> | 2018-01-26 12:40:03 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-01-26 12:40:03 -0500 |
commit | 285c22de377dd6895af30af6272cc7778cee36a7 (patch) | |
tree | 0242402441f35cf83afea2c7054d5174ae12fc79 | |
parent | 3d67fe950707a930664c5673ecc026f1bb497136 (diff) | |
parent | f7efad10b5c492892b1e5decf5d3ebb29fa5c9af (diff) |
Merge branch 'topic/suspend' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into regulator-core
-rw-r--r-- | Documentation/devicetree/bindings/regulator/regulator.txt | 12 | ||||
-rw-r--r-- | drivers/regulator/core.c | 346 | ||||
-rw-r--r-- | drivers/regulator/internal.h | 18 | ||||
-rw-r--r-- | drivers/regulator/of_regulator.c | 20 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 2 | ||||
-rw-r--r-- | include/linux/regulator/machine.h | 37 |
6 files changed, 309 insertions, 126 deletions
diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 378f6dc8b8bd..e459226dfac9 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt | |||
@@ -42,8 +42,16 @@ Optional properties: | |||
42 | - regulator-state-[mem/disk] node has following common properties: | 42 | - regulator-state-[mem/disk] node has following common properties: |
43 | - regulator-on-in-suspend: regulator should be on in suspend state. | 43 | - regulator-on-in-suspend: regulator should be on in suspend state. |
44 | - regulator-off-in-suspend: regulator should be off in suspend state. | 44 | - regulator-off-in-suspend: regulator should be off in suspend state. |
45 | - regulator-suspend-microvolt: regulator should be set to this voltage | 45 | - regulator-suspend-min-microvolt: minimum voltage may be set in |
46 | in suspend. | 46 | suspend state. |
47 | - regulator-suspend-max-microvolt: maximum voltage may be set in | ||
48 | suspend state. | ||
49 | - regulator-suspend-microvolt: the default voltage which regulator | ||
50 | would be set in suspend. This property is now deprecated, instead | ||
51 | setting voltage for suspend mode via the API which regulator | ||
52 | driver provides is recommended. | ||
53 | - regulator-changeable-in-suspend: whether the default voltage and | ||
54 | the regulator on/off in suspend can be changed in runtime. | ||
47 | - regulator-mode: operating mode in the given suspend state. | 55 | - regulator-mode: operating mode in the given suspend state. |
48 | The set of possible operating modes depends on the capabilities of | 56 | The set of possible operating modes depends on the capabilities of |
49 | every hardware so the valid modes are documented on each regulator | 57 | every hardware so the valid modes are documented on each regulator |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index fd8eacfea422..2dccc4b3766e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -229,26 +229,35 @@ static int regulator_check_voltage(struct regulator_dev *rdev, | |||
229 | return 0; | 229 | return 0; |
230 | } | 230 | } |
231 | 231 | ||
232 | /* return 0 if the state is valid */ | ||
233 | static int regulator_check_states(suspend_state_t state) | ||
234 | { | ||
235 | return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE); | ||
236 | } | ||
237 | |||
232 | /* Make sure we select a voltage that suits the needs of all | 238 | /* Make sure we select a voltage that suits the needs of all |
233 | * regulator consumers | 239 | * regulator consumers |
234 | */ | 240 | */ |
235 | static int regulator_check_consumers(struct regulator_dev *rdev, | 241 | static int regulator_check_consumers(struct regulator_dev *rdev, |
236 | int *min_uV, int *max_uV) | 242 | int *min_uV, int *max_uV, |
243 | suspend_state_t state) | ||
237 | { | 244 | { |
238 | struct regulator *regulator; | 245 | struct regulator *regulator; |
246 | struct regulator_voltage *voltage; | ||
239 | 247 | ||
240 | list_for_each_entry(regulator, &rdev->consumer_list, list) { | 248 | list_for_each_entry(regulator, &rdev->consumer_list, list) { |
249 | voltage = ®ulator->voltage[state]; | ||
241 | /* | 250 | /* |
242 | * Assume consumers that didn't say anything are OK | 251 | * Assume consumers that didn't say anything are OK |
243 | * with anything in the constraint range. | 252 | * with anything in the constraint range. |
244 | */ | 253 | */ |
245 | if (!regulator->min_uV && !regulator->max_uV) | 254 | if (!voltage->min_uV && !voltage->max_uV) |
246 | continue; | 255 | continue; |
247 | 256 | ||
248 | if (*max_uV > regulator->max_uV) | 257 | if (*max_uV > voltage->max_uV) |
249 | *max_uV = regulator->max_uV; | 258 | *max_uV = voltage->max_uV; |
250 | if (*min_uV < regulator->min_uV) | 259 | if (*min_uV < voltage->min_uV) |
251 | *min_uV = regulator->min_uV; | 260 | *min_uV = voltage->min_uV; |
252 | } | 261 | } |
253 | 262 | ||
254 | if (*min_uV > *max_uV) { | 263 | if (*min_uV > *max_uV) { |
@@ -317,6 +326,24 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, | |||
317 | return -EINVAL; | 326 | return -EINVAL; |
318 | } | 327 | } |
319 | 328 | ||
329 | static inline struct regulator_state * | ||
330 | regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) | ||
331 | { | ||
332 | if (rdev->constraints == NULL) | ||
333 | return NULL; | ||
334 | |||
335 | switch (state) { | ||
336 | case PM_SUSPEND_STANDBY: | ||
337 | return &rdev->constraints->state_standby; | ||
338 | case PM_SUSPEND_MEM: | ||
339 | return &rdev->constraints->state_mem; | ||
340 | case PM_SUSPEND_MAX: | ||
341 | return &rdev->constraints->state_disk; | ||
342 | default: | ||
343 | return NULL; | ||
344 | } | ||
345 | } | ||
346 | |||
320 | static ssize_t regulator_uV_show(struct device *dev, | 347 | static ssize_t regulator_uV_show(struct device *dev, |
321 | struct device_attribute *attr, char *buf) | 348 | struct device_attribute *attr, char *buf) |
322 | { | 349 | { |
@@ -724,29 +751,32 @@ static int drms_uA_update(struct regulator_dev *rdev) | |||
724 | } | 751 | } |
725 | 752 | ||
726 | static int suspend_set_state(struct regulator_dev *rdev, | 753 | static int suspend_set_state(struct regulator_dev *rdev, |
727 | struct regulator_state *rstate) | 754 | suspend_state_t state) |
728 | { | 755 | { |
729 | int ret = 0; | 756 | int ret = 0; |
757 | struct regulator_state *rstate; | ||
758 | |||
759 | rstate = regulator_get_suspend_state(rdev, state); | ||
760 | if (rstate == NULL) | ||
761 | return -EINVAL; | ||
730 | 762 | ||
731 | /* If we have no suspend mode configration don't set anything; | 763 | /* If we have no suspend mode configration don't set anything; |
732 | * only warn if the driver implements set_suspend_voltage or | 764 | * only warn if the driver implements set_suspend_voltage or |
733 | * set_suspend_mode callback. | 765 | * set_suspend_mode callback. |
734 | */ | 766 | */ |
735 | if (!rstate->enabled && !rstate->disabled) { | 767 | if (rstate->enabled != ENABLE_IN_SUSPEND && |
768 | rstate->enabled != DISABLE_IN_SUSPEND) { | ||
736 | if (rdev->desc->ops->set_suspend_voltage || | 769 | if (rdev->desc->ops->set_suspend_voltage || |
737 | rdev->desc->ops->set_suspend_mode) | 770 | rdev->desc->ops->set_suspend_mode) |
738 | rdev_warn(rdev, "No configuration\n"); | 771 | rdev_warn(rdev, "No configuration\n"); |
739 | return 0; | 772 | return 0; |
740 | } | 773 | } |
741 | 774 | ||
742 | if (rstate->enabled && rstate->disabled) { | 775 | if (rstate->enabled == ENABLE_IN_SUSPEND && |
743 | rdev_err(rdev, "invalid configuration\n"); | 776 | rdev->desc->ops->set_suspend_enable) |
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | if (rstate->enabled && rdev->desc->ops->set_suspend_enable) | ||
748 | ret = rdev->desc->ops->set_suspend_enable(rdev); | 777 | ret = rdev->desc->ops->set_suspend_enable(rdev); |
749 | else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) | 778 | else if (rstate->enabled == DISABLE_IN_SUSPEND && |
779 | rdev->desc->ops->set_suspend_disable) | ||
750 | ret = rdev->desc->ops->set_suspend_disable(rdev); | 780 | ret = rdev->desc->ops->set_suspend_disable(rdev); |
751 | else /* OK if set_suspend_enable or set_suspend_disable is NULL */ | 781 | else /* OK if set_suspend_enable or set_suspend_disable is NULL */ |
752 | ret = 0; | 782 | ret = 0; |
@@ -771,28 +801,8 @@ static int suspend_set_state(struct regulator_dev *rdev, | |||
771 | return ret; | 801 | return ret; |
772 | } | 802 | } |
773 | } | 803 | } |
774 | return ret; | ||
775 | } | ||
776 | |||
777 | /* locks held by caller */ | ||
778 | static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) | ||
779 | { | ||
780 | if (!rdev->constraints) | ||
781 | return -EINVAL; | ||
782 | 804 | ||
783 | switch (state) { | 805 | return ret; |
784 | case PM_SUSPEND_STANDBY: | ||
785 | return suspend_set_state(rdev, | ||
786 | &rdev->constraints->state_standby); | ||
787 | case PM_SUSPEND_MEM: | ||
788 | return suspend_set_state(rdev, | ||
789 | &rdev->constraints->state_mem); | ||
790 | case PM_SUSPEND_MAX: | ||
791 | return suspend_set_state(rdev, | ||
792 | &rdev->constraints->state_disk); | ||
793 | default: | ||
794 | return -EINVAL; | ||
795 | } | ||
796 | } | 806 | } |
797 | 807 | ||
798 | static void print_constraints(struct regulator_dev *rdev) | 808 | static void print_constraints(struct regulator_dev *rdev) |
@@ -1061,7 +1071,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
1061 | 1071 | ||
1062 | /* do we need to setup our suspend state */ | 1072 | /* do we need to setup our suspend state */ |
1063 | if (rdev->constraints->initial_state) { | 1073 | if (rdev->constraints->initial_state) { |
1064 | ret = suspend_prepare(rdev, rdev->constraints->initial_state); | 1074 | ret = suspend_set_state(rdev, rdev->constraints->initial_state); |
1065 | if (ret < 0) { | 1075 | if (ret < 0) { |
1066 | rdev_err(rdev, "failed to set suspend state\n"); | 1076 | rdev_err(rdev, "failed to set suspend state\n"); |
1067 | return ret; | 1077 | return ret; |
@@ -1349,9 +1359,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, | |||
1349 | debugfs_create_u32("uA_load", 0444, regulator->debugfs, | 1359 | debugfs_create_u32("uA_load", 0444, regulator->debugfs, |
1350 | ®ulator->uA_load); | 1360 | ®ulator->uA_load); |
1351 | debugfs_create_u32("min_uV", 0444, regulator->debugfs, | 1361 | debugfs_create_u32("min_uV", 0444, regulator->debugfs, |
1352 | ®ulator->min_uV); | 1362 | ®ulator->voltage[PM_SUSPEND_ON].min_uV); |
1353 | debugfs_create_u32("max_uV", 0444, regulator->debugfs, | 1363 | debugfs_create_u32("max_uV", 0444, regulator->debugfs, |
1354 | ®ulator->max_uV); | 1364 | ®ulator->voltage[PM_SUSPEND_ON].max_uV); |
1355 | debugfs_create_file("constraint_flags", 0444, | 1365 | debugfs_create_file("constraint_flags", 0444, |
1356 | regulator->debugfs, regulator, | 1366 | regulator->debugfs, regulator, |
1357 | &constraint_flags_fops); | 1367 | &constraint_flags_fops); |
@@ -2876,10 +2886,38 @@ out: | |||
2876 | return ret; | 2886 | return ret; |
2877 | } | 2887 | } |
2878 | 2888 | ||
2889 | static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, | ||
2890 | int min_uV, int max_uV, suspend_state_t state) | ||
2891 | { | ||
2892 | struct regulator_state *rstate; | ||
2893 | int uV, sel; | ||
2894 | |||
2895 | rstate = regulator_get_suspend_state(rdev, state); | ||
2896 | if (rstate == NULL) | ||
2897 | return -EINVAL; | ||
2898 | |||
2899 | if (min_uV < rstate->min_uV) | ||
2900 | min_uV = rstate->min_uV; | ||
2901 | if (max_uV > rstate->max_uV) | ||
2902 | max_uV = rstate->max_uV; | ||
2903 | |||
2904 | sel = regulator_map_voltage(rdev, min_uV, max_uV); | ||
2905 | if (sel < 0) | ||
2906 | return sel; | ||
2907 | |||
2908 | uV = rdev->desc->ops->list_voltage(rdev, sel); | ||
2909 | if (uV >= min_uV && uV <= max_uV) | ||
2910 | rstate->uV = uV; | ||
2911 | |||
2912 | return 0; | ||
2913 | } | ||
2914 | |||
2879 | static int regulator_set_voltage_unlocked(struct regulator *regulator, | 2915 | static int regulator_set_voltage_unlocked(struct regulator *regulator, |
2880 | int min_uV, int max_uV) | 2916 | int min_uV, int max_uV, |
2917 | suspend_state_t state) | ||
2881 | { | 2918 | { |
2882 | struct regulator_dev *rdev = regulator->rdev; | 2919 | struct regulator_dev *rdev = regulator->rdev; |
2920 | struct regulator_voltage *voltage = ®ulator->voltage[state]; | ||
2883 | int ret = 0; | 2921 | int ret = 0; |
2884 | int old_min_uV, old_max_uV; | 2922 | int old_min_uV, old_max_uV; |
2885 | int current_uV; | 2923 | int current_uV; |
@@ -2890,7 +2928,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, | |||
2890 | * should be a noop (some cpufreq implementations use the same | 2928 | * should be a noop (some cpufreq implementations use the same |
2891 | * voltage for multiple frequencies, for example). | 2929 | * voltage for multiple frequencies, for example). |
2892 | */ | 2930 | */ |
2893 | if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) | 2931 | if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) |
2894 | goto out; | 2932 | goto out; |
2895 | 2933 | ||
2896 | /* If we're trying to set a range that overlaps the current voltage, | 2934 | /* If we're trying to set a range that overlaps the current voltage, |
@@ -2900,8 +2938,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, | |||
2900 | if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { | 2938 | if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { |
2901 | current_uV = _regulator_get_voltage(rdev); | 2939 | current_uV = _regulator_get_voltage(rdev); |
2902 | if (min_uV <= current_uV && current_uV <= max_uV) { | 2940 | if (min_uV <= current_uV && current_uV <= max_uV) { |
2903 | regulator->min_uV = min_uV; | 2941 | voltage->min_uV = min_uV; |
2904 | regulator->max_uV = max_uV; | 2942 | voltage->max_uV = max_uV; |
2905 | goto out; | 2943 | goto out; |
2906 | } | 2944 | } |
2907 | } | 2945 | } |
@@ -2919,12 +2957,12 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, | |||
2919 | goto out; | 2957 | goto out; |
2920 | 2958 | ||
2921 | /* restore original values in case of error */ | 2959 | /* restore original values in case of error */ |
2922 | old_min_uV = regulator->min_uV; | 2960 | old_min_uV = voltage->min_uV; |
2923 | old_max_uV = regulator->max_uV; | 2961 | old_max_uV = voltage->max_uV; |
2924 | regulator->min_uV = min_uV; | 2962 | voltage->min_uV = min_uV; |
2925 | regulator->max_uV = max_uV; | 2963 | voltage->max_uV = max_uV; |
2926 | 2964 | ||
2927 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV); | 2965 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state); |
2928 | if (ret < 0) | 2966 | if (ret < 0) |
2929 | goto out2; | 2967 | goto out2; |
2930 | 2968 | ||
@@ -2961,7 +2999,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, | |||
2961 | 2999 | ||
2962 | if (supply_change_uV > 0) { | 3000 | if (supply_change_uV > 0) { |
2963 | ret = regulator_set_voltage_unlocked(rdev->supply, | 3001 | ret = regulator_set_voltage_unlocked(rdev->supply, |
2964 | best_supply_uV, INT_MAX); | 3002 | best_supply_uV, INT_MAX, state); |
2965 | if (ret) { | 3003 | if (ret) { |
2966 | dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", | 3004 | dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", |
2967 | ret); | 3005 | ret); |
@@ -2969,13 +3007,17 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, | |||
2969 | } | 3007 | } |
2970 | } | 3008 | } |
2971 | 3009 | ||
2972 | ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); | 3010 | if (state == PM_SUSPEND_ON) |
3011 | ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); | ||
3012 | else | ||
3013 | ret = _regulator_do_set_suspend_voltage(rdev, min_uV, | ||
3014 | max_uV, state); | ||
2973 | if (ret < 0) | 3015 | if (ret < 0) |
2974 | goto out2; | 3016 | goto out2; |
2975 | 3017 | ||
2976 | if (supply_change_uV < 0) { | 3018 | if (supply_change_uV < 0) { |
2977 | ret = regulator_set_voltage_unlocked(rdev->supply, | 3019 | ret = regulator_set_voltage_unlocked(rdev->supply, |
2978 | best_supply_uV, INT_MAX); | 3020 | best_supply_uV, INT_MAX, state); |
2979 | if (ret) | 3021 | if (ret) |
2980 | dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", | 3022 | dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", |
2981 | ret); | 3023 | ret); |
@@ -2986,8 +3028,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, | |||
2986 | out: | 3028 | out: |
2987 | return ret; | 3029 | return ret; |
2988 | out2: | 3030 | out2: |
2989 | regulator->min_uV = old_min_uV; | 3031 | voltage->min_uV = old_min_uV; |
2990 | regulator->max_uV = old_max_uV; | 3032 | voltage->max_uV = old_max_uV; |
2991 | 3033 | ||
2992 | return ret; | 3034 | return ret; |
2993 | } | 3035 | } |
@@ -3016,7 +3058,8 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) | |||
3016 | 3058 | ||
3017 | regulator_lock_supply(regulator->rdev); | 3059 | regulator_lock_supply(regulator->rdev); |
3018 | 3060 | ||
3019 | ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); | 3061 | ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, |
3062 | PM_SUSPEND_ON); | ||
3020 | 3063 | ||
3021 | regulator_unlock_supply(regulator->rdev); | 3064 | regulator_unlock_supply(regulator->rdev); |
3022 | 3065 | ||
@@ -3024,6 +3067,89 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) | |||
3024 | } | 3067 | } |
3025 | EXPORT_SYMBOL_GPL(regulator_set_voltage); | 3068 | EXPORT_SYMBOL_GPL(regulator_set_voltage); |
3026 | 3069 | ||
3070 | static inline int regulator_suspend_toggle(struct regulator_dev *rdev, | ||
3071 | suspend_state_t state, bool en) | ||
3072 | { | ||
3073 | struct regulator_state *rstate; | ||
3074 | |||
3075 | rstate = regulator_get_suspend_state(rdev, state); | ||
3076 | if (rstate == NULL) | ||
3077 | return -EINVAL; | ||
3078 | |||
3079 | if (!rstate->changeable) | ||
3080 | return -EPERM; | ||
3081 | |||
3082 | rstate->enabled = en; | ||
3083 | |||
3084 | return 0; | ||
3085 | } | ||
3086 | |||
3087 | int regulator_suspend_enable(struct regulator_dev *rdev, | ||
3088 | suspend_state_t state) | ||
3089 | { | ||
3090 | return regulator_suspend_toggle(rdev, state, true); | ||
3091 | } | ||
3092 | EXPORT_SYMBOL_GPL(regulator_suspend_enable); | ||
3093 | |||
3094 | int regulator_suspend_disable(struct regulator_dev *rdev, | ||
3095 | suspend_state_t state) | ||
3096 | { | ||
3097 | struct regulator *regulator; | ||
3098 | struct regulator_voltage *voltage; | ||
3099 | |||
3100 | /* | ||
3101 | * if any consumer wants this regulator device keeping on in | ||
3102 | * suspend states, don't set it as disabled. | ||
3103 | */ | ||
3104 | list_for_each_entry(regulator, &rdev->consumer_list, list) { | ||
3105 | voltage = ®ulator->voltage[state]; | ||
3106 | if (voltage->min_uV || voltage->max_uV) | ||
3107 | return 0; | ||
3108 | } | ||
3109 | |||
3110 | return regulator_suspend_toggle(rdev, state, false); | ||
3111 | } | ||
3112 | EXPORT_SYMBOL_GPL(regulator_suspend_disable); | ||
3113 | |||
3114 | static int _regulator_set_suspend_voltage(struct regulator *regulator, | ||
3115 | int min_uV, int max_uV, | ||
3116 | suspend_state_t state) | ||
3117 | { | ||
3118 | struct regulator_dev *rdev = regulator->rdev; | ||
3119 | struct regulator_state *rstate; | ||
3120 | |||
3121 | rstate = regulator_get_suspend_state(rdev, state); | ||
3122 | if (rstate == NULL) | ||
3123 | return -EINVAL; | ||
3124 | |||
3125 | if (rstate->min_uV == rstate->max_uV) { | ||
3126 | rdev_err(rdev, "The suspend voltage can't be changed!\n"); | ||
3127 | return -EPERM; | ||
3128 | } | ||
3129 | |||
3130 | return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); | ||
3131 | } | ||
3132 | |||
3133 | int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, | ||
3134 | int max_uV, suspend_state_t state) | ||
3135 | { | ||
3136 | int ret = 0; | ||
3137 | |||
3138 | /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ | ||
3139 | if (regulator_check_states(state) || state == PM_SUSPEND_ON) | ||
3140 | return -EINVAL; | ||
3141 | |||
3142 | regulator_lock_supply(regulator->rdev); | ||
3143 | |||
3144 | ret = _regulator_set_suspend_voltage(regulator, min_uV, | ||
3145 | max_uV, state); | ||
3146 | |||
3147 | regulator_unlock_supply(regulator->rdev); | ||
3148 | |||
3149 | return ret; | ||
3150 | } | ||
3151 | EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); | ||
3152 | |||
3027 | /** | 3153 | /** |
3028 | * regulator_set_voltage_time - get raise/fall time | 3154 | * regulator_set_voltage_time - get raise/fall time |
3029 | * @regulator: regulator source | 3155 | * @regulator: regulator source |
@@ -3117,6 +3243,7 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); | |||
3117 | int regulator_sync_voltage(struct regulator *regulator) | 3243 | int regulator_sync_voltage(struct regulator *regulator) |
3118 | { | 3244 | { |
3119 | struct regulator_dev *rdev = regulator->rdev; | 3245 | struct regulator_dev *rdev = regulator->rdev; |
3246 | struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; | ||
3120 | int ret, min_uV, max_uV; | 3247 | int ret, min_uV, max_uV; |
3121 | 3248 | ||
3122 | mutex_lock(&rdev->mutex); | 3249 | mutex_lock(&rdev->mutex); |
@@ -3128,20 +3255,20 @@ int regulator_sync_voltage(struct regulator *regulator) | |||
3128 | } | 3255 | } |
3129 | 3256 | ||
3130 | /* This is only going to work if we've had a voltage configured. */ | 3257 | /* This is only going to work if we've had a voltage configured. */ |
3131 | if (!regulator->min_uV && !regulator->max_uV) { | 3258 | if (!voltage->min_uV && !voltage->max_uV) { |
3132 | ret = -EINVAL; | 3259 | ret = -EINVAL; |
3133 | goto out; | 3260 | goto out; |
3134 | } | 3261 | } |
3135 | 3262 | ||
3136 | min_uV = regulator->min_uV; | 3263 | min_uV = voltage->min_uV; |
3137 | max_uV = regulator->max_uV; | 3264 | max_uV = voltage->max_uV; |
3138 | 3265 | ||
3139 | /* This should be a paranoia check... */ | 3266 | /* This should be a paranoia check... */ |
3140 | ret = regulator_check_voltage(rdev, &min_uV, &max_uV); | 3267 | ret = regulator_check_voltage(rdev, &min_uV, &max_uV); |
3141 | if (ret < 0) | 3268 | if (ret < 0) |
3142 | goto out; | 3269 | goto out; |
3143 | 3270 | ||
3144 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV); | 3271 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); |
3145 | if (ret < 0) | 3272 | if (ret < 0) |
3146 | goto out; | 3273 | goto out; |
3147 | 3274 | ||
@@ -3897,12 +4024,6 @@ static void regulator_dev_release(struct device *dev) | |||
3897 | kfree(rdev); | 4024 | kfree(rdev); |
3898 | } | 4025 | } |
3899 | 4026 | ||
3900 | struct class regulator_class = { | ||
3901 | .name = "regulator", | ||
3902 | .dev_release = regulator_dev_release, | ||
3903 | .dev_groups = regulator_dev_groups, | ||
3904 | }; | ||
3905 | |||
3906 | static void rdev_init_debugfs(struct regulator_dev *rdev) | 4027 | static void rdev_init_debugfs(struct regulator_dev *rdev) |
3907 | { | 4028 | { |
3908 | struct device *parent = rdev->dev.parent; | 4029 | struct device *parent = rdev->dev.parent; |
@@ -4153,81 +4274,86 @@ void regulator_unregister(struct regulator_dev *rdev) | |||
4153 | } | 4274 | } |
4154 | EXPORT_SYMBOL_GPL(regulator_unregister); | 4275 | EXPORT_SYMBOL_GPL(regulator_unregister); |
4155 | 4276 | ||
4156 | static int _regulator_suspend_prepare(struct device *dev, void *data) | 4277 | #ifdef CONFIG_SUSPEND |
4278 | static int _regulator_suspend_late(struct device *dev, void *data) | ||
4157 | { | 4279 | { |
4158 | struct regulator_dev *rdev = dev_to_rdev(dev); | 4280 | struct regulator_dev *rdev = dev_to_rdev(dev); |
4159 | const suspend_state_t *state = data; | 4281 | suspend_state_t *state = data; |
4160 | int ret; | 4282 | int ret; |
4161 | 4283 | ||
4162 | mutex_lock(&rdev->mutex); | 4284 | mutex_lock(&rdev->mutex); |
4163 | ret = suspend_prepare(rdev, *state); | 4285 | ret = suspend_set_state(rdev, *state); |
4164 | mutex_unlock(&rdev->mutex); | 4286 | mutex_unlock(&rdev->mutex); |
4165 | 4287 | ||
4166 | return ret; | 4288 | return ret; |
4167 | } | 4289 | } |
4168 | 4290 | ||
4169 | /** | 4291 | /** |
4170 | * regulator_suspend_prepare - prepare regulators for system wide suspend | 4292 | * regulator_suspend_late - prepare regulators for system wide suspend |
4171 | * @state: system suspend state | 4293 | * @state: system suspend state |
4172 | * | 4294 | * |
4173 | * Configure each regulator with it's suspend operating parameters for state. | 4295 | * Configure each regulator with it's suspend operating parameters for state. |
4174 | * This will usually be called by machine suspend code prior to supending. | ||
4175 | */ | 4296 | */ |
4176 | int regulator_suspend_prepare(suspend_state_t state) | 4297 | static int regulator_suspend_late(struct device *dev) |
4177 | { | 4298 | { |
4178 | /* ON is handled by regulator active state */ | 4299 | suspend_state_t state = pm_suspend_target_state; |
4179 | if (state == PM_SUSPEND_ON) | ||
4180 | return -EINVAL; | ||
4181 | 4300 | ||
4182 | return class_for_each_device(®ulator_class, NULL, &state, | 4301 | return class_for_each_device(®ulator_class, NULL, &state, |
4183 | _regulator_suspend_prepare); | 4302 | _regulator_suspend_late); |
4184 | } | 4303 | } |
4185 | EXPORT_SYMBOL_GPL(regulator_suspend_prepare); | 4304 | static int _regulator_resume_early(struct device *dev, void *data) |
4186 | |||
4187 | static int _regulator_suspend_finish(struct device *dev, void *data) | ||
4188 | { | 4305 | { |
4306 | int ret = 0; | ||
4189 | struct regulator_dev *rdev = dev_to_rdev(dev); | 4307 | struct regulator_dev *rdev = dev_to_rdev(dev); |
4190 | int ret; | 4308 | suspend_state_t *state = data; |
4309 | struct regulator_state *rstate; | ||
4310 | |||
4311 | rstate = regulator_get_suspend_state(rdev, *state); | ||
4312 | if (rstate == NULL) | ||
4313 | return -EINVAL; | ||
4191 | 4314 | ||
4192 | mutex_lock(&rdev->mutex); | 4315 | mutex_lock(&rdev->mutex); |
4193 | if (rdev->use_count > 0 || rdev->constraints->always_on) { | ||
4194 | if (!_regulator_is_enabled(rdev)) { | ||
4195 | ret = _regulator_do_enable(rdev); | ||
4196 | if (ret) | ||
4197 | dev_err(dev, | ||
4198 | "Failed to resume regulator %d\n", | ||
4199 | ret); | ||
4200 | } | ||
4201 | } else { | ||
4202 | if (!have_full_constraints()) | ||
4203 | goto unlock; | ||
4204 | if (!_regulator_is_enabled(rdev)) | ||
4205 | goto unlock; | ||
4206 | 4316 | ||
4207 | ret = _regulator_do_disable(rdev); | 4317 | if (rdev->desc->ops->resume_early && |
4208 | if (ret) | 4318 | (rstate->enabled == ENABLE_IN_SUSPEND || |
4209 | dev_err(dev, "Failed to suspend regulator %d\n", ret); | 4319 | rstate->enabled == DISABLE_IN_SUSPEND)) |
4210 | } | 4320 | ret = rdev->desc->ops->resume_early(rdev); |
4211 | unlock: | 4321 | |
4212 | mutex_unlock(&rdev->mutex); | 4322 | mutex_unlock(&rdev->mutex); |
4213 | 4323 | ||
4214 | /* Keep processing regulators in spite of any errors */ | 4324 | return ret; |
4215 | return 0; | ||
4216 | } | 4325 | } |
4217 | 4326 | ||
4218 | /** | 4327 | static int regulator_resume_early(struct device *dev) |
4219 | * regulator_suspend_finish - resume regulators from system wide suspend | ||
4220 | * | ||
4221 | * Turn on regulators that might be turned off by regulator_suspend_prepare | ||
4222 | * and that should be turned on according to the regulators properties. | ||
4223 | */ | ||
4224 | int regulator_suspend_finish(void) | ||
4225 | { | 4328 | { |
4226 | return class_for_each_device(®ulator_class, NULL, NULL, | 4329 | suspend_state_t state = pm_suspend_target_state; |
4227 | _regulator_suspend_finish); | 4330 | |
4331 | return class_for_each_device(®ulator_class, NULL, &state, | ||
4332 | _regulator_resume_early); | ||
4228 | } | 4333 | } |
4229 | EXPORT_SYMBOL_GPL(regulator_suspend_finish); | ||
4230 | 4334 | ||
4335 | #else /* !CONFIG_SUSPEND */ | ||
4336 | |||
4337 | #define regulator_suspend_late NULL | ||
4338 | #define regulator_resume_early NULL | ||
4339 | |||
4340 | #endif /* !CONFIG_SUSPEND */ | ||
4341 | |||
4342 | #ifdef CONFIG_PM | ||
4343 | static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { | ||
4344 | .suspend_late = regulator_suspend_late, | ||
4345 | .resume_early = regulator_resume_early, | ||
4346 | }; | ||
4347 | #endif | ||
4348 | |||
4349 | struct class regulator_class = { | ||
4350 | .name = "regulator", | ||
4351 | .dev_release = regulator_dev_release, | ||
4352 | .dev_groups = regulator_dev_groups, | ||
4353 | #ifdef CONFIG_PM | ||
4354 | .pm = ®ulator_pm_ops, | ||
4355 | #endif | ||
4356 | }; | ||
4231 | /** | 4357 | /** |
4232 | * regulator_has_full_constraints - the system has fully specified constraints | 4358 | * regulator_has_full_constraints - the system has fully specified constraints |
4233 | * | 4359 | * |
@@ -4403,8 +4529,8 @@ static void regulator_summary_show_subtree(struct seq_file *s, | |||
4403 | switch (rdev->desc->type) { | 4529 | switch (rdev->desc->type) { |
4404 | case REGULATOR_VOLTAGE: | 4530 | case REGULATOR_VOLTAGE: |
4405 | seq_printf(s, "%37dmV %5dmV", | 4531 | seq_printf(s, "%37dmV %5dmV", |
4406 | consumer->min_uV / 1000, | 4532 | consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, |
4407 | consumer->max_uV / 1000); | 4533 | consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); |
4408 | break; | 4534 | break; |
4409 | case REGULATOR_CURRENT: | 4535 | case REGULATOR_CURRENT: |
4410 | break; | 4536 | break; |
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 2f3218be5b8d..abfd56e8c78a 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h | |||
@@ -16,10 +16,25 @@ | |||
16 | #ifndef __REGULATOR_INTERNAL_H | 16 | #ifndef __REGULATOR_INTERNAL_H |
17 | #define __REGULATOR_INTERNAL_H | 17 | #define __REGULATOR_INTERNAL_H |
18 | 18 | ||
19 | #include <linux/suspend.h> | ||
20 | |||
21 | #define REGULATOR_STATES_NUM (PM_SUSPEND_MAX + 1) | ||
22 | |||
23 | struct regulator_voltage { | ||
24 | int min_uV; | ||
25 | int max_uV; | ||
26 | }; | ||
27 | |||
19 | /* | 28 | /* |
20 | * struct regulator | 29 | * struct regulator |
21 | * | 30 | * |
22 | * One for each consumer device. | 31 | * One for each consumer device. |
32 | * @voltage - a voltage array for each state of runtime, i.e.: | ||
33 | * PM_SUSPEND_ON | ||
34 | * PM_SUSPEND_TO_IDLE | ||
35 | * PM_SUSPEND_STANDBY | ||
36 | * PM_SUSPEND_MEM | ||
37 | * PM_SUSPEND_MAX | ||
23 | */ | 38 | */ |
24 | struct regulator { | 39 | struct regulator { |
25 | struct device *dev; | 40 | struct device *dev; |
@@ -27,8 +42,7 @@ struct regulator { | |||
27 | unsigned int always_on:1; | 42 | unsigned int always_on:1; |
28 | unsigned int bypass:1; | 43 | unsigned int bypass:1; |
29 | int uA_load; | 44 | int uA_load; |
30 | int min_uV; | 45 | struct regulator_voltage voltage[REGULATOR_STATES_NUM]; |
31 | int max_uV; | ||
32 | const char *supply_name; | 46 | const char *supply_name; |
33 | struct device_attribute dev_attr; | 47 | struct device_attribute dev_attr; |
34 | struct regulator_dev *rdev; | 48 | struct regulator_dev *rdev; |
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 54e810ae93d6..092ed6efb3ec 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c | |||
@@ -177,14 +177,30 @@ static void of_get_regulation_constraints(struct device_node *np, | |||
177 | 177 | ||
178 | if (of_property_read_bool(suspend_np, | 178 | if (of_property_read_bool(suspend_np, |
179 | "regulator-on-in-suspend")) | 179 | "regulator-on-in-suspend")) |
180 | suspend_state->enabled = true; | 180 | suspend_state->enabled = ENABLE_IN_SUSPEND; |
181 | else if (of_property_read_bool(suspend_np, | 181 | else if (of_property_read_bool(suspend_np, |
182 | "regulator-off-in-suspend")) | 182 | "regulator-off-in-suspend")) |
183 | suspend_state->disabled = true; | 183 | suspend_state->enabled = DISABLE_IN_SUSPEND; |
184 | else | ||
185 | suspend_state->enabled = DO_NOTHING_IN_SUSPEND; | ||
186 | |||
187 | if (!of_property_read_u32(np, "regulator-suspend-min-microvolt", | ||
188 | &pval)) | ||
189 | suspend_state->min_uV = pval; | ||
190 | |||
191 | if (!of_property_read_u32(np, "regulator-suspend-max-microvolt", | ||
192 | &pval)) | ||
193 | suspend_state->max_uV = pval; | ||
184 | 194 | ||
185 | if (!of_property_read_u32(suspend_np, | 195 | if (!of_property_read_u32(suspend_np, |
186 | "regulator-suspend-microvolt", &pval)) | 196 | "regulator-suspend-microvolt", &pval)) |
187 | suspend_state->uV = pval; | 197 | suspend_state->uV = pval; |
198 | else /* otherwise use min_uV as default suspend voltage */ | ||
199 | suspend_state->uV = suspend_state->min_uV; | ||
200 | |||
201 | if (of_property_read_bool(suspend_np, | ||
202 | "regulator-changeable-in-suspend")) | ||
203 | suspend_state->changeable = true; | ||
188 | 204 | ||
189 | if (i == PM_SUSPEND_MEM) | 205 | if (i == PM_SUSPEND_MEM) |
190 | constraints->initial_state = PM_SUSPEND_MEM; | 206 | constraints->initial_state = PM_SUSPEND_MEM; |
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 94417b4226bd..4c00486b7a78 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
@@ -214,6 +214,8 @@ struct regulator_ops { | |||
214 | /* set regulator suspend operating mode (defined in consumer.h) */ | 214 | /* set regulator suspend operating mode (defined in consumer.h) */ |
215 | int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode); | 215 | int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode); |
216 | 216 | ||
217 | int (*resume_early)(struct regulator_dev *rdev); | ||
218 | |||
217 | int (*set_pull_down) (struct regulator_dev *); | 219 | int (*set_pull_down) (struct regulator_dev *); |
218 | }; | 220 | }; |
219 | 221 | ||
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 9cd4fef37203..93a04893c739 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h | |||
@@ -42,6 +42,16 @@ struct regulator; | |||
42 | #define REGULATOR_CHANGE_DRMS 0x10 | 42 | #define REGULATOR_CHANGE_DRMS 0x10 |
43 | #define REGULATOR_CHANGE_BYPASS 0x20 | 43 | #define REGULATOR_CHANGE_BYPASS 0x20 |
44 | 44 | ||
45 | /* | ||
46 | * operations in suspend mode | ||
47 | * DO_NOTHING_IN_SUSPEND - the default value | ||
48 | * DISABLE_IN_SUSPEND - turn off regulator in suspend states | ||
49 | * ENABLE_IN_SUSPEND - keep regulator on in suspend states | ||
50 | */ | ||
51 | #define DO_NOTHING_IN_SUSPEND (-1) | ||
52 | #define DISABLE_IN_SUSPEND 0 | ||
53 | #define ENABLE_IN_SUSPEND 1 | ||
54 | |||
45 | /* Regulator active discharge flags */ | 55 | /* Regulator active discharge flags */ |
46 | enum regulator_active_discharge { | 56 | enum regulator_active_discharge { |
47 | REGULATOR_ACTIVE_DISCHARGE_DEFAULT, | 57 | REGULATOR_ACTIVE_DISCHARGE_DEFAULT, |
@@ -56,16 +66,24 @@ enum regulator_active_discharge { | |||
56 | * state. One of enabled or disabled must be set for the | 66 | * state. One of enabled or disabled must be set for the |
57 | * configuration to be applied. | 67 | * configuration to be applied. |
58 | * | 68 | * |
59 | * @uV: Operating voltage during suspend. | 69 | * @uV: Default operating voltage during suspend, it can be adjusted |
70 | * among <min_uV, max_uV>. | ||
71 | * @min_uV: Minimum suspend voltage may be set. | ||
72 | * @max_uV: Maximum suspend voltage may be set. | ||
60 | * @mode: Operating mode during suspend. | 73 | * @mode: Operating mode during suspend. |
61 | * @enabled: Enabled during suspend. | 74 | * @enabled: operations during suspend. |
62 | * @disabled: Disabled during suspend. | 75 | * - DO_NOTHING_IN_SUSPEND |
76 | * - DISABLE_IN_SUSPEND | ||
77 | * - ENABLE_IN_SUSPEND | ||
78 | * @changeable: Is this state can be switched between enabled/disabled, | ||
63 | */ | 79 | */ |
64 | struct regulator_state { | 80 | struct regulator_state { |
65 | int uV; /* suspend voltage */ | 81 | int uV; |
66 | unsigned int mode; /* suspend regulator operating mode */ | 82 | int min_uV; |
67 | int enabled; /* is regulator enabled in this suspend state */ | 83 | int max_uV; |
68 | int disabled; /* is the regulator disabled in this suspend state */ | 84 | unsigned int mode; |
85 | int enabled; | ||
86 | bool changeable; | ||
69 | }; | 87 | }; |
70 | 88 | ||
71 | /** | 89 | /** |
@@ -225,12 +243,12 @@ struct regulator_init_data { | |||
225 | 243 | ||
226 | #ifdef CONFIG_REGULATOR | 244 | #ifdef CONFIG_REGULATOR |
227 | void regulator_has_full_constraints(void); | 245 | void regulator_has_full_constraints(void); |
228 | int regulator_suspend_prepare(suspend_state_t state); | ||
229 | int regulator_suspend_finish(void); | ||
230 | #else | 246 | #else |
231 | static inline void regulator_has_full_constraints(void) | 247 | static inline void regulator_has_full_constraints(void) |
232 | { | 248 | { |
233 | } | 249 | } |
250 | #endif | ||
251 | |||
234 | static inline int regulator_suspend_prepare(suspend_state_t state) | 252 | static inline int regulator_suspend_prepare(suspend_state_t state) |
235 | { | 253 | { |
236 | return 0; | 254 | return 0; |
@@ -239,6 +257,5 @@ static inline int regulator_suspend_finish(void) | |||
239 | { | 257 | { |
240 | return 0; | 258 | return 0; |
241 | } | 259 | } |
242 | #endif | ||
243 | 260 | ||
244 | #endif | 261 | #endif |