You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/08/10 15:17:57 UTC

[nuttx] branch master updated (5890fde1ed -> af60bf8213)

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

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


    from 5890fde1ed drivers/input: Implement the debounce in button_upper.c
     new 67aa12e762 regulator:support always on
     new 935359fa3f regulator: support link to supply
     new 1456919e58 regulator:support lp mode and auto pm register
     new af60bf8213 regulator:optimize the lock to support call the interface in idle task by pm

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 drivers/power/supply/regulator.c | 288 ++++++++++++++++++++++++++++++++++-----
 include/nuttx/power/consumer.h   |   2 +
 include/nuttx/power/regulator.h  |  86 ++++++++----
 3 files changed, 315 insertions(+), 61 deletions(-)


[nuttx] 01/04: regulator:support always on

Posted by xi...@apache.org.
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 67aa12e762cb1709da830df08b6fd0bc04d59f60
Author: dulibo1 <du...@xiaomi.com>
AuthorDate: Thu Jul 13 20:47:13 2023 +0800

    regulator:support always on
    
    when add always on desc,the regulator is always enabled
    
    Signed-off-by: dulibo1 <du...@xiaomi.com>
---
 drivers/power/supply/regulator.c | 13 ++++++++++---
 include/nuttx/power/regulator.h  |  1 +
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/power/supply/regulator.c b/drivers/power/supply/regulator.c
index 04c2ad3589..91fee66a6e 100644
--- a/drivers/power/supply/regulator.c
+++ b/drivers/power/supply/regulator.c
@@ -521,6 +521,11 @@ int regulator_is_enabled(FAR struct regulator_s *regulator)
 
   rdev = regulator->rdev;
 
+  if (rdev->desc->always_on)
+    {
+      return 1;
+    }
+
   nxmutex_lock(&rdev->regulator_lock);
   ret = _regulator_is_enabled(rdev);
   nxmutex_unlock(&rdev->regulator_lock);
@@ -634,7 +639,7 @@ int regulator_disable(FAR struct regulator_s *regulator)
       goto err;
     }
 
-  if (rdev->use_count == 1)
+  if (rdev->use_count == 1 && !rdev->desc->always_on)
     {
       ret = _regulator_do_disable(rdev);
       if (ret < 0)
@@ -813,11 +818,13 @@ regulator_register(FAR const struct regulator_desc_s *regulator_desc,
   list_initialize(&rdev->consumer_list);
   list_initialize(&rdev->list);
 
-  if (rdev->desc->boot_on && !_regulator_is_enabled(rdev))
+  if ((rdev->desc->boot_on || rdev->desc->always_on)
+      && !_regulator_is_enabled(rdev))
     {
       _regulator_do_enable(rdev);
     }
-  else if (!rdev->desc->boot_on && _regulator_is_enabled(rdev))
+  else if (!rdev->desc->boot_on && !rdev->desc->always_on
+           && _regulator_is_enabled(rdev))
     {
       _regulator_do_disable(rdev);
     }
diff --git a/include/nuttx/power/regulator.h b/include/nuttx/power/regulator.h
index 7a63583859..c973fa2a54 100644
--- a/include/nuttx/power/regulator.h
+++ b/include/nuttx/power/regulator.h
@@ -97,6 +97,7 @@ struct regulator_desc_s
   unsigned int boot_on;           /* true if this regulator is to be enabled
                                    * at power up/reset
                                    */
+  unsigned int always_on;
 };
 
 struct regulator_dev_s


[nuttx] 02/04: regulator: support link to supply

Posted by xi...@apache.org.
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 <du...@xiaomi.com>
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 <du...@xiaomi.com>
---
 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);


[nuttx] 04/04: regulator:optimize the lock to support call the interface in idle task by pm

