regulator: core: disable parent if child enabled during registration
Laxman Dewangan [Tue, 28 May 2013 14:44:57 +0000 (19:44 +0530)]
If regulator's parent is enabled because of regulator is found to
be enabled during registration then disable parent if:
- regulator registration failed or
- when full constraints is enabled and regulator get disabled.

bug 1285809

Change-Id: I7a7c551543a9cbecf83bf10ef783e72aaa8c2173
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Venkat Reddy <vreddytalla@nvidia.com>
Reviewed-on: http://git-master/r/233346
Reviewed-by: Yong Goo Yi <yyi@nvidia.com>
Tested-by: Yong Goo Yi <yyi@nvidia.com>

drivers/regulator/core.c

index 5facefe..57a806a 100644 (file)
@@ -3112,6 +3112,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        struct regulator_dev *rdev;
        int ret, i;
        const char *supply = NULL;
+       bool parent_enable = false;
 
        if (regulator_desc == NULL)
                return ERR_PTR(-EINVAL);
@@ -3215,6 +3216,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
                        ret = regulator_enable(rdev->supply);
                        if (ret < 0)
                                goto scrub;
+                       parent_enable = true;
                }
        }
 
@@ -3242,6 +3244,8 @@ out:
 unset_supplies:
        unset_regulator_supplies(rdev);
 
+       if (rdev->supply && parent_enable)
+               regulator_disable(rdev->supply);
 scrub:
        if (rdev->supply)
                regulator_put(rdev->supply);
@@ -3524,6 +3528,8 @@ static int __init regulator_init_complete(void)
         * default behaviour in the future.
         */
        list_for_each_entry(rdev, &regulator_list, list) {
+               bool parent_disable = false;
+
                ops = rdev->desc->ops;
                c = rdev->constraints;
 
@@ -3552,6 +3558,8 @@ static int __init regulator_init_complete(void)
                        if (ret != 0) {
                                rdev_err(rdev, "couldn't disable: %d\n", ret);
                        }
+                       if (ops->is_enabled)
+                               parent_disable = true;
                } else {
                        /* The intention is that in future we will
                         * assume that full constraints are provided
@@ -3563,6 +3571,12 @@ static int __init regulator_init_complete(void)
 
 unlock:
                mutex_unlock(&rdev->mutex);
+               if (parent_disable && rdev->supply) {
+                       ret = regulator_disable(rdev->supply);
+                       if (ret < 0)
+                               rdev_err(rdev, "couldn't disable parent: %d\n",
+                                       ret);
+               }
        }
 
        mutex_unlock(&regulator_list_mutex);