@@ -107,6 +107,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
107107 int min_uV , int max_uV );
108108static 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 );
110113static 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
31223180out :
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