Posted by xi...@apache.org.
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 af60bf82138c87623af58739204adeb2edeca8b1
Author: dulibo1 <du...@xiaomi.com>
AuthorDate: Wed Aug 2 16:53:05 2023 +0800

    regulator:optimize the lock to support call the interface in idle task by pm
    
    support call api in idle task
    
    Signed-off-by: dulibo1 <du...@xiaomi.com>
---
 drivers/power/supply/regulator.c | 87 ++++++++++++++++++++++++++--------------
 1 file changed, 58 insertions(+), 29 deletions(-)

diff --git a/drivers/power/supply/regulator.c b/drivers/power/supply/regulator.c
index a529e17f19..15c59aa905 100644
--- a/drivers/power/supply/regulator.c
+++ b/drivers/power/supply/regulator.c
@@ -54,6 +54,8 @@ static int _regulator_set_voltage_unlocked(FAR struct regulator_s *regulator,
                                            int min_uv, int max_uv);
 static int _regulator_do_enable_pulldown(FAR struct regulator_dev_s *rdev);
 static int _regulator_do_disable_pulldown(FAR struct regulator_dev_s *rdev);
+static irqstate_t regulator_lock(FAR mutex_t *lock);
+static void regulator_unlock(FAR mutex_t *lock, irqstate_t flags);
 
 /****************************************************************************
  * Private Data
@@ -200,10 +202,11 @@ static int regulator_check_consumers(FAR struct regulator_dev_s *rdev,
 
 static FAR struct regulator_dev_s *regulator_dev_lookup(const char *supply)
 {
+  irqstate_t flags;
   FAR struct regulator_dev_s *rdev;
   FAR struct regulator_dev_s *rdev_found = NULL;
 
-  nxmutex_lock(&g_reg_lock);
+  flags = regulator_lock(&g_reg_lock);
   list_for_every_entry(&g_reg_list, rdev, struct regulator_dev_s, list)
     {
       if (rdev->desc->name && strcmp(rdev->desc->name, supply) == 0)
@@ -213,7 +216,7 @@ static FAR struct regulator_dev_s *regulator_dev_lookup(const char *supply)
         }
     }
 
-  nxmutex_unlock(&g_reg_lock);
+  regulator_unlock(&g_reg_lock, flags);
 
 #if defined(CONFIG_REGULATOR_RPMSG)
   if (rdev_found == NULL && strchr(supply, '/'))
@@ -514,6 +517,27 @@ static void regulator_pm_notify(struct pm_callback_s *cb, int domain,
 }
 
 #endif
+
+static irqstate_t regulator_lock(FAR mutex_t *lock)
+{
+  if (!up_interrupt_context() && !sched_idletask())
+    {
+      nxmutex_lock(lock);
+    }
+
+  return enter_critical_section();
+}
+
+static void regulator_unlock(FAR mutex_t *lock, irqstate_t flags)
+{
+  leave_critical_section(flags);
+
+  if (!up_interrupt_context() && !sched_idletask())
+    {
+      nxmutex_unlock(lock);
+    }
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -534,6 +558,7 @@ static void regulator_pm_notify(struct pm_callback_s *cb, int domain,
 
 FAR struct regulator_s *regulator_get(FAR const char *id)
 {
+  irqstate_t flags;
   FAR struct regulator_dev_s *rdev;
   FAR struct regulator_s *regulator = NULL;
 
@@ -560,10 +585,10 @@ FAR struct regulator_s *regulator_get(FAR const char *id)
   regulator->rdev = rdev;
   list_initialize(&regulator->list);
 
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   rdev->open_count++;
   list_add_tail(&rdev->consumer_list, &regulator->list);
-  nxmutex_unlock(&rdev->regulator_lock);
+  regulator_unlock(&rdev->regulator_lock, flags);
 
   return regulator;
 }
@@ -584,6 +609,7 @@ FAR struct regulator_s *regulator_get(FAR const char *id)
 void regulator_put(FAR struct regulator_s *regulator)
 {
   FAR struct regulator_dev_s *rdev;
+  irqstate_t flags;
 
   if (regulator == NULL)
     {
@@ -591,15 +617,10 @@ void regulator_put(FAR struct regulator_s *regulator)
     }
 
   rdev = regulator->rdev;
-
-  nxmutex_lock(&g_reg_lock);
-
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   list_delete(&regulator->list);
   rdev->open_count--;
-  nxmutex_unlock(&rdev->regulator_lock);
-
-  nxmutex_unlock(&g_reg_lock);
+  regulator_unlock(&rdev->regulator_lock, flags);
 
   kmm_free(regulator);
 }
@@ -621,6 +642,7 @@ void regulator_put(FAR struct regulator_s *regulator)
 int regulator_is_enabled(FAR struct regulator_s *regulator)
 {
   FAR struct regulator_dev_s *rdev;
+  irqstate_t flags;
   int ret = 0;
 
   if (regulator == NULL)
@@ -636,10 +658,9 @@ int regulator_is_enabled(FAR struct regulator_s *regulator)
       return 1;
     }
 
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   ret = _regulator_is_enabled(rdev);
-  nxmutex_unlock(&rdev->regulator_lock);
-
+  regulator_unlock(&rdev->regulator_lock, flags);
   return ret;
 }
 
@@ -660,6 +681,7 @@ int regulator_is_enabled(FAR struct regulator_s *regulator)
 int regulator_enable(FAR struct regulator_s *regulator)
 {
   FAR struct regulator_dev_s *rdev;
+  irqstate_t flags;
   int ret = 0;
 
   if (regulator == NULL)
@@ -670,7 +692,7 @@ int regulator_enable(FAR struct regulator_s *regulator)
 
   rdev = regulator->rdev;
 
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   if (rdev->use_count == 0 && !rdev->desc->always_on)
     {
       ret = _regulator_do_enable(rdev);
@@ -683,7 +705,7 @@ int regulator_enable(FAR struct regulator_s *regulator)
   rdev->use_count++;
 
 err:
-  nxmutex_unlock(&rdev->regulator_lock);
+  regulator_unlock(&rdev->regulator_lock, flags);
   return ret;
 }
 
@@ -732,6 +754,7 @@ int regulator_enable_delay(FAR struct regulator_s *regulator, int ms)
 int regulator_disable(FAR struct regulator_s *regulator)
 {
   FAR struct regulator_dev_s *rdev;
+  irqstate_t flags;
   int ret = 0;
 
   if (regulator == NULL)
@@ -742,7 +765,7 @@ int regulator_disable(FAR struct regulator_s *regulator)
 
   rdev = regulator->rdev;
 
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   if (rdev->use_count <= 0)
     {
       ret = -EIO;
@@ -761,7 +784,7 @@ int regulator_disable(FAR struct regulator_s *regulator)
   rdev->use_count--;
 
 err:
-  nxmutex_unlock(&rdev->regulator_lock);
+  regulator_unlock(&rdev->regulator_lock, flags);
   return ret;
 }
 
@@ -811,6 +834,7 @@ int regulator_set_voltage(FAR struct regulator_s *regulator,
                           int min_uv, int max_uv)
 {
   FAR struct regulator_dev_s *rdev;
+  irqstate_t flags;
   int ret = 0;
 
   if (regulator == NULL)
@@ -821,9 +845,9 @@ int regulator_set_voltage(FAR struct regulator_s *regulator,
 
   rdev = regulator->rdev;
 
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   ret = _regulator_set_voltage_unlocked(regulator, min_uv, max_uv);
-  nxmutex_unlock(&rdev->regulator_lock);
+  regulator_unlock(&rdev->regulator_lock, flags);
 
   return ret;
 }
@@ -845,6 +869,7 @@ int regulator_set_voltage(FAR struct regulator_s *regulator,
 int regulator_get_voltage(FAR struct regulator_s *regulator)
 {
   FAR struct regulator_dev_s *rdev;
+  irqstate_t flags;
   int ret = 0;
 
   if (regulator == NULL)
@@ -855,9 +880,9 @@ int regulator_get_voltage(FAR struct regulator_s *regulator)
 
   rdev = regulator->rdev;
 
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   ret = _regulator_get_voltage(rdev);
-  nxmutex_unlock(&rdev->regulator_lock);
+  regulator_unlock(&rdev->regulator_lock, flags);
 
   return ret;
 }
@@ -883,9 +908,10 @@ int regulator_set_mode(FAR struct regulator_s *regulator,
 {
   FAR struct regulator_dev_s *rdev = regulator->rdev;
   unsigned int curr_mode;
+  irqstate_t flags;
   int ret;
 
-  nxmutex_lock(&rdev->regulator_lock);
+  flags = regulator_lock(&rdev->regulator_lock);
   if (!rdev->ops->set_mode || mode == REGULATOR_MODE_INVALID)
     {
       ret = -EINVAL;
@@ -904,7 +930,7 @@ int regulator_set_mode(FAR struct regulator_s *regulator,
 
   ret = rdev->ops->set_mode(rdev, mode);
 out:
-  nxmutex_unlock(&rdev->regulator_lock);
+  regulator_unlock(&rdev->regulator_lock, flags);
   return ret;
 }
 
@@ -923,6 +949,7 @@ regulator_register(FAR const struct regulator_desc_s *regulator_desc,
                    FAR void *priv)
 {
   FAR struct regulator_dev_s *rdev;
+  irqstate_t flags;
   int ret = 0;
 
   if (regulator_desc == NULL)
@@ -1015,9 +1042,9 @@ regulator_register(FAR const struct regulator_desc_s *regulator_desc,
     }
 #endif
 
-  nxmutex_lock(&g_reg_lock);
+  flags = regulator_lock(&g_reg_lock);
   list_add_tail(&g_reg_list, &rdev->list);
-  nxmutex_unlock(&g_reg_lock);
+  regulator_unlock(&g_reg_lock, flags);
 
   return rdev;
 }
@@ -1033,21 +1060,23 @@ regulator_register(FAR const struct regulator_desc_s *regulator_desc,
 
 void regulator_unregister(FAR struct regulator_dev_s *rdev)
 {
+  irqstate_t flags;
+
   if (rdev == NULL)
     {
       return;
     }
 
-  nxmutex_lock(&g_reg_lock);
+  flags = regulator_lock(&g_reg_lock);
   if (rdev->open_count)
     {
       pwrerr("unregister, open %" PRIu32 "\n", rdev->open_count);
-      nxmutex_unlock(&g_reg_lock);
+      regulator_unlock(&g_reg_lock, flags);
       return;
     }
 
   list_delete(&rdev->list);
-  nxmutex_unlock(&g_reg_lock);
+  regulator_unlock(&g_reg_lock, flags);
 #ifdef CONFIG_PM
   if (rdev->desc->auto_lp)
     {


[nuttx] 03/04: regulator:support lp mode and auto pm register

Posted by xi...@apache.org.
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 1456919e584e363d0fd483420d9668bc1de6922c
Author: dulibo1 <du...@xiaomi.com>
AuthorDate: Fri Jul 21 17:14:34 2023 +0800

    regulator:support lp mode and auto pm register
    
    1.add new intf regulator_set_mode to manual set rehulator lower power mode;
    2.when add auto lp desc,the regulator lp mode is controlled by  pm framework;
    
    Signed-off-by: dulibo1 <du...@xiaomi.com>
---
 drivers/power/supply/regulator.c | 121 +++++++++++++++++++++++++++++++++++++++
 include/nuttx/power/consumer.h   |   2 +
 include/nuttx/power/regulator.h  |  34 ++++++++++-
 3 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/drivers/power/supply/regulator.c b/drivers/power/supply/regulator.c
index 35f9b74ec2..a529e17f19 100644
--- a/drivers/power/supply/regulator.c
+++ b/drivers/power/supply/regulator.c
@@ -455,6 +455,65 @@ out2:
   return ret;
 }
 
+#ifdef CONFIG_PM
+static void regulator_pm_notify(struct pm_callback_s *cb, int domain,
+                                enum pm_state_e pmstate)
+{
+  FAR struct regulator_dev_s *rdev = NULL;
+  FAR const struct regulator_state_s *state = NULL;
+
+  rdev = container_of(cb, struct regulator_dev_s, pm_cb);
+
+  if (rdev->desc->domain != domain)
+    {
+      return;
+    }
+
+  switch (pmstate)
+    {
+      case PM_RESTORE:
+        if (rdev->ops->resume)
+          {
+            rdev->ops->resume(rdev);
+          }
+        break;
+
+      case PM_NORMAL:
+        state = &rdev->desc->states[PM_NORMAL];
+        break;
+
+      case PM_IDLE:
+        state = &rdev->desc->states[PM_IDLE];
+        break;
+
+      case PM_STANDBY:
+        state = &rdev->desc->states[PM_STANDBY];
+        break;
+
+      case PM_SLEEP:
+        state = &rdev->desc->states[PM_SLEEP];
+        break;
+
+      default:
+        break;
+    }
+
+  if (state)
+    {
+      if (rdev->ops->set_suspend_voltage && state->uv > 0)
+        {
+          rdev->ops->set_suspend_voltage(rdev, state->uv);
+        }
+
+      if (rdev->ops->set_suspend_mode &&
+          state->mode != REGULATOR_MODE_INVALID)
+        {
+          rdev->ops->set_suspend_mode(rdev, state->mode);
+        }
+    }
+}
+
+#endif
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -803,6 +862,52 @@ int regulator_get_voltage(FAR struct regulator_s *regulator)
   return ret;
 }
 
+/****************************************************************************
+ * Name: regulator_set_mode
+ *
+ * Description:
+ * Set regulator operating mode to increase regulator efficiency or improve
+ * regulation performance.
+ *
+ * Input parameters:
+ *   regulator - The regulator consumer representative
+ *   mode - operating mode - one of the REGULATOR_MODE constants
+ *
+ * Returned value:
+ *   Positive on success or a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int regulator_set_mode(FAR struct regulator_s *regulator,
+                       enum regulator_mode_e mode)
+{
+  FAR struct regulator_dev_s *rdev = regulator->rdev;
+  unsigned int curr_mode;
+  int ret;
+
+  nxmutex_lock(&rdev->regulator_lock);
+  if (!rdev->ops->set_mode || mode == REGULATOR_MODE_INVALID)
+    {
+      ret = -EINVAL;
+      goto out;
+    }
+
+  if (rdev->ops->get_mode)
+    {
+      curr_mode = rdev->ops->get_mode(rdev);
+      if (curr_mode == mode)
+        {
+          ret = 0;
+          goto out;
+        }
+    }
+
+  ret = rdev->ops->set_mode(rdev, mode);
+out:
+  nxmutex_unlock(&rdev->regulator_lock);
+  return ret;
+}
+
 /****************************************************************************
  * Name: regulator_register
  *
@@ -901,6 +1006,15 @@ regulator_register(FAR const struct regulator_desc_s *regulator_desc,
       _regulator_do_disable_pulldown(rdev);
     }
 
+#ifdef CONFIG_PM
+  if (rdev->desc->auto_lp)
+    {
+      rdev->pm_cb.prepare = NULL;
+      rdev->pm_cb.notify = regulator_pm_notify;
+      pm_register(&rdev->pm_cb);
+    }
+#endif
+
   nxmutex_lock(&g_reg_lock);
   list_add_tail(&g_reg_list, &rdev->list);
   nxmutex_unlock(&g_reg_lock);
@@ -934,6 +1048,13 @@ void regulator_unregister(FAR struct regulator_dev_s *rdev)
 
   list_delete(&rdev->list);
   nxmutex_unlock(&g_reg_lock);
+#ifdef CONFIG_PM
+  if (rdev->desc->auto_lp)
+    {
+      pm_unregister(&rdev->pm_cb);
+    }
+#endif
+
   if (rdev->supply)
     {
       regulator_put(rdev->supply);
diff --git a/include/nuttx/power/consumer.h b/include/nuttx/power/consumer.h
index 5c3c0d24a1..edfc750771 100644
--- a/include/nuttx/power/consumer.h
+++ b/include/nuttx/power/consumer.h
@@ -67,6 +67,8 @@ int regulator_disable_deferred(FAR struct regulator_s *regulator, int ms);
 int regulator_set_voltage(FAR struct regulator_s *regulator, int min_uv,
                           int max_uv);
 int regulator_get_voltage(FAR struct regulator_s *regulator);
+int regulator_set_mode(FAR struct regulator_s *regulator,
+                       enum regulator_mode_e mode);
 
 #undef EXTERN
 #ifdef __cplusplus
diff --git a/include/nuttx/power/regulator.h b/include/nuttx/power/regulator.h
index 06f3a5c697..11a35f74d5 100644
--- a/include/nuttx/power/regulator.h
+++ b/include/nuttx/power/regulator.h
@@ -33,6 +33,7 @@
 #include <nuttx/list.h>
 #include <nuttx/mutex.h>
 #include <nuttx/wqueue.h>
+#include <nuttx/power/pm.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -42,6 +43,15 @@
  * Public Types
  ****************************************************************************/
 
