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 <[email protected]>
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 <[email protected]>
---
 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;
 };
 

Reply via email to