Skip to content

Commit 9243a19

Browse files
Maciej Purskibroonie
Maciej Purski
authored andcommitted
regulator: core: Change voltage setting path
On Odroid XU3/4 and other Exynos5422 based boards there is a case, that different devices on the board are supplied by different regulators with non-fixed voltages. If one of these devices temporarily requires higher voltage, there might occur a situation that the spread between two devices' voltages is so high, that there is a risk of changing 'high' and 'low' states on the interconnection between devices powered by those regulators. Uncoupled regulators should be a special case of coupled regulators, so they should share a common voltage setting path. When enabling, disabling or setting voltage of a coupled regulator, all coupled regulators should be locked. Regulator's supplies should be locked, when setting voltage of a single regulator. Enabling a coupled regulator or setting its voltage should not be possible if some of its coupled regulators, has not been registered. Add function for locking coupled regulators and supplies. Extract a new function regulator_set_voltage_rdev() from regulator_set_voltage_unlocked(), which is called when setting voltage of a single regulator. Signed-off-by: Maciej Purski <[email protected]> Signed-off-by: Dmitry Osipenko <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent c054c6c commit 9243a19

File tree

1 file changed

+99
-46
lines changed

1 file changed

+99
-46
lines changed

drivers/regulator/core.c

Lines changed: 99 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
107107
int min_uV, int max_uV);
108108
static int regulator_balance_voltage(struct regulator_dev *rdev,
109109
suspend_state_t state);
110+
static int regulator_set_voltage_rdev(struct regulator_dev *rdev,
111+
int min_uV, int max_uV,
112+
suspend_state_t state);
110113
static struct regulator *create_regulator(struct regulator_dev *rdev,
111114
struct device *dev,
112115
const char *supply_name);
@@ -198,37 +201,66 @@ static void regulator_unlock(struct regulator_dev *rdev)
198201
}
199202
}
200203

201-
/**
202-
* regulator_lock_supply - lock a regulator and its supplies
203-
* @rdev: regulator source
204-
*/
205-
static void regulator_lock_supply(struct regulator_dev *rdev)
204+
static int regulator_lock_recursive(struct regulator_dev *rdev,
205+
unsigned int subclass)
206206
{
207+
struct regulator_dev *c_rdev;
207208
int i;
208209

209-
for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++)
210-
regulator_lock_nested(rdev, i);
210+
for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
211+
c_rdev = rdev->coupling_desc.coupled_rdevs[i];
212+
213+
if (!c_rdev)
214+
continue;
215+
216+
regulator_lock_nested(c_rdev, subclass++);
217+
218+
if (c_rdev->supply)
219+
subclass =
220+
regulator_lock_recursive(c_rdev->supply->rdev,
221+
subclass);
222+
}
223+
224+
return subclass;
211225
}
212226

213227
/**
214-
* regulator_unlock_supply - unlock a regulator and its supplies
215-
* @rdev: regulator source
228+
* regulator_unlock_dependent - unlock regulator's suppliers and coupled
229+
* regulators
230+
* @rdev: regulator source
231+
*
232+
* Unlock all regulators related with rdev by coupling or suppling.
216233
*/
217-
static void regulator_unlock_supply(struct regulator_dev *rdev)
234+
static void regulator_unlock_dependent(struct regulator_dev *rdev)
218235
{
219-
struct regulator *supply;
236+
struct regulator_dev *c_rdev;
237+
int i;
220238

221-
while (1) {
222-
regulator_unlock(rdev);
223-
supply = rdev->supply;
239+
for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
240+
c_rdev = rdev->coupling_desc.coupled_rdevs[i];
224241

225-
if (!rdev->supply)
226-
return;
242+
if (!c_rdev)
243+
continue;
227244

228-
rdev = supply->rdev;
245+
regulator_unlock(c_rdev);
246+
247+
if (c_rdev->supply)
248+
regulator_unlock_dependent(c_rdev->supply->rdev);
229249
}
230250
}
231251

