}
/**
- * regulator_unlock_supply - unlock a regulator and its supplies
- * @rdev: regulator source
+ * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
+ * @rdev: regulator source
+ * @ww_ctx: w/w mutex acquire context
+ *
+ * This function as a wrapper on regulator_lock_recursive(), which locks
+ * all regulators related with rdev by coupling or suppling.
*/
- static void regulator_unlock_supply(struct regulator_dev *rdev)
+ static void regulator_lock_dependent(struct regulator_dev *rdev,
+ struct ww_acquire_ctx *ww_ctx)
{
- struct regulator *supply;
+ struct regulator_dev *new_contended_rdev = NULL;
+ struct regulator_dev *old_contended_rdev = NULL;
+ int err;
- while (1) {
- regulator_unlock(rdev);
- supply = rdev->supply;
+ mutex_lock(®ulator_list_mutex);
- if (!rdev->supply)
- return;
+ ww_acquire_init(ww_ctx, ®ulator_ww_class);
- rdev = supply->rdev;
- }
+ do {
+ if (new_contended_rdev) {
+ ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
+ old_contended_rdev = new_contended_rdev;
+ old_contended_rdev->ref_cnt++;
+ }
+
+ err = regulator_lock_recursive(rdev,
+ &new_contended_rdev,
+ &old_contended_rdev,
+ ww_ctx);
+
+ if (old_contended_rdev)
+ regulator_unlock(old_contended_rdev);
+
+ } while (err == -EDEADLK);
+
+ ww_acquire_done(ww_ctx);
+
+ mutex_unlock(®ulator_list_mutex);
}
+/**
+ * of_get_child_regulator - get a child regulator device node
+ * based on supply name
+ * @parent: Parent device node
+ * @prop_name: Combination regulator supply name and "-supply"
+ *
+ * Traverse all child nodes.
+ * Extract the child regulator device node corresponding to the supply name.
+ * returns the device node corresponding to the regulator if found, else
+ * returns NULL.
+ */
+static struct device_node *of_get_child_regulator(struct device_node *parent,
+ const char *prop_name)
+{
+ struct device_node *regnode = NULL;
+ struct device_node *child = NULL;
+
+ for_each_child_of_node(parent, child) {
+ regnode = of_parse_phandle(child, prop_name, 0);
+
+ if (!regnode) {
+ regnode = of_get_child_regulator(child, prop_name);
+ if (regnode)
+ return regnode;
+ } else {
+ return regnode;
+ }
+ }
+ return NULL;
+}
+
/**
* of_get_regulator - get a regulator device node based on supply name
* @dev: Device pointer for the consumer (of regulator) device