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 <dulibo1@xiaomi.com>
This commit is contained in:
dulibo1
2023-07-18 15:53:40 +08:00
committed by Xiang Xiao
parent 67aa12e762
commit 935359fa3f
2 changed files with 96 additions and 32 deletions
+68 -7
View File
@@ -32,7 +32,7 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/power/regulator.h> #include <nuttx/power/consumer.h>
#include <nuttx/signal.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) static int _regulator_do_enable(FAR struct regulator_dev_s *rdev)
{ {
FAR struct regulator_s *supply = NULL;
int ret = 0; 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) if (rdev->ops->enable)
{ {
ret = rdev->ops->enable(rdev); ret = rdev->ops->enable(rdev);
if (ret < 0) if (ret < 0)
{ {
pwrerr("failed to enable %d\n", ret); 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; return ret;
err:
if (supply)
{
regulator_put(supply);
rdev->supply = NULL;
}
return ret;
} }
static int _regulator_do_disable(FAR struct regulator_dev_s *rdev) 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) if (ret < 0)
{ {
pwrerr("failed to disable %d\n", ret); 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); nxmutex_unlock(&g_reg_lock);
#if defined(CONFIG_REGULATOR_RPMSG) #if defined(CONFIG_REGULATOR_RPMSG)
if (rdev_found == NULL) if (rdev_found == NULL && strchr(supply, '/'))
{ {
rdev_found = regulator_rpmsg_get(supply); rdev_found = regulator_rpmsg_get(supply);
} }
@@ -561,7 +612,7 @@ int regulator_enable(FAR struct regulator_s *regulator)
rdev = regulator->rdev; rdev = regulator->rdev;
nxmutex_lock(&rdev->regulator_lock); nxmutex_lock(&rdev->regulator_lock);
if (rdev->use_count == 0) if (rdev->use_count == 0 && !rdev->desc->always_on)
{ {
ret = _regulator_do_enable(rdev); ret = _regulator_do_enable(rdev);
if (ret < 0) if (ret < 0)
@@ -767,6 +818,7 @@ regulator_register(FAR const struct regulator_desc_s *regulator_desc,
FAR void *priv) FAR void *priv)
{ {
FAR struct regulator_dev_s *rdev; FAR struct regulator_dev_s *rdev;
int ret = 0;
if (regulator_desc == NULL) 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->consumer_list);
list_initialize(&rdev->list); list_initialize(&rdev->list);
if ((rdev->desc->boot_on || rdev->desc->always_on) if (rdev->desc->boot_on || rdev->desc->always_on)
&& !_regulator_is_enabled(rdev))
{ {
_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 else if (!rdev->desc->boot_on && !rdev->desc->always_on
&& _regulator_is_enabled(rdev)) && _regulator_is_enabled(rdev))
@@ -877,6 +934,10 @@ void regulator_unregister(FAR struct regulator_dev_s *rdev)
list_delete(&rdev->list); list_delete(&rdev->list);
nxmutex_unlock(&g_reg_lock); nxmutex_unlock(&g_reg_lock);
if (rdev->supply)
{
regulator_put(rdev->supply);
}
kmm_free(rdev); kmm_free(rdev);
} }
+6 -3
View File
@@ -74,7 +74,7 @@ struct regulator_ops_s
struct regulator_desc_s struct regulator_desc_s
{ {
const char *name; /* Regulator output name */ FAR const char *name; /* Regulator output name */
unsigned int id; /* Numerical id for a given regulator of unsigned int id; /* Numerical id for a given regulator of
* a device * a device
*/ */
@@ -91,13 +91,15 @@ struct regulator_desc_s
unsigned int pulldown; /* Enable pulldown when disabled */ unsigned int pulldown; /* Enable pulldown when disabled */
unsigned int pulldown_reg; /* Device register, for pulldown enable */ unsigned int pulldown_reg; /* Device register, for pulldown enable */
unsigned int pulldown_mask; /* Register mask, 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 unsigned int apply_uv; /* If true, the voltage specifed (between)
* min_uv and max_uv will be applied during
* initialisation. * initialisation.
*/ */
unsigned int boot_on; /* true if this regulator is to be enabled unsigned int boot_on; /* true if this regulator is to be enabled
* at power up/reset * at power up/reset
*/ */
unsigned int always_on; unsigned int always_on;
FAR const char *supply_name;
}; };
struct regulator_dev_s struct regulator_dev_s
@@ -109,6 +111,7 @@ struct regulator_dev_s
mutex_t regulator_lock; mutex_t regulator_lock;
struct list_node list; struct list_node list;
struct list_node consumer_list; struct list_node consumer_list;
FAR struct regulator_s *supply;
FAR void *priv; 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, regulator_register(FAR const struct regulator_desc_s *desc,
FAR const struct regulator_ops_s *ops, FAR const struct regulator_ops_s *ops,
FAR void *priv); FAR void *priv);