252+
/**
253+
* regulator_lock_dependent - lock regulator's suppliers and coupled regulators
254+
* @rdev: regulator source
255+
*
256+
* This function as a wrapper on regulator_lock_recursive(), which locks
257+
* all regulators related with rdev by coupling or suppling.
258+
*/
259+
static inline void regulator_lock_dependent(struct regulator_dev *rdev)
260+
{
261+
regulator_lock_recursive(rdev, 0);
262+
}
263+
232264
/**
233265
* of_get_regulator - get a regulator device node based on supply name
234266
* @dev: Device pointer for the consumer (of regulator) device
@@ -2289,9 +2321,16 @@ int regulator_enable(struct regulator *regulator)
22892321
return ret;
22902322
}
22912323

2292-
mutex_lock(&rdev->mutex);
2324+
regulator_lock_dependent(rdev);
2325+
/* balance only if there are regulators coupled */
2326+
if (rdev->coupling_desc.n_coupled > 1) {
2327+
ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
2328+
if (ret != 0)
2329+
goto unlock;
2330+
}
22932331
ret = _regulator_enable(rdev);
2294-
mutex_unlock(&rdev->mutex);
2332+
unlock:
2333+
regulator_unlock_dependent(rdev);
22952334

22962335
if (ret != 0 && rdev->supply)
22972336
regulator_disable(rdev->supply);
@@ -2397,9 +2436,11 @@ int regulator_disable(struct regulator *regulator)
23972436
if (regulator->always_on)
23982437
return 0;
23992438

2400-
mutex_lock(&rdev->mutex);
2439+
regulator_lock_dependent(rdev);
24012440
ret = _regulator_disable(rdev);
2402-
mutex_unlock(&rdev->mutex);
2441+
if (rdev->coupling_desc.n_coupled > 1)
2442+
regulator_balance_voltage(rdev, PM_SUSPEND_ON);
2443+
regulator_unlock_dependent(rdev);
24032444

24042445
if (ret == 0 && rdev->supply)
24052446
regulator_disable(rdev->supply);
@@ -2448,10 +2489,12 @@ int regulator_force_disable(struct regulator *regulator)
24482489
struct regulator_dev *rdev = regulator->rdev;
24492490
int ret;
24502491

2451-
mutex_lock(&rdev->mutex);
2492+
regulator_lock_dependent(rdev);
24522493
regulator->uA_load = 0;
24532494
ret = _regulator_force_disable(regulator->rdev);
2454-
mutex_unlock(&rdev->mutex);
2495+
if (rdev->coupling_desc.n_coupled > 1)
2496+
regulator_balance_voltage(rdev, PM_SUSPEND_ON);
2497+
regulator_unlock_dependent(rdev);
24552498

24562499
if (rdev->supply)
24572500
while (rdev->open_count--)
@@ -2599,9 +2642,9 @@ int regulator_is_enabled(struct regulator *regulator)
25992642
if (regulator->always_on)
26002643
return 1;
26012644

2602-
mutex_lock(&regulator->rdev->mutex);
2645+
regulator_lock_dependent(regulator->rdev);
26032646
ret = _regulator_is_enabled(regulator->rdev);
2604-
mutex_unlock(&regulator->rdev->mutex);
2647+
regulator_unlock_dependent(regulator->rdev);
26052648

26062649
return ret;
26072650
}
@@ -3015,8 +3058,6 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
30153058
int ret = 0;
30163059
int old_min_uV, old_max_uV;
30173060
int current_uV;
3018-
int best_supply_uV = 0;
3019-
int supply_change_uV = 0;
30203061

30213062
/* If we're setting the same range as last time the change
30223063
* should be a noop (some cpufreq implementations use the same
@@ -3056,10 +3097,27 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
30563097
voltage->min_uV = min_uV;
30573098
voltage->max_uV = max_uV;
30583099

3059-
ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state);
3100+
/* for not coupled regulators this will just set the voltage */
3101+
ret = regulator_balance_voltage(rdev, state);
30603102
if (ret < 0)
30613103
goto out2;
30623104

