Commit c360a6df authored by Chunyan Zhang's avatar Chunyan Zhang Committed by Mark Brown

regulator: make regulator voltage be an array to support more states

Some regulator consumers would like to make the regulator device
keeping a voltage range output when the system entering into
suspend states.

Making regulator voltage be an array can allow consumers to set voltage
for normal state as well as for suspend states through the same code.
Signed-off-by: default avatarChunyan Zhang <zhang.chunyan@linaro.org>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 057c7644
...@@ -240,22 +240,25 @@ static int regulator_check_voltage(struct regulator_dev *rdev, ...@@ -240,22 +240,25 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
* regulator consumers * regulator consumers
*/ */
static int regulator_check_consumers(struct regulator_dev *rdev, static int regulator_check_consumers(struct regulator_dev *rdev,
int *min_uV, int *max_uV) int *min_uV, int *max_uV,
suspend_state_t state)
{ {
struct regulator *regulator; struct regulator *regulator;
struct regulator_voltage *voltage;
list_for_each_entry(regulator, &rdev->consumer_list, list) { list_for_each_entry(regulator, &rdev->consumer_list, list) {
voltage = &regulator->voltage[state];
/* /*
* Assume consumers that didn't say anything are OK * Assume consumers that didn't say anything are OK
* with anything in the constraint range. * with anything in the constraint range.
*/ */
if (!regulator->min_uV && !regulator->max_uV) if (!voltage->min_uV && !voltage->max_uV)
continue; continue;
if (*max_uV > regulator->max_uV) if (*max_uV > voltage->max_uV)
*max_uV = regulator->max_uV; *max_uV = voltage->max_uV;
if (*min_uV < regulator->min_uV) if (*min_uV < voltage->min_uV)
*min_uV = regulator->min_uV; *min_uV = voltage->min_uV;
} }
if (*min_uV > *max_uV) { if (*min_uV > *max_uV) {
...@@ -1356,9 +1359,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, ...@@ -1356,9 +1359,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
debugfs_create_u32("uA_load", 0444, regulator->debugfs, debugfs_create_u32("uA_load", 0444, regulator->debugfs,
&regulator->uA_load); &regulator->uA_load);
debugfs_create_u32("min_uV", 0444, regulator->debugfs, debugfs_create_u32("min_uV", 0444, regulator->debugfs,
&regulator->min_uV); &regulator->voltage[PM_SUSPEND_ON].min_uV);
debugfs_create_u32("max_uV", 0444, regulator->debugfs, debugfs_create_u32("max_uV", 0444, regulator->debugfs,
&regulator->max_uV); &regulator->voltage[PM_SUSPEND_ON].max_uV);
debugfs_create_file("constraint_flags", 0444, debugfs_create_file("constraint_flags", 0444,
regulator->debugfs, regulator, regulator->debugfs, regulator,
&constraint_flags_fops); &constraint_flags_fops);
...@@ -2898,9 +2901,11 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, ...@@ -2898,9 +2901,11 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
} }
static int regulator_set_voltage_unlocked(struct regulator *regulator, static int regulator_set_voltage_unlocked(struct regulator *regulator,
int min_uV, int max_uV) int min_uV, int max_uV,
suspend_state_t state)
{ {
struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *rdev = regulator->rdev;
struct regulator_voltage *voltage = &regulator->voltage[state];
int ret = 0; int ret = 0;
int old_min_uV, old_max_uV; int old_min_uV, old_max_uV;
int current_uV; int current_uV;
...@@ -2911,7 +2916,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, ...@@ -2911,7 +2916,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
* should be a noop (some cpufreq implementations use the same * should be a noop (some cpufreq implementations use the same
* voltage for multiple frequencies, for example). * voltage for multiple frequencies, for example).
*/ */
if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) if (voltage->min_uV == min_uV && voltage->max_uV == max_uV)
goto out; goto out;
/* If we're trying to set a range that overlaps the current voltage, /* If we're trying to set a range that overlaps the current voltage,
...@@ -2921,8 +2926,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, ...@@ -2921,8 +2926,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
current_uV = _regulator_get_voltage(rdev); current_uV = _regulator_get_voltage(rdev);
if (min_uV <= current_uV && current_uV <= max_uV) { if (min_uV <= current_uV && current_uV <= max_uV) {
regulator->min_uV = min_uV; voltage->min_uV = min_uV;
regulator->max_uV = max_uV; voltage->max_uV = max_uV;
goto out; goto out;
} }
} }
...@@ -2940,12 +2945,12 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, ...@@ -2940,12 +2945,12 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
goto out; goto out;
/* restore original values in case of error */ /* restore original values in case of error */
old_min_uV = regulator->min_uV; old_min_uV = voltage->min_uV;
old_max_uV = regulator->max_uV; old_max_uV = voltage->max_uV;
regulator->min_uV = min_uV; voltage->min_uV = min_uV;
regulator->max_uV = max_uV; voltage->max_uV = max_uV;
ret = regulator_check_consumers(rdev, &min_uV, &max_uV); ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state);
if (ret < 0) if (ret < 0)
goto out2; goto out2;
...@@ -2982,7 +2987,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, ...@@ -2982,7 +2987,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (supply_change_uV > 0) { if (supply_change_uV > 0) {
ret = regulator_set_voltage_unlocked(rdev->supply, ret = regulator_set_voltage_unlocked(rdev->supply,
best_supply_uV, INT_MAX); best_supply_uV, INT_MAX, state);
if (ret) { if (ret) {
dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
ret); ret);
...@@ -2996,7 +3001,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, ...@@ -2996,7 +3001,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (supply_change_uV < 0) { if (supply_change_uV < 0) {
ret = regulator_set_voltage_unlocked(rdev->supply, ret = regulator_set_voltage_unlocked(rdev->supply,
best_supply_uV, INT_MAX); best_supply_uV, INT_MAX, state);
if (ret) if (ret)
dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n",
ret); ret);
...@@ -3007,8 +3012,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator, ...@@ -3007,8 +3012,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
out: out:
return ret; return ret;
out2: out2:
regulator->min_uV = old_min_uV; voltage->min_uV = old_min_uV;
regulator->max_uV = old_max_uV; voltage->max_uV = old_max_uV;
return ret; return ret;
} }
...@@ -3037,7 +3042,8 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) ...@@ -3037,7 +3042,8 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
regulator_lock_supply(regulator->rdev); regulator_lock_supply(regulator->rdev);
ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
PM_SUSPEND_ON);
regulator_unlock_supply(regulator->rdev); regulator_unlock_supply(regulator->rdev);
...@@ -3138,6 +3144,7 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); ...@@ -3138,6 +3144,7 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
int regulator_sync_voltage(struct regulator *regulator) int regulator_sync_voltage(struct regulator *regulator)
{ {
struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *rdev = regulator->rdev;
struct regulator_voltage *voltage = &regulator->voltage[PM_SUSPEND_ON];
int ret, min_uV, max_uV; int ret, min_uV, max_uV;
mutex_lock(&rdev->mutex); mutex_lock(&rdev->mutex);
...@@ -3149,20 +3156,20 @@ int regulator_sync_voltage(struct regulator *regulator) ...@@ -3149,20 +3156,20 @@ int regulator_sync_voltage(struct regulator *regulator)
} }
/* This is only going to work if we've had a voltage configured. */ /* This is only going to work if we've had a voltage configured. */
if (!regulator->min_uV && !regulator->max_uV) { if (!voltage->min_uV && !voltage->max_uV) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
min_uV = regulator->min_uV; min_uV = voltage->min_uV;
max_uV = regulator->max_uV; max_uV = voltage->max_uV;
/* This should be a paranoia check... */ /* This should be a paranoia check... */
ret = regulator_check_voltage(rdev, &min_uV, &max_uV); ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
if (ret < 0) if (ret < 0)
goto out; goto out;
ret = regulator_check_consumers(rdev, &min_uV, &max_uV); ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -4424,8 +4431,8 @@ static void regulator_summary_show_subtree(struct seq_file *s, ...@@ -4424,8 +4431,8 @@ static void regulator_summary_show_subtree(struct seq_file *s,
switch (rdev->desc->type) { switch (rdev->desc->type) {
case REGULATOR_VOLTAGE: case REGULATOR_VOLTAGE:
seq_printf(s, "%37dmV %5dmV", seq_printf(s, "%37dmV %5dmV",
consumer->min_uV / 1000, consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
consumer->max_uV / 1000); consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
break; break;
case REGULATOR_CURRENT: case REGULATOR_CURRENT:
break; break;
......
...@@ -16,10 +16,25 @@ ...@@ -16,10 +16,25 @@
#ifndef __REGULATOR_INTERNAL_H #ifndef __REGULATOR_INTERNAL_H
#define __REGULATOR_INTERNAL_H #define __REGULATOR_INTERNAL_H
#include <linux/suspend.h>
#define REGULATOR_STATES_NUM (PM_SUSPEND_MAX + 1)
struct regulator_voltage {
int min_uV;
int max_uV;
};
/* /*
* struct regulator * struct regulator
* *
* One for each consumer device. * One for each consumer device.
* @voltage - a voltage array for each state of runtime, i.e.:
* PM_SUSPEND_ON
* PM_SUSPEND_TO_IDLE
* PM_SUSPEND_STANDBY
* PM_SUSPEND_MEM
* PM_SUSPEND_MAX
*/ */
struct regulator { struct regulator {
struct device *dev; struct device *dev;
...@@ -27,8 +42,7 @@ struct regulator { ...@@ -27,8 +42,7 @@ struct regulator {
unsigned int always_on:1; unsigned int always_on:1;
unsigned int bypass:1; unsigned int bypass:1;
int uA_load; int uA_load;
int min_uV; struct regulator_voltage voltage[REGULATOR_STATES_NUM];
int max_uV;
const char *supply_name; const char *supply_name;
struct device_attribute dev_attr; struct device_attribute dev_attr;
struct regulator_dev *rdev; struct regulator_dev *rdev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment