diff options
| author | Anup Patel <[email protected]> | 2024-08-06 09:38:02 +0530 |
|---|---|---|
| committer | Anup Patel <[email protected]> | 2024-12-06 09:26:13 +0530 |
| commit | ad846a7cb8cdb98870e42539087f2bc4e786fd22 (patch) | |
| tree | e1de100cb93da6d708f107b169cdc9abd0ff7daa /lib/utils | |
| parent | b49d67b70f09149016afbfa07c8f65df1626a157 (diff) | |
lib: utils/mailbox: Add generic mailbox library
Add generic mailbox library which is independent of hardware description
format. The OpenSBI platform support or mailbox drivers can register
mailbox controller instances which can be discovered and used by different
mailbox client drivers. Each mailbox controller instance has a unique ID
which can be used by mailbox client drivers for find the mailbox controller
instance. The mailbox client drivers will typically request a mailbox channel
from the mailbox controller and use it to do data transfer with the remote
end of mailbox channel.
Signed-off-by: Anup Patel <[email protected]>
Diffstat (limited to 'lib/utils')
| -rw-r--r-- | lib/utils/Kconfig | 2 | ||||
| -rw-r--r-- | lib/utils/mailbox/Kconfig | 9 | ||||
| -rw-r--r-- | lib/utils/mailbox/mailbox.c | 138 | ||||
| -rw-r--r-- | lib/utils/mailbox/objects.mk | 10 |
4 files changed, 159 insertions, 0 deletions
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig index de8b4eb9..6aa7843c 100644 --- a/lib/utils/Kconfig +++ b/lib/utils/Kconfig @@ -14,6 +14,8 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/irqchip/Kconfig" source "$(OPENSBI_SRC_DIR)/lib/utils/libfdt/Kconfig" +source "$(OPENSBI_SRC_DIR)/lib/utils/mailbox/Kconfig" + source "$(OPENSBI_SRC_DIR)/lib/utils/regmap/Kconfig" source "$(OPENSBI_SRC_DIR)/lib/utils/reset/Kconfig" diff --git a/lib/utils/mailbox/Kconfig b/lib/utils/mailbox/Kconfig new file mode 100644 index 00000000..f91a9bb9 --- /dev/null +++ b/lib/utils/mailbox/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "Mailbox Support" + +config MAILBOX + bool "Mailbox support" + default n + +endmenu diff --git a/lib/utils/mailbox/mailbox.c b/lib/utils/mailbox/mailbox.c new file mode 100644 index 00000000..2ea7a005 --- /dev/null +++ b/lib/utils/mailbox/mailbox.c @@ -0,0 +1,138 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel <[email protected]> + */ + +#include <sbi/sbi_error.h> +#include <sbi/sbi_string.h> +#include <sbi_utils/mailbox/mailbox.h> + +static SBI_LIST_HEAD(mbox_list); + +struct mbox_controller *mbox_controller_find(unsigned int id) +{ + struct sbi_dlist *pos; + + sbi_list_for_each(pos, &mbox_list) { + struct mbox_controller *mbox = to_mbox_controller(pos); + + if (mbox->id == id) + return mbox; + } + + return NULL; +} + +int mbox_controller_add(struct mbox_controller *mbox) +{ + if (!mbox || !mbox->max_xfer_len) + return SBI_EINVAL; + if (mbox_controller_find(mbox->id)) + return SBI_EALREADY; + + SBI_INIT_LIST_HEAD(&mbox->node); + ATOMIC_INIT(&mbox->xfer_next_seq, 0); + SBI_INIT_LIST_HEAD(&mbox->chan_list); + sbi_list_add(&mbox->node, &mbox_list); + + return 0; +} + +void mbox_controller_remove(struct mbox_controller *mbox) +{ + struct mbox_chan *chan; + + if (!mbox) + return; + + while (!sbi_list_empty(&mbox->chan_list)) { + chan = sbi_list_first_entry(&mbox->chan_list, + struct mbox_chan, node); + if (mbox->free_chan) + mbox->free_chan(mbox, chan); + sbi_list_del(&chan->node); + } + + sbi_list_del(&mbox->node); +} + +struct mbox_chan *mbox_controller_request_chan(struct mbox_controller *mbox, + u32 *chan_args) +{ + struct mbox_chan *ret; + struct sbi_dlist *pos; + + if (!chan_args || !mbox || !mbox->request_chan) + return NULL; + + sbi_list_for_each(pos, &mbox->chan_list) { + ret = to_mbox_chan(pos); + if (!sbi_memcmp(ret->chan_args, chan_args, + sizeof(ret->chan_args))) + return ret; + } + + ret = mbox->request_chan(mbox, chan_args); + if (!ret) + return NULL; + + SBI_INIT_LIST_HEAD(&ret->node); + ret->mbox = mbox; + sbi_memcpy(ret->chan_args, chan_args, sizeof(ret->chan_args)); + sbi_list_add(&ret->node, &mbox->chan_list); + return ret; +} + +void mbox_controller_free_chan(struct mbox_chan *chan) +{ + if (!chan || !chan->mbox) + return; + + if (chan->mbox->free_chan) + chan->mbox->free_chan(chan->mbox, chan); + sbi_list_del(&chan->node); +} + +int mbox_chan_xfer(struct mbox_chan *chan, struct mbox_xfer *xfer) +{ + if (!xfer || !chan || !chan->mbox || !chan->mbox->xfer) + return SBI_EINVAL; + + if (xfer->tx && (xfer->tx_len > chan->mbox->max_xfer_len)) + return SBI_EINVAL; + + if (xfer->rx && (xfer->rx_len > chan->mbox->max_xfer_len)) + return SBI_EINVAL; + + if (!(xfer->flags & MBOX_XFER_SEQ)) + mbox_xfer_set_sequence(xfer, + atomic_add_return(&chan->mbox->xfer_next_seq, 1)); + + return chan->mbox->xfer(chan, xfer); +} + +int mbox_chan_get_attribute(struct mbox_chan *chan, int attr_id, void *out_value) +{ + if (!chan || !chan->mbox || !out_value) + return SBI_EINVAL; + + if (!chan->mbox->get_attribute) + return SBI_ENOTSUPP; + + return chan->mbox->get_attribute(chan, attr_id, out_value); +} + +int mbox_chan_set_attribute(struct mbox_chan *chan, int attr_id, void *new_value) +{ + if (!chan || !chan->mbox || !new_value) + return SBI_EINVAL; + + if (!chan->mbox->set_attribute) + return SBI_ENOTSUPP; + + return chan->mbox->set_attribute(chan, attr_id, new_value); +} diff --git a/lib/utils/mailbox/objects.mk b/lib/utils/mailbox/objects.mk new file mode 100644 index 00000000..79b27e4c --- /dev/null +++ b/lib/utils/mailbox/objects.mk @@ -0,0 +1,10 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2024 Ventana Micro Systems Inc. +# +# Authors: +# Anup Patel <[email protected]> +# + +libsbiutils-objs-$(CONFIG_MAILBOX) += mailbox/mailbox.o |
