Skip to content

Commit 85254bc

Browse files
digetxbroonie
authored andcommitted
regulator: core: Add new max_uV_step constraint
On NVIDIA Tegra30 there is a requirement for regulator "A" to have voltage higher than voltage of regulator "B" by N microvolts, the N value changes depending on the voltage of regulator "B". This is similar to min-spread between voltages of regulators, the difference is that the spread value isn't fixed. This means that extra carefulness is required for regulator "A" to drop its voltage without violating the requirement, hence its voltage should be changed in steps so that its couple "B" could follow (there is also max-spread requirement). Add new "max_uV_step" constraint that breaks voltage change into several steps, each step is limited by the max_uV_step value. Signed-off-by: Dmitry Osipenko <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent a2dfe7c commit 85254bc

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

drivers/regulator/core.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,6 +3191,36 @@ static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
31913191
return ret;
31923192
}
31933193

3194+
static int regulator_limit_voltage_step(struct regulator_dev *rdev,
3195+
int *current_uV, int *min_uV)
3196+
{
3197+
struct regulation_constraints *constraints = rdev->constraints;
3198+
3199+
/* Limit voltage change only if necessary */
3200+
if (!constraints->max_uV_step || !_regulator_is_enabled(rdev))
3201+
return 1;
3202+
3203+
if (*current_uV < 0) {
3204+
*current_uV = _regulator_get_voltage(rdev);
3205+
3206+
if (*current_uV < 0)
3207+
return *current_uV;
3208+
}
3209+
3210+
if (abs(*current_uV - *min_uV) <= constraints->max_uV_step)
3211+
return 1;
3212+
3213+
/* Clamp target voltage within the given step */
3214+
if (*current_uV < *min_uV)
3215+
*min_uV = min(*current_uV + constraints->max_uV_step,
3216+
*min_uV);
3217+
else
3218+
*min_uV = max(*current_uV - constraints->max_uV_step,
3219+
*min_uV);
3220+
3221+
return 0;
3222+
}
3223+
31943224
static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
31953225
int *current_uV,
31963226
int *min_uV, int *max_uV,
@@ -3302,6 +3332,17 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
33023332
desired_min_uV = possible_uV;
33033333

33043334
finish:
3335+
/* Apply max_uV_step constraint if necessary */
3336+
if (state == PM_SUSPEND_ON) {
3337+
ret = regulator_limit_voltage_step(rdev, current_uV,
3338+
&desired_min_uV);
3339+
if (ret < 0)
3340+
return ret;
3341+
3342+
if (ret == 0)
3343+
done = false;
3344+
}
3345+
33053346
/* Set current_uV if wasn't done earlier in the code and if necessary */
33063347
if (n_coupled > 1 && *current_uV == -1) {
33073348

drivers/regulator/of_regulator.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ static void of_get_regulation_constraints(struct device_node *np,
170170
&pval))
171171
constraints->max_spread = pval;
172172

173+
if (!of_property_read_u32(np, "regulator-max-step-microvolt",
174+
&pval))
175+
constraints->max_uV_step = pval;
176+
173177
constraints->over_current_protection = of_property_read_bool(np,
174178
"regulator-over-current-protection");
175179

include/linux/regulator/machine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ struct regulation_constraints {
158158
/* used for coupled regulators */
159159
int max_spread;
160160

161+
/* used for changing voltage in steps */
162+
int max_uV_step;
163+
161164
/* valid regulator operating modes for this machine */
162165
unsigned int valid_modes_mask;
163166

0 commit comments

Comments
 (0)