From 97d684847b6f1dd654af11f26dd56ea76180b35b Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Wed, 27 Sep 2023 18:43:15 +0800 Subject: [PATCH] drivers/reset: support rpmsg reset Signed-off-by: dongjiuzhu1 --- drivers/drivers_initialize.c | 5 + drivers/reset/Kconfig | 7 + drivers/reset/Make.defs | 6 + drivers/reset/core.c | 35 ++ drivers/reset/reset_rpmsg.c | 798 +++++++++++++++++++++++++ include/nuttx/reset/reset-controller.h | 44 +- 6 files changed, 893 insertions(+), 2 deletions(-) create mode 100644 drivers/reset/reset_rpmsg.c diff --git a/drivers/drivers_initialize.c b/drivers/drivers_initialize.c index b38a5ecf39..0be8a0519e 100644 --- a/drivers/drivers_initialize.c +++ b/drivers/drivers_initialize.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -154,6 +155,10 @@ void drivers_initialize(void) regulator_rpmsg_server_init(); #endif +#if defined(CONFIG_RESET_RPMSG) + reset_rpmsg_server_init(); +#endif + /* Initialize the serial device driver */ #ifdef CONFIG_RPMSG_UART diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 01e1617614..e4f3f11708 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -8,3 +8,10 @@ menuconfig RESET default n ---help--- This selection enables building of the "upper-half" reset driver. + +config RESET_RPMSG + bool "Reset rpmsg driver support" + depends on RESET && RPTUN + default n + ---help--- + This selection enables rpmsg support for reset. diff --git a/drivers/reset/Make.defs b/drivers/reset/Make.defs index 7aeea7704a..93aaa33056 100644 --- a/drivers/reset/Make.defs +++ b/drivers/reset/Make.defs @@ -24,6 +24,12 @@ ifeq ($(CONFIG_RESET),y) CSRCS += core.c +ifeq ($(CONFIG_RESET_RPMSG),y) + +CSRCS += reset_rpmsg.c + +endif + DEPPATH += --dep-path reset VPATH += :reset CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)reset diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 9bbbab46f0..40a80572d4 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -251,6 +251,7 @@ reset_control_get_internal(FAR struct reset_controller_dev *rcdev, unsigned int index, bool shared, bool acquired) { FAR struct reset_control *rstc; + int ret; DEBUGASSERT(nxmutex_is_locked(&g_reset_list_mutex)); @@ -288,6 +289,21 @@ reset_control_get_internal(FAR struct reset_controller_dev *rcdev, return NULL; } +#if defined(CONFIG_RESET_RPMSG) + + /* Only client defines this function */ + + if (rcdev->ops->acquire) + { + ret = rcdev->ops->acquire(rcdev, index, shared, acquired); + if (ret < 0) + { + kmm_free(rstc); + return NULL; + } + } +#endif + rstc->rcdev = rcdev; list_add_after(&rcdev->reset_control_head, &rstc->list); rstc->id = index; @@ -317,6 +333,17 @@ static void reset_control_put_internal(FAR struct reset_control *rstc) { DEBUGASSERT(nxmutex_is_locked(&g_reset_list_mutex)); list_delete(&rstc->list); + +#if defined(CONFIG_RESET_RPMSG) + + /* Only client defines this function */ + + if (rstc->rcdev->ops->release) + { + rstc->rcdev->ops->release(rstc->rcdev, rstc->id); + } +#endif + kmm_free(rstc); } } @@ -378,6 +405,14 @@ reset_controller_get_by_name(FAR const char *name) } nxmutex_unlock(&g_reset_list_mutex); + +#if defined(CONFIG_RESET_RPMSG) + if (strchr(name, '/')) + { + return reset_rpmsg_get(name); + } +#endif + return NULL; } diff --git a/drivers/reset/reset_rpmsg.c b/drivers/reset/reset_rpmsg.c new file mode 100644 index 0000000000..a16e887d44 --- /dev/null +++ b/drivers/reset/reset_rpmsg.c @@ -0,0 +1,798 @@ +/**************************************************************************** + * drivers/reset/reset_rpmsg.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RESET_RPMSG_EPT_NAME "rpmsg-reset" + +#define RESET_RPMSG_ACQUIRE 0 +#define RESET_RPMSG_RELEASE 1 +#define RESET_RPMSG_RESET 2 +#define RESET_RPMSG_ASSERT 3 +#define RESET_RPMSG_DEASSERT 4 +#define RESET_RPMSG_STATUS 5 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct reset_rpmsg_cookie_s +{ + int32_t result; + sem_t sem; +}; + +struct reset_rpmsg_server_s +{ + struct rpmsg_endpoint ept; + struct list_node list; + mutex_t lock; +}; + +struct reset_rpmsg_client_s +{ + struct rpmsg_endpoint ept; + struct list_node node; + sem_t sem; + char cpuname[0]; +}; + +begin_packed_struct struct reset_rpmsg_header_s +{ + uint32_t command : 31; + uint32_t response : 1; + int32_t result; + uint64_t cookie; +} end_packed_struct; + +begin_packed_struct struct rpmsg_reset_msg +{ + struct reset_rpmsg_header_s header; + int id; + bool shared; + bool acquired; + char name[0]; +} end_packed_struct; + +struct reset_rpmsg_s +{ + FAR struct reset_control *rstc; + struct list_node node; + unsigned int count; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int reset_rpmsg_acquire_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static int reset_rpmsg_release_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static int reset_rpmsg_reset_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static int reset_rpmsg_assert_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static int reset_rpmsg_deassert_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static int reset_rpmsg_status_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static int reset_rpmsg_acquire(FAR struct reset_controller_dev *rcdev, + unsigned int id, bool shared, + bool acquired); + +static int reset_rpmsg_release(FAR struct reset_controller_dev *rcdev, + unsigned int id); + +static int reset_rpmsg_reset(FAR struct reset_controller_dev *rcdev, + unsigned int id); + +static int reset_rpmsg_assert(FAR struct reset_controller_dev *rcdev, + unsigned int id); + +static int reset_rpmsg_deassert(FAR struct reset_controller_dev *rcdev, + unsigned int id); + +static int reset_rpmsg_status(FAR struct reset_controller_dev *rcdev, + unsigned int id); + +static int reset_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static mutex_t g_reset_rpmsg_lock = NXMUTEX_INITIALIZER; +static struct list_node g_reset_rpmsg_client = + LIST_INITIAL_VALUE(g_reset_rpmsg_client); + +static const rpmsg_ept_cb g_reset_rpmsg_handler[] = +{ + [RESET_RPMSG_ACQUIRE] = reset_rpmsg_acquire_handler, + [RESET_RPMSG_RELEASE] = reset_rpmsg_release_handler, + [RESET_RPMSG_RESET] = reset_rpmsg_reset_handler, + [RESET_RPMSG_ASSERT] = reset_rpmsg_assert_handler, + [RESET_RPMSG_DEASSERT] = reset_rpmsg_deassert_handler, + [RESET_RPMSG_STATUS] = reset_rpmsg_status_handler, +}; + +static const struct reset_control_ops g_reset_rpmsg_ops = +{ + .acquire = reset_rpmsg_acquire, + .release = reset_rpmsg_release, + .reset = reset_rpmsg_reset, + .assert = reset_rpmsg_assert, + .deassert = reset_rpmsg_deassert, + .status = reset_rpmsg_status, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void reset_rpmsg_client_created(FAR struct rpmsg_device *rdev, + FAR void *priv) +{ + FAR struct reset_rpmsg_client_s *client = priv; + + if (client == NULL) + { + return; + } + + if (strcmp(client->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + rpmsg_create_ept(&client->ept, rdev, RESET_RPMSG_EPT_NAME, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + reset_rpmsg_ept_cb, NULL); + + nxsem_post(&client->sem); + } +} + +static void reset_rpmsg_client_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv) +{ + FAR struct reset_rpmsg_client_s *client = priv; + + if (client == NULL) + { + return; + } + + if (strcmp(client->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + nxsem_wait(&client->sem); + rpmsg_destroy_ept(&client->ept); + } +} + +static FAR struct reset_rpmsg_client_s * +reset_rpmsg_get_client(FAR const char *name) +{ + FAR struct reset_rpmsg_client_s *client; + FAR const char *slash = strchr(name, '/'); + + if (slash == NULL) + { + return NULL; + } + + nxmutex_lock(&g_reset_rpmsg_lock); + + list_for_every_entry(&g_reset_rpmsg_client, client, + struct reset_rpmsg_client_s, node) + { + if (strncmp(client->cpuname, name, slash - name) == 0) + { + goto out; /* Find the target, exit */ + } + } + + client = kmm_zalloc(sizeof(*client) + slash - name + 1); + if (client == NULL) + { + goto out; + } + + memcpy(client->cpuname, name, slash - name); + list_add_head(&g_reset_rpmsg_client, &client->node); + nxmutex_unlock(&g_reset_rpmsg_lock); + + rpmsg_register_callback(client, + reset_rpmsg_client_created, + reset_rpmsg_client_destroy, + NULL, + NULL); + return client; + +out: + nxmutex_unlock(&g_reset_rpmsg_lock); + return client; +} + +static struct rpmsg_endpoint *rpmsg_reset_get_ept(FAR const char **name) +{ + FAR struct reset_rpmsg_client_s *client; + int ret = 0; + + client = reset_rpmsg_get_client(*name); + if (client == NULL) + { + return NULL; + } + + if (!is_rpmsg_ept_ready(&client->ept)) + { + ret = nxsem_wait_uninterruptible(&client->sem); + if (ret < 0) + { + return NULL; + } + + nxsem_post(&client->sem); + } + + *name += strlen(client->cpuname) + 1; + return &client->ept; +} + +static int reset_rpmsg_sendrecv(FAR struct rpmsg_endpoint *ept, + uint32_t command, + FAR struct reset_rpmsg_header_s *msg, + int len) +{ + struct reset_rpmsg_cookie_s cookie = + { + 0 + }; + + int ret; + + nxsem_init(&cookie.sem, 0, 0); + msg->command = command; + msg->response = 0; + msg->result = -ENXIO; + msg->cookie = (uintptr_t)&cookie; + ret = rpmsg_send_nocopy(ept, msg, len); + if (ret >= 0) + { + ret = nxsem_wait_uninterruptible(&cookie.sem); + if (ret >= 0) + { + ret = cookie.result; + } + } + else + { + rpmsg_release_tx_buffer(ept, msg); + } + + nxsem_destroy(&cookie.sem); + return ret; +} + +static int reset_rpmsg_acquire(FAR struct reset_controller_dev *rcdev, + unsigned int id, bool shared, + bool acquired) +{ + FAR struct rpmsg_endpoint *ept; + FAR struct rpmsg_reset_msg *msg; + FAR const char *name = rcdev->name; + uint32_t len; + + ept = rpmsg_reset_get_ept(&name); + if (ept == NULL) + { + return -ENODEV; + } + + len = sizeof(*msg) + strlen(name) + 1; + msg = rpmsg_get_tx_payload_buffer(ept, &len, true); + if (msg == NULL) + { + return -ENOMEM; + } + + /* We have to pass name, id, shared, acquired for the remote + * to create rstc, after that only need to pass name and id. + */ + + strlcpy(msg->name, name, len - sizeof(*msg)); + msg->id = id; + msg->shared = shared; + msg->acquired = acquired; + return reset_rpmsg_sendrecv(ept, RESET_RPMSG_ACQUIRE, + (struct reset_rpmsg_header_s *)msg, + len); +} + +static int reset_rpmsg_release(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + FAR struct rpmsg_endpoint *ept; + FAR struct rpmsg_reset_msg *msg; + FAR const char *name = rcdev->name; + uint32_t len; + + ept = rpmsg_reset_get_ept(&name); + if (ept == NULL) + { + return -ENODEV; + } + + len = sizeof(*msg) + strlen(name) + 1; + msg = rpmsg_get_tx_payload_buffer(ept, &len, true); + if (msg == NULL) + { + return -ENOMEM; + } + + strlcpy(msg->name, name, len - sizeof(*msg)); + msg->id = id; + return reset_rpmsg_sendrecv(ept, RESET_RPMSG_RELEASE, + (struct reset_rpmsg_header_s *)msg, + len); +} + +static int reset_rpmsg_reset(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + FAR struct rpmsg_endpoint *ept; + FAR struct rpmsg_reset_msg *msg; + FAR const char *name = rcdev->name; + uint32_t len; + + ept = rpmsg_reset_get_ept(&name); + if (ept == NULL) + { + return -ENODEV; + } + + len = sizeof(*msg) + strlen(name) + 1; + msg = rpmsg_get_tx_payload_buffer(ept, &len, true); + if (msg == NULL) + { + return -ENOMEM; + } + + strlcpy(msg->name, name, len - sizeof(*msg)); + msg->id = id; + return reset_rpmsg_sendrecv(ept, RESET_RPMSG_RESET, + (struct reset_rpmsg_header_s *)msg, + len); +} + +static int reset_rpmsg_assert(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + FAR struct rpmsg_endpoint *ept; + FAR struct rpmsg_reset_msg *msg; + FAR const char *name = rcdev->name; + uint32_t len; + + ept = rpmsg_reset_get_ept(&name); + if (ept == NULL) + { + return -ENODEV; + } + + len = sizeof(*msg) + strlen(name) + 1; + msg = rpmsg_get_tx_payload_buffer(ept, &len, true); + if (msg == NULL) + { + return -ENOMEM; + } + + strlcpy(msg->name, name, len - sizeof(*msg)); + msg->id = id; + return reset_rpmsg_sendrecv(ept, RESET_RPMSG_ASSERT, + (struct reset_rpmsg_header_s *)msg, + len); +} + +static int reset_rpmsg_deassert(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + FAR struct rpmsg_endpoint *ept; + FAR struct rpmsg_reset_msg *msg; + FAR const char *name = rcdev->name; + uint32_t len; + + ept = rpmsg_reset_get_ept(&name); + if (ept == NULL) + { + return -ENODEV; + } + + len = sizeof(*msg) + strlen(name) + 1; + msg = rpmsg_get_tx_payload_buffer(ept, &len, true); + if (msg == NULL) + { + return -ENOMEM; + } + + strlcpy(msg->name, name, len - sizeof(*msg)); + msg->id = id; + return reset_rpmsg_sendrecv(ept, RESET_RPMSG_DEASSERT, + (struct reset_rpmsg_header_s *)msg, + len); +} + +static int reset_rpmsg_status(FAR struct reset_controller_dev *rcdev, + unsigned int id) +{ + FAR struct rpmsg_endpoint *ept; + FAR struct rpmsg_reset_msg *msg; + FAR const char *name = rcdev->name; + uint32_t len; + + ept = rpmsg_reset_get_ept(&name); + if (ept == NULL) + { + return -ENODEV; + } + + len = sizeof(*msg) + strlen(name) + 1; + msg = rpmsg_get_tx_payload_buffer(ept, &len, true); + if (msg == NULL) + { + return -ENOMEM; + } + + strlcpy(msg->name, name, len - sizeof(*msg)); + msg->id = id; + return reset_rpmsg_sendrecv(ept, RESET_RPMSG_STATUS, + (struct reset_rpmsg_header_s *)msg, + len); +} + +static FAR struct reset_control * +reset_rpmsg_find(FAR struct rpmsg_endpoint *ept, + FAR const char *name, unsigned int id) +{ + FAR struct reset_rpmsg_server_s *server = ept->priv; + FAR struct reset_rpmsg_s *reset; + + nxmutex_lock(&server->lock); + list_for_every_entry(&server->list, reset, + struct reset_rpmsg_s, node) + { + if (strcmp(reset->rstc->rcdev->name, name) == 0) + { + if (reset->rstc->id == id) + { + nxmutex_unlock(&server->lock); + return reset->rstc; + } + } + } + + nxmutex_unlock(&server->lock); + return NULL; +} + +static int reset_rpmsg_acquire_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct reset_rpmsg_server_s *server = ept->priv; + FAR struct rpmsg_reset_msg *msg = data; + FAR struct reset_control *rstc = NULL; + FAR struct reset_rpmsg_s *reset; + + nxmutex_lock(&server->lock); + list_for_every_entry(&server->list, reset, + struct reset_rpmsg_s, node) + { + if (strcmp(reset->rstc->rcdev->name, msg->name) == 0) + { + if (reset->rstc->id == msg->id) + { + reset->count++; + nxmutex_unlock(&server->lock); + rstc = reset->rstc; + goto out; + } + } + } + + reset = kmm_zalloc(sizeof(*reset)); + if (reset == NULL) + { + nxmutex_unlock(&server->lock); + goto out; + } + + reset->rstc = reset_control_get(msg->name, msg->id, + msg->shared, msg->acquired); + if (reset->rstc == NULL) + { + kmm_free(reset); + nxmutex_unlock(&server->lock); + goto out; + } + + reset->count++; + rstc = reset->rstc; + list_add_head(&server->list, &reset->node); + nxmutex_unlock(&server->lock); + +out: + msg->header.result = rstc ? 0 : -ENOENT; + return rpmsg_send(ept, data, len); +} + +static int reset_rpmsg_release_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct reset_rpmsg_server_s *server = ept->priv; + FAR struct rpmsg_reset_msg *msg = data; + FAR struct reset_rpmsg_s *reset; + + nxmutex_lock(&server->lock); + list_for_every_entry(&server->list, reset, + struct reset_rpmsg_s, node) + { + if (strcmp(reset->rstc->rcdev->name, msg->name) == 0) + { + if (reset->rstc->id == msg->id) + { + msg->header.result = 0; + if (--reset->count == 0) + { + reset_control_put(reset->rstc); + list_delete(&reset->node); + kmm_free(reset); + break; + } + } + } + } + + nxmutex_unlock(&server->lock); + return rpmsg_send(ept, data, len); +} + +static int reset_rpmsg_reset_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsg_reset_msg *msg = data; + FAR struct reset_control *rstc = reset_rpmsg_find(ept, msg->name, msg->id); + + msg->header.result = reset_control_reset(rstc); + return rpmsg_send(ept, data, len); +} + +static int reset_rpmsg_assert_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsg_reset_msg *msg = data; + FAR struct reset_control *rstc = reset_rpmsg_find(ept, msg->name, msg->id); + + msg->header.result = reset_control_assert(rstc); + return rpmsg_send(ept, data, len); +} + +static int reset_rpmsg_deassert_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsg_reset_msg *msg = data; + FAR struct reset_control *rstc = reset_rpmsg_find(ept, msg->name, msg->id); + + msg->header.result = reset_control_deassert(rstc); + return rpmsg_send(ept, data, len); +} + +static int reset_rpmsg_status_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsg_reset_msg *msg = data; + FAR struct reset_control *rstc = reset_rpmsg_find(ept, msg->name, msg->id); + + msg->header.result = reset_control_status(rstc); + return rpmsg_send(ept, data, len); +} + +static int reset_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct reset_rpmsg_header_s *header = data; + uint32_t cmd = header->command; + int ret = -EINVAL; + + struct reset_rpmsg_cookie_s *cookie = + (struct reset_rpmsg_cookie_s *)(uintptr_t)header->cookie; + + if (cookie && header->response) + { + cookie->result = header->result; + nxsem_post(&cookie->sem); + ret = 0; + } + else if (cmd < nitems(g_reset_rpmsg_handler) + && g_reset_rpmsg_handler[cmd]) + { + header->response = 1; + ret = g_reset_rpmsg_handler[cmd](ept, data, len, src, priv); + } + + return ret; +} + +static void reset_rpmsg_server_unbind(FAR struct rpmsg_endpoint *ept) +{ + FAR struct reset_rpmsg_server_s *server = ept->priv; + FAR struct reset_rpmsg_s *reset; + FAR struct reset_rpmsg_s *tmp; + + list_for_every_entry_safe(&server->list, reset, tmp, + struct reset_rpmsg_s, node) + { + reset_control_put(reset->rstc); + list_delete(&reset->node); + kmm_free(reset); + } + + rpmsg_destroy_ept(ept); + nxmutex_destroy(&server->lock); + kmm_free(server); +} + +static bool reset_rpmsg_server_match(FAR struct rpmsg_device *rdev, + FAR void *priv, + FAR const char *name, + uint32_t dest) +{ + return strcmp(name, RESET_RPMSG_EPT_NAME) == 0; +} + +static void reset_rpmsg_server_bind(FAR struct rpmsg_device *rdev, + FAR void *priv, + FAR const char *name, + uint32_t dest) +{ + FAR struct reset_rpmsg_server_s *server; + + server = kmm_zalloc(sizeof(struct reset_rpmsg_server_s)); + if (server == NULL) + { + return; + } + + server->ept.priv = server; + list_initialize(&server->list); + nxmutex_init(&server->lock); + + rpmsg_create_ept(&server->ept, rdev, name, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + reset_rpmsg_ept_cb, + reset_rpmsg_server_unbind); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: reset_rpmsg_get + * + * Description: + * + * Input Parameters: + * + * name - the name of the remote reset controller + * + * Returned Value: + * + * Reset controller pointer + * + ****************************************************************************/ + +FAR struct reset_controller_dev *reset_rpmsg_get(FAR const char *name) +{ + FAR struct reset_controller_dev *rcdev; + size_t len = strlen(name) + 1; + int ret; + + rcdev = kmm_zalloc(sizeof(struct reset_controller_dev) + len); + if (rcdev == NULL) + { + return NULL; + } + + rcdev->name = (FAR char *)(rcdev + 1); + memcpy((FAR char *)rcdev->name, name, len); + rcdev->ops = &g_reset_rpmsg_ops; + + ret = reset_controller_register(rcdev); + if (ret < 0) + { + kmm_free(rcdev); + return NULL; + } + + return rcdev; +} + +/**************************************************************************** + * Name: reset_rpmsg_server_init + * + * Description: + * + * Establish rpmsg channel for the operations of the + * remote reset controller + * + * Input Parameters: + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +int reset_rpmsg_server_init(void) +{ + return rpmsg_register_callback(NULL, + NULL, + NULL, + reset_rpmsg_server_match, + reset_rpmsg_server_bind); +} diff --git a/include/nuttx/reset/reset-controller.h b/include/nuttx/reset/reset-controller.h index 604e975753..bd7e021c09 100644 --- a/include/nuttx/reset/reset-controller.h +++ b/include/nuttx/reset/reset-controller.h @@ -25,6 +25,8 @@ * Included Files ****************************************************************************/ +#include + #include #include @@ -44,13 +46,18 @@ struct reset_controller_dev; struct reset_control_ops { - CODE int (*reset)(FAR struct reset_controller_dev *rcdev, unsigned int id); + CODE int (*acquire)(FAR struct reset_controller_dev *rcdev, + unsigned int id, bool shared, bool acquired); + CODE int (*release)(FAR struct reset_controller_dev *rcdev, + unsigned int id); + CODE int (*reset)(FAR struct reset_controller_dev *rcdev, + unsigned int id); CODE int (*assert)(FAR struct reset_controller_dev *rcdev, unsigned int id); CODE int (*deassert)(FAR struct reset_controller_dev *rcdev, unsigned int id); CODE int (*status)(FAR struct reset_controller_dev *rcdev, - unsigned long id); + unsigned int id); }; /* struct reset_controller_dev - reset controller entity that might @@ -73,6 +80,39 @@ struct reset_controller_dev * Public Functions Definitions ****************************************************************************/ +#ifdef CONFIG_RESET_RPMSG + +/**************************************************************************** + * Name: reset_rpmsg_get + * + * Description: + * + * Input Parameters: + * + * name - the name of the remote reset controller + * + * Returned Value: + * + * Reset controller pointer + * + ****************************************************************************/ + +FAR struct reset_controller_dev *reset_rpmsg_get(FAR const char *name); + +/**************************************************************************** + * Name: reset_rpmsg_server_init + * + * Description: + * Server side rpmsg initialization + * + * Returned Value: + * Returns 0 if success. + ****************************************************************************/ + +int reset_rpmsg_server_init(void); + +#endif + /**************************************************************************** * Name: reset_controller_register() *