mutex_unlock(®ulator_nesting_mutex);
 }
 
+/**
+ * regulator_lock_two - lock two regulators
+ * @rdev1:             first regulator
+ * @rdev2:             second regulator
+ * @ww_ctx:            w/w mutex acquire context
+ *
+ * Locks both rdevs using the regulator_ww_class.
+ */
+static void regulator_lock_two(struct regulator_dev *rdev1,
+                              struct regulator_dev *rdev2,
+                              struct ww_acquire_ctx *ww_ctx)
+{
+       struct regulator_dev *tmp;
+       int ret;
+
+       ww_acquire_init(ww_ctx, ®ulator_ww_class);
+
+       /* Try to just grab both of them */
+       ret = regulator_lock_nested(rdev1, ww_ctx);
+       WARN_ON(ret);
+       ret = regulator_lock_nested(rdev2, ww_ctx);
+       if (ret != -EDEADLOCK) {
+               WARN_ON(ret);
+               goto exit;
+       }
+
+       while (true) {
+               /*
+                * Start of loop: rdev1 was locked and rdev2 was contended.
+                * Need to unlock rdev1, slowly lock rdev2, then try rdev1
+                * again.
+                */
+               regulator_unlock(rdev1);
+
+               ww_mutex_lock_slow(&rdev2->mutex, ww_ctx);
+               rdev2->ref_cnt++;
+               rdev2->mutex_owner = current;
+               ret = regulator_lock_nested(rdev1, ww_ctx);
+
+               if (ret == -EDEADLOCK) {
+                       /* More contention; swap which needs to be slow */
+                       tmp = rdev1;
+                       rdev1 = rdev2;
+                       rdev2 = tmp;
+               } else {
+                       WARN_ON(ret);
+                       break;
+               }
+       }
+
+exit:
+       ww_acquire_done(ww_ctx);
+}
+
+/**
+ * regulator_unlock_two - unlock two regulators
+ * @rdev1:             first regulator
+ * @rdev2:             second regulator
+ * @ww_ctx:            w/w mutex acquire context
+ *
+ * The inverse of regulator_lock_two().
+ */
+
+static void regulator_unlock_two(struct regulator_dev *rdev1,
+                                struct regulator_dev *rdev2,
+                                struct ww_acquire_ctx *ww_ctx)
+{
+       regulator_unlock(rdev2);
+       regulator_unlock(rdev1);
+       ww_acquire_fini(ww_ctx);
+}
+
 static bool regulator_supply_is_couple(struct regulator_dev *rdev)
 {
        struct regulator_dev *c_rdev;
 
 /**
  * set_supply - set regulator supply regulator
- * @rdev: regulator name
- * @supply_rdev: supply regulator name
+ * @rdev: regulator (locked)
+ * @supply_rdev: supply regulator (locked))
  *
  * Called by platform initialisation code to set the supply regulator for this
  * regulator. This ensures that a regulators supply will also be enabled by the
        struct regulator *regulator;
        int err = 0;
 
+       lockdep_assert_held_once(&rdev->mutex.base);
+
        if (dev) {
                char buf[REG_STR_SIZE];
                int size;
        regulator->rdev = rdev;
        regulator->supply_name = supply_name;
 
-       regulator_lock(rdev);
        list_add(®ulator->list, &rdev->consumer_list);
-       regulator_unlock(rdev);
 
        if (dev) {
                regulator->dev = dev;
 {
        struct regulator_dev *r;
        struct device *dev = rdev->dev.parent;
+       struct ww_acquire_ctx ww_ctx;
        int ret = 0;
 
        /* No supply to resolve? */
         * between rdev->supply null check and setting rdev->supply in
         * set_supply() from concurrent tasks.
         */
-       regulator_lock(rdev);
+       regulator_lock_two(rdev, r, &ww_ctx);
 
        /* Supply just resolved by a concurrent task? */
        if (rdev->supply) {
-               regulator_unlock(rdev);
+               regulator_unlock_two(rdev, r, &ww_ctx);
                put_device(&r->dev);
                goto out;
        }
 
        ret = set_supply(rdev, r);
        if (ret < 0) {
-               regulator_unlock(rdev);
+               regulator_unlock_two(rdev, r, &ww_ctx);
                put_device(&r->dev);
                goto out;
        }
 
-       regulator_unlock(rdev);
+       regulator_unlock_two(rdev, r, &ww_ctx);
 
        /*
         * In set_machine_constraints() we may have turned this regulator on
                return regulator;
        }
 
+       regulator_lock(rdev);
        regulator = create_regulator(rdev, dev, id);
+       regulator_unlock(rdev);
        if (regulator == NULL) {
                regulator = ERR_PTR(-ENOMEM);
                module_put(rdev->owner);