3105+
out:
3106+
return 0;
3107+
out2:
3108+
voltage->min_uV = old_min_uV;
3109+
voltage->max_uV = old_max_uV;
3110+
3111+
return ret;
3112+
}
3113+
3114+
static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
3115+
int max_uV, suspend_state_t state)
3116+
{
3117+
int best_supply_uV = 0;
3118+
int supply_change_uV = 0;
3119+
int ret;
3120+
30633121
if (rdev->supply &&
30643122
regulator_ops_is_valid(rdev->supply->rdev,
30653123
REGULATOR_CHANGE_VOLTAGE) &&
@@ -3071,21 +3129,21 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
30713129
selector = regulator_map_voltage(rdev, min_uV, max_uV);
30723130
if (selector < 0) {
30733131
ret = selector;
3074-
goto out2;
3132+
goto out;
30753133
}
30763134

30773135
best_supply_uV = _regulator_list_voltage(rdev, selector, 0);
30783136
if (best_supply_uV < 0) {
30793137
ret = best_supply_uV;
3080-
goto out2;
3138+
goto out;
30813139
}
30823140

30833141
best_supply_uV += rdev->desc->min_dropout_uV;
30843142

30853143
current_supply_uV = _regulator_get_voltage(rdev->supply->rdev);
30863144
if (current_supply_uV < 0) {
30873145
ret = current_supply_uV;
3088-
goto out2;
3146+
goto out;
30893147
}
30903148

30913149
supply_change_uV = best_supply_uV - current_supply_uV;
@@ -3097,7 +3155,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
30973155
if (ret) {
30983156
dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
30993157
ret);
3100-
goto out2;
3158+
goto out;
31013159
}
31023160
}
31033161

@@ -3107,7 +3165,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
31073165
ret = _regulator_do_set_suspend_voltage(rdev, min_uV,
31083166
max_uV, state);
31093167
if (ret < 0)
3110-
goto out2;
3168+
goto out;
31113169

31123170
if (supply_change_uV < 0) {
31133171
ret = regulator_set_voltage_unlocked(rdev->supply,
@@ -3120,11 +3178,6 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
31203178
}
31213179

31223180
out:
3123-
return ret;
3124-
out2:
3125-
voltage->min_uV = old_min_uV;
3126-
voltage->max_uV = old_max_uV;
3127-
31283181
return ret;
31293182
}
31303183

@@ -3340,10 +3393,10 @@ static int regulator_balance_voltage(struct regulator_dev *rdev,
33403393
ret = 0;
33413394
goto out;
33423395
}
3343-
#if 0
3396+
33443397
ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
33453398
best_max_uV, state);
3346-
#endif
3399+
33473400
if (ret < 0)
33483401
goto out;
33493402

@@ -3377,12 +3430,12 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
33773430
{
33783431
int ret = 0;
33793432

3380-
regulator_lock_supply(regulator->rdev);
3433+
regulator_lock_dependent(regulator->rdev);
33813434

33823435
ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
33833436
PM_SUSPEND_ON);
33843437

3385-
regulator_unlock_supply(regulator->rdev);
3438+
regulator_unlock_dependent(regulator->rdev);
33863439

33873440
return ret;
33883441
}
@@ -3460,12 +3513,12 @@ int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
34603513
if (regulator_check_states(state) || state == PM_SUSPEND_ON)
34613514
return -EINVAL;
34623515

3463-
regulator_lock_supply(regulator->rdev);
3516+
regulator_lock_dependent(regulator->rdev);
34643517

34653518
ret = _regulator_set_suspend_voltage(regulator, min_uV,
34663519
max_uV, state);
34673520

3468-
regulator_unlock_supply(regulator->rdev);
3521+
regulator_unlock_dependent(regulator->rdev);
34693522

34703523
return ret;
34713524
}
@@ -3657,11 +3710,11 @@ int regulator_get_voltage(struct regulator *regulator)
36573710
{
36583711
int ret;
36593712

3660-
regulator_lock_supply(regulator->rdev);
3713+
regulator_lock_dependent(regulator->rdev);
36613714

36623715
ret = _regulator_get_voltage(regulator->rdev);
36633716

3664-
regulator_unlock_supply(regulator->rdev);
3717+
regulator_unlock_dependent(regulator->rdev);
36653718

36663719
return ret;
36673720
}

0 commit comments

Comments
 (0)