+enum regulator_mode_e
+{
+  REGULATOR_MODE_INVALID = 0,
+  REGULATOR_MODE_FAST,
+  REGULATOR_MODE_NORMAL,
+  REGULATOR_MODE_IDLE,
+  REGULATOR_MODE_STANDBY,
+};
+
 struct regulator_dev_s;
 
 struct regulator_s
@@ -50,7 +60,13 @@ struct regulator_s
   int min_uv;
   int max_uv;
   struct list_node list;
-  struct regulator_dev_s *rdev;
+  FAR struct regulator_dev_s *rdev;
+};
+
+struct regulator_state_s
+{
+  int uv;
+  enum regulator_mode_e mode;
 };
 
 struct regulator_ops_s
@@ -68,6 +84,13 @@ struct regulator_ops_s
   CODE int (*disable)(FAR struct regulator_dev_s *rdev);
   CODE int (*enable_pulldown)(FAR struct regulator_dev_s *rdev);
   CODE int (*disable_pulldown)(FAR struct regulator_dev_s *rdev);
+  CODE int (*set_mode)(FAR struct regulator_dev_s *rdev,
+                       enum regulator_mode_e mode);
+  CODE enum regulator_mode_e (*get_mode)(FAR struct regulator_dev_s *rdev);
+  CODE int (*set_suspend_mode)(FAR struct regulator_dev_s *rdev,
+                               enum regulator_mode_e mode);
+  CODE int (*set_suspend_voltage)(FAR struct regulator_dev_s *, int uv);
+  CODE int (*resume)(FAR struct regulator_dev_s *rdev);
 };
 
 /* This structure describes the regulators capabilities */
@@ -100,6 +123,11 @@ struct regulator_desc_s
                                      */
   unsigned int   always_on;
   FAR const char *supply_name;
+#ifdef CONFIG_PM
+  unsigned int auto_lp;
+  unsigned int domain;
+  struct regulator_state_s states[PM_COUNT];
+#endif
 };
 
 struct regulator_dev_s
@@ -112,7 +140,9 @@ struct regulator_dev_s
   struct list_node list;
   struct list_node consumer_list;
   FAR struct regulator_s *supply;
-
+#ifdef CONFIG_PM
+  struct pm_callback_s pm_cb;
+#endif
   FAR void *priv;
 };