This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 935359fa3fd654f0af5d20d172cc08cb899d0db9
Author: dulibo1 <[email protected]>
AuthorDate: Tue Jul 18 15:53:40 2023 +0800

    regulator: support link to supply
    
    when add supply desc,the regulator is linked to the parent regulator
    1.if enable the regualtor, the parent regulator is enabled
    2.if disable all child regulator, the parent regualtor is disabled
    
    Signed-off-by: dulibo1 <[email protected]>
---
 drivers/power/supply/regulator.c | 75 ++++++++++++++++++++++++++++++++++++----
 include/nuttx/power/regulator.h  | 53 ++++++++++++++--------------
 2 files changed, 96 insertions(+), 32 deletions(-)

diff --git a/drivers/power/supply/regulator.c b/drivers/power/supply/regulator.c
index 91fee66a6e..35f9b74ec2 100644
--- a/drivers/power/supply/regulator.c
+++ b/drivers/power/supply/regulator.c
@@ -32,7 +32,7 @@
 
 #include <nuttx/arch.h>
 #include <nuttx/kmalloc.h>
-#include <nuttx/power/regulator.h>
+#include <nuttx/power/consumer.h>
 #include <nuttx/signal.h>
 
 /****************************************************************************
@@ -78,15 +78,43 @@ static int _regulator_is_enabled(FAR struct regulator_dev_s 
*rdev)
 
 static int _regulator_do_enable(FAR struct regulator_dev_s *rdev)
 {
+  FAR struct regulator_s *supply = NULL;
   int ret = 0;
 
+  if (rdev->desc->supply_name && rdev->supply == NULL)
+    {
+      supply = regulator_get(rdev->desc->supply_name);
+      if (supply == NULL)
+        {
+          pwrerr("get supply %s failed \n", rdev->desc->supply_name);
+          return -ENODEV;
+        }
+
+      rdev->supply = supply;
+    }
+
+  if (rdev->supply)
+    {
+      ret = regulator_enable(rdev->supply);
+      if (ret < 0)
+        {
+          pwrerr("failed to enable supply %d\n", ret);
+          goto err;
+        }
+    }
+
   if (rdev->ops->enable)
     {
       ret = rdev->ops->enable(rdev);
       if (ret < 0)
         {
           pwrerr("failed to enable %d\n", ret);
-          return ret;
+          if (rdev->supply)
+            {
+              regulator_disable(rdev->supply);
+            }
+
+          goto err;
         }
     }
 
@@ -96,6 +124,15 @@ static int _regulator_do_enable(FAR struct regulator_dev_s 
*rdev)
     }
 
   return ret;
+
+err:
+  if (supply)
+    {
+      regulator_put(supply);
+      rdev->supply = NULL;
+    }
+
+  return ret;
 }
 
 static int _regulator_do_disable(FAR struct regulator_dev_s *rdev)
@@ -108,6 +145,20 @@ static int _regulator_do_disable(FAR struct 
regulator_dev_s *rdev)
       if (ret < 0)
         {
           pwrerr("failed to disable %d\n", ret);
+          return ret;
+        }
+    }
+
+  if (rdev->supply)
+    {
+      ret = regulator_disable(rdev->supply);
+      if (ret < 0)
+        {
+          pwrerr("failed to disable supply %d\n", ret);
+          if (rdev->ops->enable)
+            {
+              rdev->ops->enable(rdev);
+            }
         }
     }
 
@@ -165,7 +216,7 @@ static FAR struct regulator_dev_s 
*regulator_dev_lookup(const char *supply)
   nxmutex_unlock(&g_reg_lock);
 
 #if defined(CONFIG_REGULATOR_RPMSG)
-  if (rdev_found == NULL)
+  if (rdev_found == NULL && strchr(supply, '/'))
     {
       rdev_found = regulator_rpmsg_get(supply);
     }
@@ -561,7 +612,7 @@ int regulator_enable(FAR struct regulator_s *regulator)
   rdev = regulator->rdev;
 
   nxmutex_lock(&rdev->regulator_lock);
-  if (rdev->use_count == 0)
+  if (rdev->use_count == 0 && !rdev->desc->always_on)
     {
       ret = _regulator_do_enable(rdev);
       if (ret < 0)
@@ -767,6 +818,7 @@ regulator_register(FAR const struct regulator_desc_s 
*regulator_desc,
                    FAR void *priv)
 {
   FAR struct regulator_dev_s *rdev;
+  int ret = 0;
 
   if (regulator_desc == NULL)
     {
@@ -818,10 +870,15 @@ regulator_register(FAR const struct regulator_desc_s 
*regulator_desc,
   list_initialize(&rdev->consumer_list);
   list_initialize(&rdev->list);
 
-  if ((rdev->desc->boot_on || rdev->desc->always_on)
-      && !_regulator_is_enabled(rdev))
+  if (rdev->desc->boot_on || rdev->desc->always_on)
     {
-      _regulator_do_enable(rdev);
+      ret = _regulator_do_enable(rdev);
+      if (ret < 0)
+        {
+          pwrerr("failed to enable regulator\n");
+          kmm_free(rdev);
+          return NULL;
+        }
     }
   else if (!rdev->desc->boot_on && !rdev->desc->always_on
            && _regulator_is_enabled(rdev))
@@ -877,6 +934,10 @@ void regulator_unregister(FAR struct regulator_dev_s *rdev)
 
   list_delete(&rdev->list);
   nxmutex_unlock(&g_reg_lock);
+  if (rdev->supply)
+    {
+      regulator_put(rdev->supply);
+    }
 
   kmm_free(rdev);
 }
diff --git a/include/nuttx/power/regulator.h b/include/nuttx/power/regulator.h
index c973fa2a54..06f3a5c697 100644
--- a/include/nuttx/power/regulator.h
+++ b/include/nuttx/power/regulator.h
@@ -74,30 +74,32 @@ struct regulator_ops_s
 
 struct regulator_desc_s
 {
-  const char   *name;             /* Regulator output name */
-  unsigned int id;                /* Numerical id for a given regulator of
-                                   * a device
-                                   */
-  unsigned int n_voltages;        /* Number of discrete voltages */
-  unsigned int vsel_reg;          /* Device register for voltage selection */
-  unsigned int vsel_mask;         /* Register mask, for voltage selection */
-  unsigned int enable_reg;        /* Device register for enable/disable */
-  unsigned int enable_mask;       /* Register mask for enable/disable */
-  unsigned int enable_time;       /* Time for initial enable of regulator */
-  unsigned int ramp_delay;        /* Rate of change for setting new voltage */
-  unsigned int uv_step;           /* Voltage per step if linear mapping_uv */
-  unsigned int min_uv;            /* Minimum acceptable voltage */
-  unsigned int max_uv;            /* Maximum acceptable voltage */
-  unsigned int pulldown;          /* Enable pulldown when disabled */
-  unsigned int pulldown_reg;      /* Device register, for pulldown enable */
-  unsigned int pulldown_mask;     /* Register mask, for pulldown enable */
-  unsigned int apply_uv;          /* If true, the voltage specifed (between)   
                               * min_uv and max_uv will be applied during
-                                   * initialisation.
-                                   */
-  unsigned int boot_on;           /* true if this regulator is to be enabled
-                                   * at power up/reset
-                                   */
-  unsigned int always_on;
+  FAR const char *name;             /* Regulator output name */
+  unsigned int   id;                /* Numerical id for a given regulator of
+                                     * a device
+                                     */
+  unsigned int   n_voltages;        /* Number of discrete voltages */
+  unsigned int   vsel_reg;          /* Device register for voltage selection */
+  unsigned int   vsel_mask;         /* Register mask, for voltage selection */
+  unsigned int   enable_reg;        /* Device register for enable/disable */
+  unsigned int   enable_mask;       /* Register mask for enable/disable */
+  unsigned int   enable_time;       /* Time for initial enable of regulator */
+  unsigned int   ramp_delay;        /* Rate of change for setting new voltage 
*/
+  unsigned int   uv_step;           /* Voltage per step if linear mapping_uv */
+  unsigned int   min_uv;            /* Minimum acceptable voltage */
+  unsigned int   max_uv;            /* Maximum acceptable voltage */
+  unsigned int   pulldown;          /* Enable pulldown when disabled */
+  unsigned int   pulldown_reg;      /* Device register, for pulldown enable */
+  unsigned int   pulldown_mask;     /* Register mask, for pulldown enable */
+  unsigned int   apply_uv;          /* If true, the voltage specifed (between)
+                                     * min_uv and max_uv will be applied during
+                                     * initialisation.
+                                     */
+  unsigned int   boot_on;           /* true if this regulator is to be enabled
+                                     * at power up/reset
+                                     */
+  unsigned int   always_on;
+  FAR const char *supply_name;
 };
 
 struct regulator_dev_s
@@ -109,6 +111,7 @@ struct regulator_dev_s
   mutex_t regulator_lock;
   struct list_node list;
   struct list_node consumer_list;
+  FAR struct regulator_s *supply;
 
   FAR void *priv;
 };
@@ -147,7 +150,7 @@ extern "C"
  *
  ****************************************************************************/
 
-struct regulator_dev_s *
+FAR struct regulator_dev_s *
 regulator_register(FAR const struct regulator_desc_s *desc,
                    FAR const struct regulator_ops_s *ops,
                    FAR void *priv);

Reply via email to