regulator/rpmsg: pending in wait ept ready for regulator client

Signed-off-by: zhuyanlin <zhuyanlin1@xiaomi.com>
This commit is contained in:
zhuyanlin 2021-12-23 17:16:26 +08:00 committed by Xiang Xiao
parent cbd82f1c1b
commit a22dae19c1
3 changed files with 128 additions and 47 deletions

View File

@ -353,6 +353,7 @@ config REGULATOR
config REGULATOR_RPMSG config REGULATOR_RPMSG
bool "Regulator rpmsg driver support" bool "Regulator rpmsg driver support"
depends on OPENAMP
default n default n
---help--- ---help---
The rpmsg regulator driver implements the common regulator APIs, inside which The rpmsg regulator driver implements the common regulator APIs, inside which

View File

@ -86,11 +86,17 @@ struct regulator_rpmsg_cookie_s
sem_t sem; sem_t sem;
}; };
struct regulator_rpmsg_priv_s struct regulator_rpmsg_client_s
{ {
struct rpmsg_endpoint ept; struct rpmsg_endpoint ept;
FAR const char *cpuname; FAR const char *cpuname;
struct list_node node; struct list_node node;
sem_t sem;
};
struct regulator_rpmsg_server_s
{
struct rpmsg_endpoint ept;
struct list_node regulator_list; struct list_node regulator_list;
}; };
@ -124,6 +130,17 @@ static int regulator_rpmsg_isenabled_handler(FAR struct rpmsg_endpoint *ept,
FAR void *data, size_t len, FAR void *data, size_t len,
uint32_t src, FAR void *priv_); uint32_t src, FAR void *priv_);
static void regulator_rpmsg_client_created(struct rpmsg_device *rdev,
FAR void *priv_);
static void regulator_rpmsg_client_destroy(struct rpmsg_device *rdev,
FAR void *priv_);
static void regulator_rpmsg_server_unbind(FAR struct rpmsg_endpoint *ept);
static void regulator_rpmsg_server_bind(FAR struct rpmsg_device *rdev,
FAR void *priv_,
FAR const char *name,
uint32_t dest);
static int regulator_rpmsg_set_voltage(FAR struct regulator_dev_s *rdev, static int regulator_rpmsg_set_voltage(FAR struct regulator_dev_s *rdev,
int min_uv, int max_uv, int min_uv, int max_uv,
FAR unsigned *selector); FAR unsigned *selector);
@ -162,26 +179,46 @@ static const struct regulator_ops_s g_regulator_rpmsg_ops =
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
static struct regulator_rpmsg_priv_s * static struct regulator_rpmsg_client_s *
regulator_rpmsg_get_priv(FAR const char *name) regulator_rpmsg_get_priv(FAR const char *name)
{ {
FAR struct regulator_rpmsg_priv_s *priv; FAR struct regulator_rpmsg_client_s *priv;
FAR const char *slash = strchr(name, '/');
if (!slash)
{
return NULL;
}
nxmutex_lock(&g_regulator_rpmsg_lock); nxmutex_lock(&g_regulator_rpmsg_lock);
list_for_every_entry(&g_regulator_rpmsg_priv, priv, list_for_every_entry(&g_regulator_rpmsg_priv, priv,
struct regulator_rpmsg_priv_s, node) struct regulator_rpmsg_client_s, node)
{ {
size_t len = strlen(priv->cpuname); if (!strncmp(priv->cpuname, name, slash - name))
if (!strncmp(priv->cpuname, name, len) &&
(name[len] == '/' || name[len] == 0))
{ {
goto out; /* Find the target, exit */ goto out; /* Find the target, exit */
} }
} }
priv = NULL; priv = kmm_zalloc(sizeof(struct regulator_rpmsg_client_s));
if (!priv)
{
goto out;
}
priv->cpuname = strndup(name, slash - name);
list_add_head(&g_regulator_rpmsg_priv, &priv->node);
nxmutex_unlock(&g_regulator_rpmsg_lock);
rpmsg_register_callback(priv,
regulator_rpmsg_client_created,
regulator_rpmsg_client_destroy,
NULL);
return priv;
out: out:
nxmutex_unlock(&g_regulator_rpmsg_lock); nxmutex_unlock(&g_regulator_rpmsg_lock);
@ -190,14 +227,27 @@ out:
static struct rpmsg_endpoint *regulator_rpmsg_get_ept(FAR const char **name) static struct rpmsg_endpoint *regulator_rpmsg_get_ept(FAR const char **name)
{ {
FAR struct regulator_rpmsg_priv_s *priv; FAR struct regulator_rpmsg_client_s *priv;
int ret = 0;
priv = regulator_rpmsg_get_priv(*name); priv = regulator_rpmsg_get_priv(*name);
if (priv == NULL)
if (!priv)
{ {
return NULL; return NULL;
} }
if (!is_rpmsg_ept_ready(&priv->ept))
{
ret = nxsem_wait_uninterruptible(&priv->sem);
if (ret < 0)
{
return NULL;
}
nxsem_post(&priv->sem);
}
*name += strlen(priv->cpuname) + 1; *name += strlen(priv->cpuname) + 1;
return &priv->ept; return &priv->ept;
@ -206,7 +256,7 @@ static struct rpmsg_endpoint *regulator_rpmsg_get_ept(FAR const char **name)
static FAR struct regulator_s * static FAR struct regulator_s *
regulator_rpmsg_get_reg(FAR struct rpmsg_endpoint *ept, FAR const char *name) regulator_rpmsg_get_reg(FAR struct rpmsg_endpoint *ept, FAR const char *name)
{ {
FAR struct regulator_rpmsg_priv_s *priv = ept->priv; FAR struct regulator_rpmsg_server_s *priv = ept->priv;
FAR struct list_node *regulator_list = &priv->regulator_list; FAR struct list_node *regulator_list = &priv->regulator_list;
FAR struct regulator_rpmsg_s *reg; FAR struct regulator_rpmsg_s *reg;
@ -237,48 +287,47 @@ regulator_rpmsg_get_reg(FAR struct rpmsg_endpoint *ept, FAR const char *name)
return reg->regulator; return reg->regulator;
} }
static void regulator_rpmsg_device_created(struct rpmsg_device *rdev, static void regulator_rpmsg_client_created(struct rpmsg_device *rdev,
FAR void *priv_) FAR void *priv_)
{ {
FAR struct regulator_rpmsg_priv_s *priv; FAR struct regulator_rpmsg_client_s *priv = priv_;
int ret;
priv = kmm_zalloc(sizeof(struct regulator_rpmsg_priv_s));
if (!priv) if (!priv)
{ {
return; return;
} }
priv->ept.priv = priv; if (!strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)))
priv->cpuname = rpmsg_get_cpuname(rdev);
list_initialize(&priv->regulator_list);
nxmutex_lock(&g_regulator_rpmsg_lock);
list_add_head(&g_regulator_rpmsg_priv, &priv->node);
nxmutex_unlock(&g_regulator_rpmsg_lock);
ret = rpmsg_create_ept(&priv->ept, rdev, REGULATOR_RPMSG_EPT_NAME,
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
regulator_rpmsg_ept_cb, NULL);
if (ret)
{ {
free(priv); priv->ept.priv = priv;
rpmsg_create_ept(&priv->ept, rdev, REGULATOR_RPMSG_EPT_NAME,
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
regulator_rpmsg_ept_cb, NULL);
nxsem_post(&priv->sem);
} }
} }
static void regulator_rpmsg_device_destroy(struct rpmsg_device *rdev, static void regulator_rpmsg_client_destroy(struct rpmsg_device *rdev,
FAR void *priv_) FAR void *priv_)
{ {
FAR struct regulator_rpmsg_priv_s *priv; FAR struct regulator_rpmsg_client_s *priv = priv_;
FAR struct regulator_rpmsg_s *reg;
priv = regulator_rpmsg_get_priv(rpmsg_get_cpuname(rdev));
if (!priv) if (!priv)
{ {
return; return;
} }
nxsem_wait(&priv->sem);
rpmsg_destroy_ept(&priv->ept);
}
static void regulator_rpmsg_server_unbind(FAR struct rpmsg_endpoint *ept)
{
FAR struct regulator_rpmsg_server_s *priv = ept->priv;
FAR struct regulator_rpmsg_s *reg;
list_for_every_entry(&priv->regulator_list, reg, list_for_every_entry(&priv->regulator_list, reg,
struct regulator_rpmsg_s, node) struct regulator_rpmsg_s, node)
{ {
@ -292,14 +341,37 @@ static void regulator_rpmsg_device_destroy(struct rpmsg_device *rdev,
kmm_free(reg); kmm_free(reg);
} }
nxmutex_lock(&g_regulator_rpmsg_lock); rpmsg_destroy_ept(ept);
list_delete(&priv->node);
nxmutex_unlock(&g_regulator_rpmsg_lock);
rpmsg_destroy_ept(&priv->ept);
kmm_free(priv); kmm_free(priv);
} }
static void regulator_rpmsg_server_bind(FAR struct rpmsg_device *rdev,
FAR void *priv_,
FAR const char *name,
uint32_t dest)
{
FAR struct regulator_rpmsg_server_s *priv;
if (!strcmp(name, REGULATOR_RPMSG_EPT_NAME))
{
priv = kmm_zalloc(sizeof(struct regulator_rpmsg_server_s));
if (!priv)
{
return;
}
priv->ept.priv = priv;
list_initialize(&priv->regulator_list);
rpmsg_create_ept(&priv->ept, rdev, name,
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
regulator_rpmsg_ept_cb,
regulator_rpmsg_server_unbind);
}
}
static int regulator_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, static int regulator_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept,
FAR void *data, size_t len, FAR void *data, size_t len,
uint32_t src, FAR void *priv_) uint32_t src, FAR void *priv_)
@ -584,6 +656,7 @@ static int regulator_rpmsg_is_enabled(FAR struct regulator_dev_s *rdev)
FAR struct regulator_dev_s *regulator_rpmsg_get(FAR const char *name) FAR struct regulator_dev_s *regulator_rpmsg_get(FAR const char *name)
{ {
FAR struct regulator_desc_s *desc; FAR struct regulator_desc_s *desc;
FAR struct regulator_dev_s *dev;
desc = kmm_zalloc(sizeof(struct regulator_desc_s)); desc = kmm_zalloc(sizeof(struct regulator_desc_s));
if (!desc) if (!desc)
@ -593,11 +666,17 @@ FAR struct regulator_dev_s *regulator_rpmsg_get(FAR const char *name)
desc->name = name; desc->name = name;
return regulator_register(desc, &g_regulator_rpmsg_ops, NULL); dev = regulator_register(desc, &g_regulator_rpmsg_ops, NULL);
if (!dev)
{
kmm_free(desc);
}
return dev;
} }
/**************************************************************************** /****************************************************************************
* Name: regulator_rpmsg_init * Name: regulator_rpmsg_server_init
* *
* Description: * Description:
* *
@ -610,10 +689,10 @@ FAR struct regulator_dev_s *regulator_rpmsg_get(FAR const char *name)
* *
****************************************************************************/ ****************************************************************************/
int regulator_rpmsg_init(void) int regulator_rpmsg_server_init(void)
{ {
return rpmsg_register_callback(NULL, return rpmsg_register_callback(NULL,
regulator_rpmsg_device_created, NULL,
regulator_rpmsg_device_destroy, NULL,
NULL); regulator_rpmsg_server_bind);
} }

View File

@ -197,19 +197,20 @@ int regulator_gpio_init(FAR struct ioexpander_dev_s *iodev,
FAR struct regulator_dev_s *regulator_rpmsg_get(FAR const char *name); FAR struct regulator_dev_s *regulator_rpmsg_get(FAR const char *name);
/**************************************************************************** /****************************************************************************
* Name: regulator_rpmsg_init * Name: regulator_rpmsg_server_init
* *
* Description: * Description:
* *
* Establish rpmsg channel for the operations of the remote regulator
*
* Input Parameters: * Input Parameters:
* *
* Returned Value: * Returned Value:
*
* Zero (OK) on success; a negated errno on failure * Zero (OK) on success; a negated errno on failure
* *
****************************************************************************/ ****************************************************************************/
int regulator_rpmsg_init(void); int regulator_rpmsg_server_init(void);
#endif #endif