OpenSBI Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Anup Patel <apatel@ventanamicro.com>
To: opensbi@lists.infradead.org
Subject: [PATCH 02/16] lib: utils/mailbox: Add generic mailbox library
Date: Tue,  6 Aug 2024 13:03:24 +0530	[thread overview]
Message-ID: <20240806073338.1856901-3-apatel@ventanamicro.com> (raw)
In-Reply-To: <20240806073338.1856901-1-apatel@ventanamicro.com>

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 <apatel@ventanamicro.com>
---
 include/sbi_utils/mailbox/mailbox.h | 170 ++++++++++++++++++++++++++++
 lib/utils/Kconfig                   |   2 +
 lib/utils/mailbox/Kconfig           |   9 ++
 lib/utils/mailbox/mailbox.c         | 116 +++++++++++++++++++
 lib/utils/mailbox/objects.mk        |  10 ++
 5 files changed, 307 insertions(+)
 create mode 100644 include/sbi_utils/mailbox/mailbox.h
 create mode 100644 lib/utils/mailbox/Kconfig
 create mode 100644 lib/utils/mailbox/mailbox.c
 create mode 100644 lib/utils/mailbox/objects.mk

diff --git a/include/sbi_utils/mailbox/mailbox.h b/include/sbi_utils/mailbox/mailbox.h
new file mode 100644
index 00000000..7206ce81
--- /dev/null
+++ b/include/sbi_utils/mailbox/mailbox.h
@@ -0,0 +1,170 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ *   Anup Patel <apatel@ventanamicro.com>
+ */
+
+#ifndef __MAILBOX_H__
+#define __MAILBOX_H__
+
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_list.h>
+#include <sbi/riscv_atomic.h>
+
+/** Representation of a mailbox channel */
+struct mbox_chan {
+	/** List head */
+	struct sbi_dlist node;
+	/** Pointer to the mailbox controller */
+	struct mbox_controller *mbox;
+	/**
+	 * Arguments (or parameters) to identify a mailbox channel
+	 * within a mailbox controller.
+	 */
+#define MBOX_CHAN_MAX_ARGS	2
+	u32 chan_args[MBOX_CHAN_MAX_ARGS];
+};
+
+#define to_mbox_chan(__node)	\
+	container_of((__node), struct mbox_chan, node)
+
+/**
+ * Representation of a mailbox data transfer
+ *
+ * NOTE: If both "tx" and "rx" are non-NULL then Tx is done before Rx.
+ */
+struct mbox_xfer {
+#define MBOX_XFER_SEQ			(1UL << 0)
+	/** Transfer flags */
+	unsigned long flags;
+	/** Transfer arguments (or parameters) */
+	void *args;
+	/**
+	 * Sequence number
+	 *
+	 * If MBOX_XFER_SEQ is not set in flags then mbox_chan_xfer()
+	 * will generate a unique sequence number and update this field
+	 * else mbox_chan_xfer() will blindly use the sequence number
+	 * specified by this field.
+	 */
+	long seq;
+	/** Send data pointer */
+	void *tx;
+	/** Send data length (valid only if tx != NULL) */
+	unsigned long tx_len;
+	/**
+	 * Send timeout milliseconds (valid only if tx != NULL)
+	 *
+	 * If this field is non-zero along with tx != NULL then the
+	 * mailbox controller driver will wait specified milliseconds
+	 * for send data transfer to complete else the mailbox controller
+	 * driver will not wait.
+	 */
+	unsigned long tx_timeout;
+	/** Receive data pointer */
+	void *rx;
+	/** Receive data length (valid only if rx != NULL) */
+	unsigned long rx_len;
+	/**
+	 * Receive timeout milliseconds (valid only if rx != NULL)
+	 *
+	 * If this field is non-zero along with rx != NULL then the
+	 * mailbox controller driver will wait specified milliseconds
+	 * for receive data transfer to complete else the mailbox
+	 * controller driver will not wait.
+	 */
+	unsigned long rx_timeout;
+};
+
+#define mbox_xfer_init_tx(__p, __a, __t, __t_len, __t_tim)		\
+do {									\
+	(__p)->flags = 0;						\
+	(__p)->args = (__a);						\
+	(__p)->tx = (__t);						\
+	(__p)->tx_len = (__t_len);					\
+	(__p)->tx_timeout = (__t_tim);					\
+	(__p)->rx = NULL;						\
+	(__p)->rx_len = 0;						\
+	(__p)->rx_timeout = 0;						\
+} while (0)
+
+#define mbox_xfer_init_rx(__p, __a, __r, __r_len, __r_tim)		\
+do {									\
+	(__p)->flags = 0;						\
+	(__p)->args = (__a);						\
+	(__p)->tx = NULL;						\
+	(__p)->tx_len = 0;						\
+	(__p)->tx_timeout = 0;						\
+	(__p)->rx = (__r);						\
+	(__p)->rx_len = (__r_len);					\
+	(__p)->rx_timeout = (__r_tim);					\
+} while (0)
+
+#define mbox_xfer_init_txrx(__p, __a, __t, __t_len, __t_tim, __r, __r_len, __r_tim)\
+do {									\
+	(__p)->flags = 0;						\
+	(__p)->args = (__a);						\
+	(__p)->tx = (__t);						\
+	(__p)->tx_len = (__t_len);					\
+	(__p)->tx_timeout = (__t_tim);					\
+	(__p)->rx = (__r);						\
+	(__p)->rx_len = (__r_len);					\
+	(__p)->rx_timeout = (__r_tim);					\
+} while (0)
+
+#define mbox_xfer_set_sequence(__p, __seq)				\
+do {									\
+	(__p)->flags |= MBOX_XFER_SEQ;					\
+	(__p)->seq = (__seq);						\
+} while (0)
+
+/** Representation of a mailbox controller */
+struct mbox_controller {
+	/** List head */
+	struct sbi_dlist node;
+	/** Next sequence atomic counter */
+	atomic_t xfer_next_seq;
+	/* List of mailbox channels */
+	struct sbi_dlist chan_list;
+	/** Unique ID of the mailbox controller assigned by the driver */
+	unsigned int id;
+	/** Maximum length of transfer supported by the mailbox controller */
+	unsigned int max_xfer_len;
+	/** Pointer to mailbox driver owning this mailbox controller */
+	void *driver;
+	/** Request a mailbox channel from the mailbox controller */
+	struct mbox_chan *(*request_chan)(struct mbox_controller *mbox,
+					  u32 *chan_args);
+	/** Free a mailbox channel from the mailbox controller */
+	void *(*free_chan)(struct mbox_controller *mbox,
+			   struct mbox_chan *chan);
+	/** Transfer data over mailbox channel */
+	int (*xfer)(struct mbox_chan *chan, struct mbox_xfer *xfer);
+};
+
+#define to_mbox_controller(__node)	\
+	container_of((__node), struct mbox_controller, node)
+
+/** Find a registered mailbox controller */
+struct mbox_controller *mbox_controller_find(unsigned int id);
+
+/** Register mailbox controller */
+int mbox_controller_add(struct mbox_controller *mbox);
+
+/** Un-register mailbox controller */
+void mbox_controller_remove(struct mbox_controller *mbox);
+
+/** Request a mailbox channel */
+struct mbox_chan *mbox_controller_request_chan(struct mbox_controller *mbox,
+					       u32 *chan_args);
+
+/** Free a mailbox channel */
+void mbox_controller_free_chan(struct mbox_chan *chan);
+
+/** Data transfer over mailbox channel */
+int mbox_chan_xfer(struct mbox_chan *chan, struct mbox_xfer *xfer);
+
+#endif
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..86f2feac
--- /dev/null
+++ b/lib/utils/mailbox/mailbox.c
@@ -0,0 +1,116 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ *   Anup Patel <apatel@ventanamicro.com>
+ */
+
+#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);
+}
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 <apatel@ventanamicro.com>
+#
+
+libsbiutils-objs-$(CONFIG_MAILBOX) += mailbox/mailbox.o
-- 
2.34.1



  parent reply	other threads:[~2024-08-06  7:33 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-06  7:33 [PATCH 00/16] RPMI and SBI MPXY support for OpenSBI Anup Patel
2024-08-06  7:33 ` [PATCH 01/16] lib: Increase ROOT_REGION_MAX to accomodate more memregions Anup Patel
2024-08-06  7:33 ` Anup Patel [this message]
2024-08-06  7:33 ` [PATCH 03/16] lib: utils/mailbox: Add simple FDT based mailbox framework Anup Patel
2024-08-06  7:33 ` [PATCH 04/16] lib/utils: Add RPMI messaging protocol and shared memory transport support Anup Patel
2024-08-16  1:01   ` Bo Gan
2024-08-17  6:54     ` Anup Patel
2024-08-26 22:34   ` Bo Gan
2024-08-06  7:33 ` [PATCH 05/16] lib/utils: reset: Add RPMI System Reset driver Anup Patel
2024-08-06  7:33 ` [PATCH 06/16] lib: utils: Add simple FDT based system suspend driver framework Anup Patel
2024-08-06  7:33 ` [PATCH 07/16] lib: utils/suspend: Add RPMI system suspend driver Anup Patel
2024-08-06  7:33 ` [PATCH 08/16] lib: utils: Add simple FDT based HSM driver framework Anup Patel
2024-08-06  7:33 ` [PATCH 09/16] lib: sbi: Add optional resume address to hart suspend Anup Patel
2024-08-06  7:33 ` [PATCH 10/16] lib: utils/hsm: Add RPMI HSM driver Anup Patel
2024-08-06  7:33 ` [PATCH 11/16] lib: utils: Add simple FDT based CPPC driver framework Anup Patel
2024-08-06  7:33 ` [PATCH 12/16] lib: utils/cppc: Add RPMI CPPC driver Anup Patel
2024-08-06  7:33 ` [PATCH 13/16] lib: sbi: Add SBI Message Proxy (MPXY) framework Anup Patel
2024-10-11 11:26   ` Yu-Chien Peter Lin
2024-10-11 11:51     ` Rahul Pathak
2024-08-06  7:33 ` [PATCH 14/16] lib: sbi: Implement SBI MPXY extension Anup Patel
2024-08-07  9:24   ` Yu-Chien Peter Lin
2024-08-07  9:34     ` Rahul Pathak
2024-08-07  9:46       ` Yu-Chien Peter Lin
2024-08-06  7:33 ` [PATCH 15/16] lib: utils: Add simple FDT based MPXY driver framework Anup Patel
2024-08-06  7:33 ` [PATCH 16/16] lib: utils/mpxy: Add RPMI client driver for MPXY Anup Patel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240806073338.1856901-3-apatel@ventanamicro.com \
    --to=apatel@ventanamicro.com \
    --cc=opensbi@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox