From a22dae19c157cda10608e6128d9360d5b495c4e6 Mon Sep 17 00:00:00 2001 From: zhuyanlin Date: Thu, 23 Dec 2021 17:16:26 +0800 Subject: [PATCH] regulator/rpmsg: pending in wait ept ready for regulator client Signed-off-by: zhuyanlin --- drivers/power/Kconfig | 1 + drivers/power/regulator_rpmsg.c | 167 +++++++++++++++++++++++--------- include/nuttx/power/regulator.h | 7 +- 3 files changed, 128 insertions(+), 47 deletions(-) diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index eb1a3d44cdd..4eaec85d8de 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -353,6 +353,7 @@ config REGULATOR config REGULATOR_RPMSG bool "Regulator rpmsg driver support" + depends on OPENAMP default n ---help--- The rpmsg regulator driver implements the common regulator APIs, inside which diff --git a/drivers/power/regulator_rpmsg.c b/drivers/power/regulator_rpmsg.c index b0b2cd85f69..d9b450287dd 100644 --- a/drivers/power/regulator_rpmsg.c +++ b/drivers/power/regulator_rpmsg.c @@ -86,11 +86,17 @@ struct regulator_rpmsg_cookie_s sem_t sem; }; -struct regulator_rpmsg_priv_s +struct regulator_rpmsg_client_s { struct rpmsg_endpoint ept; FAR const char *cpuname; struct list_node node; + sem_t sem; +}; + +struct regulator_rpmsg_server_s +{ + struct rpmsg_endpoint ept; 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, 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, int min_uv, int max_uv, FAR unsigned *selector); @@ -162,26 +179,46 @@ static const struct regulator_ops_s g_regulator_rpmsg_ops = * Private Functions ****************************************************************************/ -static struct regulator_rpmsg_priv_s * +static struct regulator_rpmsg_client_s * 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); 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, len) && - (name[len] == '/' || name[len] == 0)) + if (!strncmp(priv->cpuname, name, slash - name)) { 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: nxmutex_unlock(&g_regulator_rpmsg_lock); @@ -190,14 +227,27 @@ out: 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); - if (priv == NULL) + + if (!priv) { 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; return &priv->ept; @@ -206,7 +256,7 @@ static struct rpmsg_endpoint *regulator_rpmsg_get_ept(FAR const char **name) static FAR struct regulator_s * 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 regulator_rpmsg_s *reg; @@ -237,48 +287,47 @@ regulator_rpmsg_get_reg(FAR struct rpmsg_endpoint *ept, FAR const char *name) 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 struct regulator_rpmsg_priv_s *priv; - int ret; + FAR struct regulator_rpmsg_client_s *priv = priv_; - priv = kmm_zalloc(sizeof(struct regulator_rpmsg_priv_s)); if (!priv) { return; } - priv->ept.priv = priv; - 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) + if (!strcmp(priv->cpuname, rpmsg_get_cpuname(rdev))) { - 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 struct regulator_rpmsg_priv_s *priv; - FAR struct regulator_rpmsg_s *reg; - - priv = regulator_rpmsg_get_priv(rpmsg_get_cpuname(rdev)); + FAR struct regulator_rpmsg_client_s *priv = priv_; if (!priv) { 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, struct regulator_rpmsg_s, node) { @@ -292,14 +341,37 @@ static void regulator_rpmsg_device_destroy(struct rpmsg_device *rdev, kmm_free(reg); } - nxmutex_lock(&g_regulator_rpmsg_lock); - list_delete(&priv->node); - nxmutex_unlock(&g_regulator_rpmsg_lock); + rpmsg_destroy_ept(ept); - rpmsg_destroy_ept(&priv->ept); 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, FAR void *data, size_t len, 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_desc_s *desc; + FAR struct regulator_dev_s *dev; desc = kmm_zalloc(sizeof(struct regulator_desc_s)); if (!desc) @@ -593,11 +666,17 @@ FAR struct regulator_dev_s *regulator_rpmsg_get(FAR const char *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: * @@ -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, - regulator_rpmsg_device_created, - regulator_rpmsg_device_destroy, - NULL); + NULL, + NULL, + regulator_rpmsg_server_bind); } diff --git a/include/nuttx/power/regulator.h b/include/nuttx/power/regulator.h index 9809cd21041..bec5c37fb89 100644 --- a/include/nuttx/power/regulator.h +++ b/include/nuttx/power/regulator.h @@ -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); /**************************************************************************** - * Name: regulator_rpmsg_init + * Name: regulator_rpmsg_server_init * * Description: * + * Establish rpmsg channel for the operations of the remote regulator + * * Input Parameters: * * Returned Value: - * * Zero (OK) on success; a negated errno on failure * ****************************************************************************/ -int regulator_rpmsg_init(void); +int regulator_rpmsg_server_init(void); #endif