* [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI
@ 2024-11-29 15:50 Anup Patel
2024-11-29 15:50 ` [PATCH v2 01/17] lib: Increase ROOT_REGION_MAX to accomodate more memregions Anup Patel
` (17 more replies)
0 siblings, 18 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
This series adds RPMI and SBI MPXY support for OpenSBI. The RPMI service
groups supported include system reset, system suspend, HSM, CPPC, and
clock. The RPMI clock serivice group is exposed to supervisor software
as an MPXY channel.
These patches can also be found in the rpmi_mpxy_v2 branch at:
https://github.com/avpatel/opensbi.git
To test these patches, use the dev-upstream branch of the following repos:
* https://github.com/ventanamicro/qemu.git
* https://github.com/ventanamicro/linux.git
To enable QEMU RPMI emulation (using librpmi) for virt machine, use
"virt,rpmi=on" as the QEMU machine name.
Changes since v1:
- Rebased on latest OpenSBI
- Use the recently introduced helpers for generic driver initialization
- Updated RPMI drivers to match the latest RPMI specification
- Don't support fixed number of channels in RPMI shared memory mailbox driver
- Added new patch9 for support RPMI HSM based FDT fixup
- Improved arrangment of barrier in __smq_rx() and __smq_tx()
Anup Patel (8):
lib: utils/mailbox: Add generic mailbox library
lib: utils/mailbox: Add simple FDT based mailbox framework
lib: utils: Add simple FDT based system suspend driver framework
lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
lib: utils: Add simple FDT based HSM driver framework
lib: utils: Add simple FDT based CPPC driver framework
lib: sbi: Implement SBI MPXY extension
lib: utils: Add simple FDT based MPXY driver framework
Rahul Pathak (5):
lib: Increase ROOT_REGION_MAX to accomodate more memregions
lib/utils: Add RPMI messaging protocol and shared memory transport
support
lib/utils: reset: Add RPMI System Reset driver
lib: sbi: Add SBI Message Proxy (MPXY) framework
lib: utils/mpxy: Add RPMI client driver for MPXY
Subrahmanya Lingappa (4):
lib: utils/suspend: Add RPMI system suspend driver
lib: sbi: Add optional resume address to hart suspend
lib: utils/hsm: Add RPMI HSM driver
lib: utils/cppc: Add RPMI CPPC driver
include/sbi/sbi_ecall_interface.h | 12 +
include/sbi/sbi_error.h | 15 +-
include/sbi/sbi_hsm.h | 6 +-
include/sbi/sbi_mpxy.h | 183 +++++
include/sbi/sbi_platform.h | 17 +
include/sbi_utils/cppc/fdt_cppc.h | 26 +
include/sbi_utils/fdt/fdt_fixup.h | 15 +
include/sbi_utils/hsm/fdt_hsm.h | 26 +
include/sbi_utils/mailbox/fdt_mailbox.h | 35 +
include/sbi_utils/mailbox/mailbox.h | 180 +++++
include/sbi_utils/mailbox/rpmi_mailbox.h | 32 +
include/sbi_utils/mailbox/rpmi_msgprot.h | 607 +++++++++++++++
include/sbi_utils/mpxy/fdt_mpxy.h | 26 +
include/sbi_utils/suspend/fdt_suspend.h | 26 +
lib/sbi/Kconfig | 3 +
lib/sbi/objects.mk | 4 +
lib/sbi/sbi_domain.c | 2 +-
lib/sbi/sbi_ecall_mpxy.c | 68 ++
lib/sbi/sbi_hsm.c | 6 +-
lib/sbi/sbi_init.c | 6 +
lib/sbi/sbi_mpxy.c | 698 +++++++++++++++++
lib/utils/Kconfig | 10 +
lib/utils/cppc/Kconfig | 19 +
lib/utils/cppc/fdt_cppc.c | 22 +
lib/utils/cppc/fdt_cppc_drivers.carray | 3 +
lib/utils/cppc/fdt_cppc_rpmi.c | 377 +++++++++
lib/utils/cppc/objects.mk | 14 +
lib/utils/fdt/fdt_fixup.c | 33 +
lib/utils/hsm/Kconfig | 19 +
lib/utils/hsm/fdt_hsm.c | 22 +
lib/utils/hsm/fdt_hsm_drivers.carray | 3 +
lib/utils/hsm/fdt_hsm_rpmi.c | 362 +++++++++
lib/utils/hsm/objects.mk | 14 +
lib/utils/mailbox/Kconfig | 29 +
lib/utils/mailbox/fdt_mailbox.c | 96 +++
lib/utils/mailbox/fdt_mailbox_drivers.carray | 5 +
lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c | 773 +++++++++++++++++++
lib/utils/mailbox/mailbox.c | 138 ++++
lib/utils/mailbox/objects.mk | 18 +
lib/utils/mailbox/rpmi_mailbox.c | 91 +++
lib/utils/mpxy/Kconfig | 19 +
lib/utils/mpxy/fdt_mpxy.c | 22 +
lib/utils/mpxy/fdt_mpxy_drivers.carray | 3 +
lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c | 442 +++++++++++
lib/utils/mpxy/objects.mk | 14 +
lib/utils/reset/Kconfig | 5 +
lib/utils/reset/fdt_reset_rpmi.c | 141 ++++
lib/utils/reset/objects.mk | 3 +
lib/utils/suspend/Kconfig | 19 +
lib/utils/suspend/fdt_suspend.c | 22 +
lib/utils/suspend/fdt_suspend_drivers.carray | 3 +
lib/utils/suspend/fdt_suspend_rpmi.c | 138 ++++
lib/utils/suspend/objects.mk | 14 +
platform/generic/allwinner/sun20i-d1.c | 2 +-
platform/generic/configs/defconfig | 12 +
platform/generic/platform.c | 16 +
56 files changed, 4903 insertions(+), 13 deletions(-)
create mode 100644 include/sbi/sbi_mpxy.h
create mode 100644 include/sbi_utils/cppc/fdt_cppc.h
create mode 100644 include/sbi_utils/hsm/fdt_hsm.h
create mode 100644 include/sbi_utils/mailbox/fdt_mailbox.h
create mode 100644 include/sbi_utils/mailbox/mailbox.h
create mode 100644 include/sbi_utils/mailbox/rpmi_mailbox.h
create mode 100644 include/sbi_utils/mailbox/rpmi_msgprot.h
create mode 100644 include/sbi_utils/mpxy/fdt_mpxy.h
create mode 100644 include/sbi_utils/suspend/fdt_suspend.h
create mode 100644 lib/sbi/sbi_ecall_mpxy.c
create mode 100644 lib/sbi/sbi_mpxy.c
create mode 100644 lib/utils/cppc/Kconfig
create mode 100644 lib/utils/cppc/fdt_cppc.c
create mode 100644 lib/utils/cppc/fdt_cppc_drivers.carray
create mode 100644 lib/utils/cppc/fdt_cppc_rpmi.c
create mode 100644 lib/utils/cppc/objects.mk
create mode 100644 lib/utils/hsm/Kconfig
create mode 100644 lib/utils/hsm/fdt_hsm.c
create mode 100644 lib/utils/hsm/fdt_hsm_drivers.carray
create mode 100644 lib/utils/hsm/fdt_hsm_rpmi.c
create mode 100644 lib/utils/hsm/objects.mk
create mode 100644 lib/utils/mailbox/Kconfig
create mode 100644 lib/utils/mailbox/fdt_mailbox.c
create mode 100644 lib/utils/mailbox/fdt_mailbox_drivers.carray
create mode 100644 lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
create mode 100644 lib/utils/mailbox/mailbox.c
create mode 100644 lib/utils/mailbox/objects.mk
create mode 100644 lib/utils/mailbox/rpmi_mailbox.c
create mode 100644 lib/utils/mpxy/Kconfig
create mode 100644 lib/utils/mpxy/fdt_mpxy.c
create mode 100644 lib/utils/mpxy/fdt_mpxy_drivers.carray
create mode 100644 lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c
create mode 100644 lib/utils/mpxy/objects.mk
create mode 100644 lib/utils/reset/fdt_reset_rpmi.c
create mode 100644 lib/utils/suspend/Kconfig
create mode 100644 lib/utils/suspend/fdt_suspend.c
create mode 100644 lib/utils/suspend/fdt_suspend_drivers.carray
create mode 100644 lib/utils/suspend/fdt_suspend_rpmi.c
create mode 100644 lib/utils/suspend/objects.mk
--
2.43.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 01/17] lib: Increase ROOT_REGION_MAX to accomodate more memregions
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 02/17] lib: utils/mailbox: Add generic mailbox library Anup Patel
` (16 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Rahul Pathak <rpathak@ventanamicro.com>
As more drivers adding memregions into root domain, the current static limit
of ROOT_REGION_MAX is not sufficient. Increase the limit to accomodate more
memregions.
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
lib/sbi/sbi_domain.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/sbi/sbi_domain.c b/lib/sbi/sbi_domain.c
index 7fdcf9d3..1cf7e2d8 100644
--- a/lib/sbi/sbi_domain.c
+++ b/lib/sbi/sbi_domain.c
@@ -24,7 +24,7 @@ SBI_LIST_HEAD(domain_list);
static u32 domain_count = 0;
static bool domain_finalized = false;
-#define ROOT_REGION_MAX 16
+#define ROOT_REGION_MAX 32
static u32 root_memregs_count = 0;
struct sbi_domain root = {
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 02/17] lib: utils/mailbox: Add generic mailbox library
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
2024-11-29 15:50 ` [PATCH v2 01/17] lib: Increase ROOT_REGION_MAX to accomodate more memregions Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 03/17] lib: utils/mailbox: Add simple FDT based mailbox framework Anup Patel
` (15 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
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 | 180 ++++++++++++++++++++++++++++
lib/utils/Kconfig | 2 +
lib/utils/mailbox/Kconfig | 9 ++
lib/utils/mailbox/mailbox.c | 138 +++++++++++++++++++++
lib/utils/mailbox/objects.mk | 10 ++
5 files changed, 339 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..46fd8770
--- /dev/null
+++ b/include/sbi_utils/mailbox/mailbox.h
@@ -0,0 +1,180 @@
+/*
+ * 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);
+ /** Get an attribute of mailbox channel */
+ int (*get_attribute)(struct mbox_chan *chan, int attr_id, void *out_value);
+ /** Set an attribute of mailbox channel */
+ int (*set_attribute)(struct mbox_chan *chan, int attr_id, void *new_value);
+};
+
+#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);
+
+/** Get an attribute of mailbox channel */
+int mbox_chan_get_attribute(struct mbox_chan *chan, int attr_id, void *out_value);
+
+/** Set an attribute of mailbox channel */
+int mbox_chan_set_attribute(struct mbox_chan *chan, int attr_id, void *new_value);
+
+#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..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 <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);
+}
+
+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 <apatel@ventanamicro.com>
+#
+
+libsbiutils-objs-$(CONFIG_MAILBOX) += mailbox/mailbox.o
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 03/17] lib: utils/mailbox: Add simple FDT based mailbox framework
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
2024-11-29 15:50 ` [PATCH v2 01/17] lib: Increase ROOT_REGION_MAX to accomodate more memregions Anup Patel
2024-11-29 15:50 ` [PATCH v2 02/17] lib: utils/mailbox: Add generic mailbox library Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 04/17] lib/utils: Add RPMI messaging protocol and shared memory transport support Anup Patel
` (14 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
Add a simple FDT based mailbox framework which is built on top of the generic
mailbox library. The phandle of FDT mailbox DT node is treated as the unique
mailbox controller ID which is required by the generic mailbox library. The
FDT based mailbox drivers will be probed on-demand from fdt_mailbox_request_chan()
called by the mailbox client drivers.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mailbox/fdt_mailbox.h | 35 +++++++
lib/utils/mailbox/Kconfig | 6 ++
lib/utils/mailbox/fdt_mailbox.c | 96 ++++++++++++++++++++
lib/utils/mailbox/fdt_mailbox_drivers.carray | 5 +
lib/utils/mailbox/objects.mk | 3 +
5 files changed, 145 insertions(+)
create mode 100644 include/sbi_utils/mailbox/fdt_mailbox.h
create mode 100644 lib/utils/mailbox/fdt_mailbox.c
create mode 100644 lib/utils/mailbox/fdt_mailbox_drivers.carray
diff --git a/include/sbi_utils/mailbox/fdt_mailbox.h b/include/sbi_utils/mailbox/fdt_mailbox.h
new file mode 100644
index 00000000..0d5df340
--- /dev/null
+++ b/include/sbi_utils/mailbox/fdt_mailbox.h
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#ifndef __FDT_MAILBOX_H__
+#define __FDT_MAILBOX_H__
+
+#include <sbi_utils/fdt/fdt_driver.h>
+#include <sbi_utils/mailbox/mailbox.h>
+
+struct fdt_phandle_args;
+
+/** FDT based mailbox driver */
+struct fdt_mailbox {
+ struct fdt_driver driver;
+ int (*xlate)(struct mbox_controller *mbox,
+ const struct fdt_phandle_args *pargs,
+ u32 *out_chan_args);
+};
+
+/** Request a mailbox channel using "mboxes" DT property of client DT node */
+int fdt_mailbox_request_chan(const void *fdt, int nodeoff, int index,
+ struct mbox_chan **out_chan);
+
+/** Simple xlate function to convert one mailbox FDT cell into channel args */
+int fdt_mailbox_simple_xlate(struct mbox_controller *mbox,
+ const struct fdt_phandle_args *pargs,
+ u32 *out_chan_args);
+
+#endif
diff --git a/lib/utils/mailbox/Kconfig b/lib/utils/mailbox/Kconfig
index f91a9bb9..3957bfba 100644
--- a/lib/utils/mailbox/Kconfig
+++ b/lib/utils/mailbox/Kconfig
@@ -2,6 +2,12 @@
menu "Mailbox Support"
+config FDT_MAILBOX
+ bool "FDT based mailbox drivers"
+ depends on FDT
+ select MAILBOX
+ default n
+
config MAILBOX
bool "Mailbox support"
default n
diff --git a/lib/utils/mailbox/fdt_mailbox.c b/lib/utils/mailbox/fdt_mailbox.c
new file mode 100644
index 00000000..6378ab0d
--- /dev/null
+++ b/lib/utils/mailbox/fdt_mailbox.c
@@ -0,0 +1,96 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_error.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/mailbox/fdt_mailbox.h>
+
+/* List of FDT mailbox drivers generated at compile time */
+extern const struct fdt_driver *const fdt_mailbox_drivers[];
+
+static int fdt_mbox_controller_find(const void *fdt, int nodeoff,
+ struct mbox_controller **out_mbox)
+{
+ int rc;
+ struct mbox_controller *mbox = mbox_controller_find(nodeoff);
+
+ if (!mbox) {
+ /* mailbox not found so initialize matching driver */
+ rc = fdt_driver_init_by_offset(fdt, nodeoff, fdt_mailbox_drivers);
+ if (rc)
+ return rc;
+
+ /* Try to find mailbox controller again */
+ mbox = mbox_controller_find(nodeoff);
+ if (!mbox)
+ return SBI_ENOSYS;
+ }
+
+ if (out_mbox)
+ *out_mbox = mbox;
+
+ return 0;
+}
+
+int fdt_mailbox_request_chan(const void *fdt, int nodeoff, int index,
+ struct mbox_chan **out_chan)
+{
+ int rc;
+ struct mbox_chan *chan;
+ struct fdt_mailbox *drv;
+ struct fdt_phandle_args pargs;
+ struct mbox_controller *mbox = NULL;
+ u32 chan_args[MBOX_CHAN_MAX_ARGS];
+
+ if (!fdt || (nodeoff < 0) || (index < 0) || !out_chan)
+ return SBI_EINVAL;
+
+ pargs.node_offset = pargs.args_count = 0;
+ rc = fdt_parse_phandle_with_args(fdt, nodeoff,
+ "mboxes", "#mbox-cells",
+ index, &pargs);
+ if (rc)
+ return rc;
+
+ rc = fdt_mbox_controller_find(fdt, pargs.node_offset, &mbox);
+ if (rc)
+ return rc;
+
+ drv = mbox->driver;
+ if (!drv || !drv->xlate)
+ return SBI_ENOSYS;
+
+ rc = drv->xlate(mbox, &pargs, chan_args);
+ if (rc)
+ return rc;
+
+ chan = mbox_controller_request_chan(mbox, chan_args);
+ if (!chan)
+ return SBI_ENOENT;
+
+ *out_chan = chan;
+ return 0;
+}
+
+int fdt_mailbox_simple_xlate(struct mbox_controller *mbox,
+ const struct fdt_phandle_args *pargs,
+ u32 *out_chan_args)
+{
+ int i;
+
+ if (pargs->args_count < 1)
+ return SBI_EINVAL;
+
+ out_chan_args[0] = pargs->args[0];
+ for (i = 1; i < MBOX_CHAN_MAX_ARGS; i++)
+ out_chan_args[i] = 0;
+
+ return 0;
+}
diff --git a/lib/utils/mailbox/fdt_mailbox_drivers.carray b/lib/utils/mailbox/fdt_mailbox_drivers.carray
new file mode 100644
index 00000000..cf87d40c
--- /dev/null
+++ b/lib/utils/mailbox/fdt_mailbox_drivers.carray
@@ -0,0 +1,5 @@
+HEADER: sbi_utils/mailbox/fdt_mailbox.h
+TYPE: const struct fdt_mailbox
+NAME: fdt_mailbox_drivers
+MEMBER-NAME: driver
+MEMBER-TYPE: const struct fdt_driver
diff --git a/lib/utils/mailbox/objects.mk b/lib/utils/mailbox/objects.mk
index 79b27e4c..2135898c 100644
--- a/lib/utils/mailbox/objects.mk
+++ b/lib/utils/mailbox/objects.mk
@@ -7,4 +7,7 @@
# Anup Patel <apatel@ventanamicro.com>
#
+libsbiutils-objs-$(CONFIG_FDT_MAILBOX) += mailbox/fdt_mailbox.o
+libsbiutils-objs-$(CONFIG_FDT_MAILBOX) += mailbox/fdt_mailbox_drivers.carray.o
+
libsbiutils-objs-$(CONFIG_MAILBOX) += mailbox/mailbox.o
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 04/17] lib/utils: Add RPMI messaging protocol and shared memory transport support
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (2 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 03/17] lib: utils/mailbox: Add simple FDT based mailbox framework Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 05/17] lib/utils: reset: Add RPMI System Reset driver Anup Patel
` (13 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Rahul Pathak <rpathak@ventanamicro.com>
The RISC-V Platform Management Interface (RPMI) defines a messaging protocol
and shared memory based transport for bi-directional communication with an
on-chip or external microcontroller.
To support RPMI in OpenSBI, add:
1) The RPMI messaging protocol defines and helper macros
2) A FDT mailbox driver for the RPMI shared memory transport
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mailbox/rpmi_mailbox.h | 32 +
include/sbi_utils/mailbox/rpmi_msgprot.h | 255 +++++++
lib/utils/mailbox/Kconfig | 14 +
lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c | 773 +++++++++++++++++++++
lib/utils/mailbox/objects.mk | 5 +
lib/utils/mailbox/rpmi_mailbox.c | 91 +++
platform/generic/configs/defconfig | 3 +
7 files changed, 1173 insertions(+)
create mode 100644 include/sbi_utils/mailbox/rpmi_mailbox.h
create mode 100644 include/sbi_utils/mailbox/rpmi_msgprot.h
create mode 100644 lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
create mode 100644 lib/utils/mailbox/rpmi_mailbox.c
diff --git a/include/sbi_utils/mailbox/rpmi_mailbox.h b/include/sbi_utils/mailbox/rpmi_mailbox.h
new file mode 100644
index 00000000..61af51a8
--- /dev/null
+++ b/include/sbi_utils/mailbox/rpmi_mailbox.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#ifndef __RPMI_MAILBOX_H__
+#define __RPMI_MAILBOX_H__
+
+#include <sbi/sbi_error.h>
+#include <sbi_utils/mailbox/rpmi_msgprot.h>
+
+#define rpmi_u32_count(__var) (sizeof(__var) / sizeof(u32))
+
+/** Convert RPMI error to SBI error */
+int rpmi_xlate_error(enum rpmi_error error);
+
+/** Typical RPMI normal request with at least status code in response */
+int rpmi_normal_request_with_status(
+ struct mbox_chan *chan, u32 service_id,
+ void *req, u32 req_words, u32 req_endian_words,
+ void *resp, u32 resp_words, u32 resp_endian_words);
+
+/* RPMI posted request which is without any response*/
+int rpmi_posted_request(
+ struct mbox_chan *chan, u32 service_id,
+ void *req, u32 req_words, u32 req_endian_words);
+
+#endif /* !__RPMI_MAILBOX_H__ */
diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h
new file mode 100644
index 00000000..f9f65447
--- /dev/null
+++ b/include/sbi_utils/mailbox/rpmi_msgprot.h
@@ -0,0 +1,255 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Rahul Pathak <rpathak@ventanamicro.com>
+ */
+
+#ifndef __RPMI_MSGPROT_H__
+#define __RPMI_MSGPROT_H__
+
+#include <sbi/sbi_byteorder.h>
+#include <sbi/sbi_error.h>
+
+/*
+ * 31 0
+ * +---------------------+-----------------------+
+ * | FLAGS | SERVICE_ID | SERVICEGROUP_ID |
+ * +---------------------+-----------------------+
+ * | TOKEN | DATA LENGTH |
+ * +---------------------+-----------------------+
+ * | DATA/PAYLOAD |
+ * +---------------------------------------------+
+ */
+
+/** Message Header byte offset */
+#define RPMI_MSG_HDR_OFFSET (0x0)
+/** Message Header Size in bytes */
+#define RPMI_MSG_HDR_SIZE (8)
+
+/** ServiceGroup ID field byte offset */
+#define RPMI_MSG_SERVICEGROUP_ID_OFFSET (0x0)
+/** ServiceGroup ID field size in bytes */
+#define RPMI_MSG_SERVICEGROUP_ID_SIZE (2)
+
+/** Service ID field byte offset */
+#define RPMI_MSG_SERVICE_ID_OFFSET (0x2)
+/** Service ID field size in bytes */
+#define RPMI_MSG_SERVICE_ID_SIZE (1)
+
+/** Flags field byte offset */
+#define RPMI_MSG_FLAGS_OFFSET (0x3)
+/** Flags field size in bytes */
+#define RPMI_MSG_FLAGS_SIZE (1)
+
+#define RPMI_MSG_FLAGS_TYPE_POS (0U)
+#define RPMI_MSG_FLAGS_TYPE_MASK 0x7
+#define RPMI_MSG_FLAGS_TYPE \
+ ((0x7) << RPMI_MSG_FLAGS_TYPE_POS)
+
+#define RPMI_MSG_FLAGS_DOORBELL_POS (3U)
+#define RPMI_MSG_FLAGS_DOORBELL_MASK 0x1
+#define RPMI_MSG_FLAGS_DOORBELL \
+ ((0x1) << RPMI_MSG_FLAGS_DOORBELL_POS)
+
+/** Data length field byte offset */
+#define RPMI_MSG_DATALEN_OFFSET (0x4)
+/** Data length field size in bytes */
+#define RPMI_MSG_DATALEN_SIZE (2)
+
+/** Token field byte offset */
+#define RPMI_MSG_TOKEN_OFFSET (0x6)
+/** Token field size in bytes */
+#define RPMI_MSG_TOKEN_SIZE (2)
+/** Token field mask */
+#define RPMI_MSG_TOKEN_MASK (0xffffU)
+
+/** Data field byte offset */
+#define RPMI_MSG_DATA_OFFSET (RPMI_MSG_HDR_SIZE)
+/** Data field size in bytes */
+#define RPMI_MSG_DATA_SIZE(__slot_size) ((__slot_size) - RPMI_MSG_HDR_SIZE)
+
+/** Minimum slot size in bytes */
+#define RPMI_SLOT_SIZE_MIN (64)
+
+/** Name length of 16 characters */
+#define RPMI_NAME_CHARS_MAX (16)
+
+/** Queue layout */
+#define RPMI_QUEUE_HEAD_SLOT 0
+#define RPMI_QUEUE_TAIL_SLOT 1
+#define RPMI_QUEUE_HEADER_SLOTS 2
+
+/** Default timeout values */
+#define RPMI_DEF_TX_TIMEOUT 20
+#define RPMI_DEF_RX_TIMEOUT 20
+
+/**
+ * Common macro to generate composite version from major
+ * and minor version numbers.
+ *
+ * RPMI has Specification version, Implementation version
+ * Service group versions which follow the same versioning
+ * encoding as below.
+ */
+#define RPMI_VERSION(__major, __minor) (((__major) << 16) | (__minor))
+
+/** RPMI Message Header */
+struct rpmi_message_header {
+ le16_t servicegroup_id;
+ uint8_t service_id;
+ uint8_t flags;
+ le16_t datalen;
+ le16_t token;
+} __packed;
+
+/** RPMI Message */
+struct rpmi_message {
+ struct rpmi_message_header header;
+ u8 data[0];
+} __packed;
+
+/** RPMI Messages Types */
+enum rpmi_message_type {
+ /* Normal request backed with ack */
+ RPMI_MSG_NORMAL_REQUEST = 0x0,
+ /* Request without any ack */
+ RPMI_MSG_POSTED_REQUEST = 0x1,
+ /* Acknowledgment for normal request message */
+ RPMI_MSG_ACKNOWLDGEMENT = 0x2,
+ /* Notification message */
+ RPMI_MSG_NOTIFICATION = 0x3,
+};
+
+/** RPMI Error Types */
+enum rpmi_error {
+ /* Success */
+ RPMI_SUCCESS = 0,
+ /* General failure */
+ RPMI_ERR_FAILED = -1,
+ /* Service or feature not supported */
+ RPMI_ERR_NOTSUPP = -2,
+ /* Invalid Parameter */
+ RPMI_ERR_INVALID_PARAM = -3,
+ /*
+ * Denied to insufficient permissions
+ * or due to unmet prerequisite
+ */
+ RPMI_ERR_DENIED = -4,
+ /* Invalid address or offset */
+ RPMI_ERR_INVALID_ADDR = -5,
+ /*
+ * Operation failed as it was already in
+ * progress or the state has changed already
+ * for which the operation was carried out.
+ */
+ RPMI_ERR_ALREADY = -6,
+ /*
+ * Error in implementation which violates
+ * the specification version
+ */
+ RPMI_ERR_EXTENSION = -7,
+ /* Operation failed due to hardware issues */
+ RPMI_ERR_HW_FAULT = -8,
+ /* System, device or resource is busy */
+ RPMI_ERR_BUSY = -9,
+ /* System or device or resource in invalid state */
+ RPMI_ERR_INVALID_STATE = -10,
+ /* Index, offset or address is out of range */
+ RPMI_ERR_BAD_RANGE = -11,
+ /* Operation timed out */
+ RPMI_ERR_TIMEOUT = -12,
+ /*
+ * Error in input or output or
+ * error in sending or receiving data
+ * through communication medium
+ */
+ RPMI_ERR_IO = -13,
+ /* No data available */
+ RPMI_ERR_NO_DATA = -14,
+ RPMI_ERR_RESERVED_START = -15,
+ RPMI_ERR_RESERVED_END = -127,
+ RPMI_ERR_VENDOR_START = -128,
+};
+
+/** RPMI Message Arguments */
+struct rpmi_message_args {
+ u32 flags;
+#define RPMI_MSG_FLAGS_NO_TX (1U << 0)
+#define RPMI_MSG_FLAGS_NO_RX (1U << 1)
+#define RPMI_MSG_FLAGS_NO_RX_TOKEN (1U << 2)
+ enum rpmi_message_type type;
+ u8 service_id;
+ u32 tx_endian_words;
+ u32 rx_endian_words;
+ u16 rx_token;
+ u32 rx_data_len;
+};
+
+/*
+ * RPMI SERVICEGROUPS AND SERVICES
+ */
+
+/** RPMI ServiceGroups IDs */
+enum rpmi_servicegroup_id {
+ RPMI_SRVGRP_ID_MIN = 0,
+ RPMI_SRVGRP_BASE = 0x0001,
+ RPMI_SRVGRP_ID_MAX_COUNT,
+
+ /* Reserved range for service groups */
+ RPMI_SRVGRP_RESERVE_START = RPMI_SRVGRP_ID_MAX_COUNT,
+ RPMI_SRVGRP_RESERVE_END = 0x7FFF,
+
+ /* Vendor/Implementation-specific service groups range */
+ RPMI_SRVGRP_VENDOR_START = 0x8000,
+ RPMI_SRVGRP_VENDOR_END = 0xFFFF,
+};
+
+/** RPMI enable notification request */
+struct rpmi_enable_notification_req {
+ u32 eventid;
+};
+
+/** RPMI enable notification response */
+struct rpmi_enable_notification_resp {
+ s32 status;
+};
+
+/** RPMI Base ServiceGroup Service IDs */
+enum rpmi_base_service_id {
+ RPMI_BASE_SRV_ENABLE_NOTIFICATION = 0x01,
+ RPMI_BASE_SRV_GET_IMPLEMENTATION_VERSION = 0x02,
+ RPMI_BASE_SRV_GET_IMPLEMENTATION_IDN = 0x03,
+ RPMI_BASE_SRV_GET_SPEC_VERSION = 0x04,
+ RPMI_BASE_SRV_GET_PLATFORM_INFO = 0x05,
+ RPMI_BASE_SRV_PROBE_SERVICE_GROUP = 0x06,
+ RPMI_BASE_SRV_GET_ATTRIBUTES = 0x07,
+ RPMI_BASE_SRV_SET_MSI = 0x08,
+};
+
+#define RPMI_BASE_FLAGS_F0_PRIVILEGE (1U << 2)
+#define RPMI_BASE_FLAGS_F0_EV_NOTIFY (1U << 1)
+#define RPMI_BASE_FLAGS_F0_MSI_EN (1U)
+
+enum rpmi_base_context_priv_level {
+ RPMI_BASE_CONTEXT_PRIV_S_MODE,
+ RPMI_BASE_CONTEXT_PRIV_M_MODE,
+};
+
+struct rpmi_base_get_attributes_resp {
+ s32 status_code;
+ u32 f0;
+ u32 f1;
+ u32 f2;
+ u32 f3;
+};
+
+struct rpmi_base_get_platform_info_resp {
+ s32 status;
+ u32 plat_info_len;
+ char plat_info[];
+};
+
+#endif /* !__RPMI_MSGPROT_H__ */
diff --git a/lib/utils/mailbox/Kconfig b/lib/utils/mailbox/Kconfig
index 3957bfba..6e7f2cdd 100644
--- a/lib/utils/mailbox/Kconfig
+++ b/lib/utils/mailbox/Kconfig
@@ -8,8 +8,22 @@ config FDT_MAILBOX
select MAILBOX
default n
+config RPMI_MAILBOX
+ bool "RPMI based mailbox drivers"
+ select MAILBOX
+ default n
+
config MAILBOX
bool "Mailbox support"
default n
+if FDT_MAILBOX
+
+config FDT_MAILBOX_RPMI_SHMEM
+ bool "RPMI Shared Memory Mailbox Controller"
+ depends on RPMI_MAILBOX
+ default n
+
+endif
+
endmenu
diff --git a/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c b/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
new file mode 100644
index 00000000..91db4e96
--- /dev/null
+++ b/lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
@@ -0,0 +1,773 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Rahul Pathak <rpathak@ventanamicro.com>
+ * Subrahmanya Lingappa <slingappa@ventanamicro.com>
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/sbi_timer.h>
+#include <sbi/riscv_io.h>
+#include <sbi/riscv_locks.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_barrier.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/mailbox/mailbox.h>
+#include <sbi_utils/mailbox/fdt_mailbox.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+
+/** Minimum Base group version required */
+#define RPMI_BASE_VERSION_MIN RPMI_VERSION(1, 0)
+
+/**************** RPMI Transport Structures and Macros ***********/
+
+#define GET_SERVICEGROUP_ID(msg) \
+({ \
+ struct rpmi_message *mbuf = msg; \
+ le16_to_cpu(mbuf->header.servicegroup_id);\
+})
+
+#define GET_SERVICE_ID(msg) \
+({ \
+ struct rpmi_message *mbuf = msg; \
+ mbuf->header.service_id; \
+})
+
+#define GET_FLAGS(msg) \
+({ \
+ struct rpmi_message *mbuf = msg; \
+ mbuf->header.flags; \
+})
+
+#define GET_MESSAGE_ID(msg) \
+({ \
+ struct rpmi_message *mbuf = msg; \
+ ((u32)mbuf->header.flags << (RPMI_MSG_FLAGS_OFFSET * 8)) | \
+ ((u32)mbuf->header.service_id << (RPMI_MSG_SERVICE_ID_OFFSET * 8)) | \
+ ((u32)le16_to_cpu(mbuf->header.servicegroup_id)); \
+})
+
+#define MAKE_MESSAGE_ID(__group_id, __service_id, __flags) \
+({ \
+ u32 __ret = 0; \
+ __ret |= (u32)(__group_id) << (RPMI_MSG_SERVICEGROUP_ID_OFFSET * 8); \
+ __ret |= (u32)(__service_id) << (RPMI_MSG_SERVICE_ID_OFFSET * 8); \
+ __ret |= (u32)(__flags) << (RPMI_MSG_FLAGS_OFFSET * 8); \
+ __ret; \
+})
+
+#define GET_DLEN(msg) \
+({ \
+ struct rpmi_message *mbuf = msg; \
+ le16_to_cpu(mbuf->header.datalen); \
+})
+
+#define GET_TOKEN(msg) \
+({ \
+ struct rpmi_message *mbuf = msg; \
+ le16_to_cpu(mbuf->header.token); \
+})
+
+#define GET_MESSAGE_TYPE(msg) \
+({ \
+ uint8_t flags = *((uint8_t *)msg + RPMI_MSG_FLAGS_OFFSET); \
+ ((flags & RPMI_MSG_FLAGS_TYPE) >> RPMI_MSG_FLAGS_TYPE_POS)); \
+})
+
+enum rpmi_queue_type {
+ RPMI_QUEUE_TYPE_REQ = 0,
+ RPMI_QUEUE_TYPE_ACK = 1,
+};
+
+enum rpmi_queue_idx {
+ RPMI_QUEUE_IDX_A2P_REQ = 0,
+ RPMI_QUEUE_IDX_P2A_ACK = 1,
+ RPMI_QUEUE_IDX_P2A_REQ = 2,
+ RPMI_QUEUE_IDX_A2P_ACK = 3,
+ RPMI_QUEUE_IDX_MAX_COUNT,
+};
+
+enum rpmi_reg_idx {
+ RPMI_REG_IDX_DB_REG = 0, /* Doorbell register */
+ RPMI_REG_IDX_MAX_COUNT,
+};
+
+/** Mailbox registers */
+struct rpmi_mb_regs {
+ /* doorbell from AP -> PuC*/
+ volatile le32_t db_reg;
+} __packed;
+
+/** Single Queue Context Structure */
+struct smq_queue_ctx {
+ u32 queue_id;
+ u32 num_slots;
+ spinlock_t queue_lock;
+ /* Type of queue - REQ or ACK */
+ enum rpmi_queue_type queue_type;
+ /* Pointers to the queue shared memory */
+ volatile le32_t *headptr;
+ volatile le32_t *tailptr;
+ volatile uint8_t *buffer;
+ /* Name of the queue */
+ char name[RPMI_NAME_CHARS_MAX];
+};
+
+struct rpmi_srvgrp_chan {
+ u32 servicegroup_id;
+ u32 servicegroup_version;
+ struct mbox_chan chan;
+};
+
+#define to_srvgrp_chan(mbox_chan) \
+ container_of(mbox_chan, struct rpmi_srvgrp_chan, chan);
+
+struct rpmi_shmem_mbox_controller {
+ /* Driver specific members */
+ u32 slot_size;
+ u32 queue_count;
+ struct rpmi_mb_regs *mb_regs;
+ struct smq_queue_ctx queue_ctx_tbl[RPMI_QUEUE_IDX_MAX_COUNT];
+ /* Mailbox framework related members */
+ struct mbox_controller controller;
+ struct mbox_chan *base_chan;
+ u32 impl_version;
+ u32 impl_id;
+ u32 spec_version;
+ u32 plat_info_len;
+ char *plat_info;
+ struct {
+ u8 f0_priv_level;
+ bool f0_ev_notif_en;
+ bool f0_msi_en;
+ } base_flags;
+};
+
+/**************** Shared Memory Queues Helpers **************/
+
+static bool __smq_queue_full(struct smq_queue_ctx *qctx)
+{
+ return ((le32_to_cpu(*qctx->tailptr) + 1) % qctx->num_slots ==
+ le32_to_cpu(*qctx->headptr)) ? true : false;
+}
+
+static bool __smq_queue_empty(struct smq_queue_ctx *qctx)
+{
+ return (le32_to_cpu(*qctx->headptr) ==
+ le32_to_cpu(*qctx->tailptr)) ? true : false;
+}
+
+static int __smq_rx(struct smq_queue_ctx *qctx, u32 slot_size,
+ u32 service_group_id, struct mbox_xfer *xfer)
+{
+ void *dst, *src;
+ struct rpmi_message *msg;
+ u32 i, tmp, pos, dlen, msgidn, headidx, tailidx;
+ struct rpmi_message_args *args = xfer->args;
+ bool no_rx_token = (args->flags & RPMI_MSG_FLAGS_NO_RX_TOKEN) ?
+ true : false;
+
+ /* Rx sanity checks */
+ if ((sizeof(u32) * args->rx_endian_words) >
+ (slot_size - sizeof(struct rpmi_message_header)))
+ return SBI_EINVAL;
+ if ((sizeof(u32) * args->rx_endian_words) > xfer->rx_len)
+ return SBI_EINVAL;
+
+ /* There should be some message in the queue */
+ if (__smq_queue_empty(qctx))
+ return SBI_ENOENT;
+
+ /* Get the head/read index and tail/write index */
+ headidx = le32_to_cpu(*qctx->headptr);
+ tailidx = le32_to_cpu(*qctx->tailptr);
+
+ /*
+ * Compute msgidn expected in the incoming message
+ * NOTE: DOORBELL bit is not expected to be set.
+ */
+ msgidn = MAKE_MESSAGE_ID(service_group_id, args->service_id, args->type);
+
+ /* Find the Rx message with matching token */
+ pos = headidx;
+ while (pos != tailidx) {
+ src = (void *)qctx->buffer + (pos * slot_size);
+ if ((no_rx_token && GET_MESSAGE_ID(src) == msgidn) ||
+ (GET_TOKEN(src) == (xfer->seq & RPMI_MSG_TOKEN_MASK)))
+ break;
+ pos = (pos + 1) % qctx->num_slots;
+ }
+ if (pos == tailidx)
+ return SBI_ENOENT;
+
+ /* If Rx message is not first message then make it first message */
+ if (pos != headidx) {
+ src = (void *)qctx->buffer + (pos * slot_size);
+ dst = (void *)qctx->buffer + (headidx * slot_size);
+ for (i = 0; i < slot_size / sizeof(u32); i++) {
+ tmp = ((u32 *)dst)[i];
+ ((u32 *)dst)[i] = ((u32 *)src)[i];
+ ((u32 *)src)[i] = tmp;
+ }
+ }
+
+ /* Update rx_token if not available */
+ msg = (void *)qctx->buffer + (headidx * slot_size);
+ if (no_rx_token)
+ args->rx_token = GET_TOKEN(msg);
+
+ /* Extract data from the first message */
+ if (xfer->rx) {
+ args->rx_data_len = dlen = GET_DLEN(msg);
+ if (dlen > xfer->rx_len)
+ dlen = xfer->rx_len;
+ src = (void *)msg + sizeof(struct rpmi_message_header);
+ dst = xfer->rx;
+ for (i = 0; i < args->rx_endian_words; i++)
+ ((u32 *)dst)[i] = le32_to_cpu(((u32 *)src)[i]);
+ dst += sizeof(u32) * args->rx_endian_words;
+ src += sizeof(u32) * args->rx_endian_words;
+ sbi_memcpy(dst, src,
+ xfer->rx_len - (sizeof(u32) * args->rx_endian_words));
+ }
+
+ /* Update the head/read index */
+ *qctx->headptr = cpu_to_le32(headidx + 1) % qctx->num_slots;
+
+ /* Make sure updates to head are immediately visible to PuC */
+ smp_wmb();
+
+ return SBI_OK;
+}
+
+static int __smq_tx(struct smq_queue_ctx *qctx, struct rpmi_mb_regs *mb_regs,
+ u32 slot_size, u32 service_group_id, struct mbox_xfer *xfer)
+{
+ u32 i, tailidx;
+ void *dst, *src;
+ struct rpmi_message_header header = { 0 };
+ struct rpmi_message_args *args = xfer->args;
+
+ /* Tx sanity checks */
+ if ((sizeof(u32) * args->tx_endian_words) >
+ (slot_size - sizeof(struct rpmi_message_header)))
+ return SBI_EINVAL;
+ if ((sizeof(u32) * args->tx_endian_words) > xfer->tx_len)
+ return SBI_EINVAL;
+
+ /* There should be some room in the queue */
+ if (__smq_queue_full(qctx))
+ return SBI_ENOMEM;
+
+ /* Get the tail/write index */
+ tailidx = le32_to_cpu(*qctx->tailptr);
+
+ /* Prepare the header to be written into the slot */
+ header.servicegroup_id = cpu_to_le16(service_group_id);
+ header.service_id = args->service_id;
+ header.flags = args->type;
+ header.datalen = cpu_to_le16((u16)xfer->tx_len);
+ header.token = cpu_to_le16((u16)xfer->seq);
+
+ /* Write header into the slot */
+ dst = (char *)qctx->buffer + (tailidx * slot_size);
+ sbi_memcpy(dst, &header, sizeof(header));
+ dst += sizeof(header);
+
+ /* Write data into the slot */
+ if (xfer->tx) {
+ src = xfer->tx;
+ for (i = 0; i < args->tx_endian_words; i++)
+ ((u32 *)dst)[i] = cpu_to_le32(((u32 *)src)[i]);
+ dst += sizeof(u32) * args->tx_endian_words;
+ src += sizeof(u32) * args->tx_endian_words;
+ sbi_memcpy(dst, src,
+ xfer->tx_len - (sizeof(u32) * args->tx_endian_words));
+ }
+
+ /* Make sure queue chanages are visible to PuC before updating tail */
+ smp_wmb();
+
+ /* Update the tail/write index */
+ *qctx->tailptr = cpu_to_le32(tailidx + 1) % qctx->num_slots;
+
+ /* Ring the RPMI doorbell if present */
+ if (mb_regs)
+ writel(cpu_to_le32(1), &mb_regs->db_reg);
+
+ return SBI_OK;
+}
+
+static int smq_rx(struct rpmi_shmem_mbox_controller *mctl,
+ u32 queue_id, u32 service_group_id, struct mbox_xfer *xfer)
+{
+ int ret, rxretry = 0;
+ struct smq_queue_ctx *qctx;
+
+ if (mctl->queue_count < queue_id) {
+ sbi_printf("%s: invalid queue_id or service_group_id\n",
+ __func__);
+ return SBI_EINVAL;
+ }
+ qctx = &mctl->queue_ctx_tbl[queue_id];
+
+ /*
+ * Once the timeout happens and call this function is returned
+ * to the client then there is no way to deliver the response
+ * message after that if it comes later.
+ *
+ * REVISIT: In complete timeout duration how much duration
+ * it should wait(delay) before recv retry. udelay or mdelay
+ */
+ do {
+ spin_lock(&qctx->queue_lock);
+ ret = __smq_rx(qctx, mctl->slot_size, service_group_id, xfer);
+ spin_unlock(&qctx->queue_lock);
+ if (!ret)
+ return 0;
+
+ sbi_timer_mdelay(1);
+ rxretry += 1;
+ } while (rxretry < xfer->rx_timeout);
+
+ return SBI_ETIMEDOUT;
+}
+
+static int smq_tx(struct rpmi_shmem_mbox_controller *mctl,
+ u32 queue_id, u32 service_group_id, struct mbox_xfer *xfer)
+{
+ int ret, txretry = 0;
+ struct smq_queue_ctx *qctx;
+
+ if (mctl->queue_count < queue_id) {
+ sbi_printf("%s: invalid queue_id or service_group_id\n",
+ __func__);
+ return SBI_EINVAL;
+ }
+ qctx = &mctl->queue_ctx_tbl[queue_id];
+
+ /*
+ * Ignoring the tx timeout since in RPMI has no mechanism
+ * with which other side can let know about the reception of
+ * message which marks as tx complete. For RPMI tx complete is
+ * marked as done when message in successfully copied in queue.
+ *
+ * REVISIT: In complete timeout duration how much duration
+ * it should wait(delay) before send retry. udelay or mdelay
+ */
+ do {
+ spin_lock(&qctx->queue_lock);
+ ret = __smq_tx(qctx, mctl->mb_regs, mctl->slot_size,
+ service_group_id, xfer);
+ spin_unlock(&qctx->queue_lock);
+ if (!ret)
+ return 0;
+
+ sbi_timer_mdelay(1);
+ txretry += 1;
+ } while (txretry < xfer->tx_timeout);
+
+ return SBI_ETIMEDOUT;
+}
+
+static int rpmi_get_platform_info(struct rpmi_shmem_mbox_controller *mctl)
+{
+ int ret = SBI_OK;
+
+ /**
+ * platform string can occupy max possible size
+ * max possible space in the message data as
+ * per the format
+ */
+ struct rpmi_base_get_platform_info_resp *resp =
+ sbi_zalloc(RPMI_MSG_DATA_SIZE(mctl->slot_size));
+ if (!resp)
+ return SBI_ENOMEM;
+
+ ret = rpmi_normal_request_with_status(mctl->base_chan,
+ RPMI_BASE_SRV_GET_PLATFORM_INFO,
+ NULL, 0, 0,
+ resp,
+ RPMI_MSG_DATA_SIZE(mctl->slot_size)/4,
+ RPMI_MSG_DATA_SIZE(mctl->slot_size)/4);
+ if (ret)
+ goto fail_free_resp;
+
+ mctl->plat_info_len = resp->plat_info_len;
+ mctl->plat_info = sbi_zalloc(mctl->plat_info_len);
+ if (!mctl->plat_info) {
+ ret = SBI_ENOMEM;
+ goto fail_free_resp;
+ }
+
+ sbi_strncpy(mctl->plat_info, resp->plat_info, mctl->plat_info_len);
+
+fail_free_resp:
+ sbi_free(resp);
+ return ret;
+}
+
+static int smq_base_get_two_u32(struct rpmi_shmem_mbox_controller *mctl,
+ u32 service_id, u32 *inarg, u32 *outvals)
+{
+ return rpmi_normal_request_with_status(
+ mctl->base_chan, service_id,
+ inarg, (inarg) ? 1 : 0, (inarg) ? 1 : 0,
+ outvals, 2, 2);
+}
+
+/**************** Mailbox Controller Functions **************/
+
+static int rpmi_shmem_mbox_xfer(struct mbox_chan *chan, struct mbox_xfer *xfer)
+{
+ int ret;
+ u32 tx_qid = 0, rx_qid = 0;
+ struct rpmi_shmem_mbox_controller *mctl =
+ container_of(chan->mbox,
+ struct rpmi_shmem_mbox_controller,
+ controller);
+ struct rpmi_srvgrp_chan *srvgrp_chan = to_srvgrp_chan(chan);
+
+ struct rpmi_message_args *args = xfer->args;
+ bool do_tx = (args->flags & RPMI_MSG_FLAGS_NO_TX) ? false : true;
+ bool do_rx = (args->flags & RPMI_MSG_FLAGS_NO_RX) ? false : true;
+
+ if (!do_tx && !do_rx)
+ return SBI_EINVAL;
+
+ switch (args->type) {
+ case RPMI_MSG_NORMAL_REQUEST:
+ if (do_tx && do_rx) {
+ tx_qid = RPMI_QUEUE_IDX_A2P_REQ;
+ rx_qid = RPMI_QUEUE_IDX_P2A_ACK;
+ } else if (do_tx) {
+ tx_qid = RPMI_QUEUE_IDX_A2P_REQ;
+ } else if (do_rx) {
+ rx_qid = RPMI_QUEUE_IDX_P2A_REQ;
+ }
+ break;
+ case RPMI_MSG_POSTED_REQUEST:
+ if (do_tx && do_rx)
+ return SBI_EINVAL;
+ if (do_tx) {
+ tx_qid = RPMI_QUEUE_IDX_A2P_REQ;
+ } else {
+ rx_qid = RPMI_QUEUE_IDX_P2A_REQ;
+ }
+ break;
+ case RPMI_MSG_ACKNOWLDGEMENT:
+ if (do_tx && do_rx)
+ return SBI_EINVAL;
+ if (do_tx) {
+ tx_qid = RPMI_QUEUE_IDX_A2P_ACK;
+ } else {
+ rx_qid = RPMI_QUEUE_IDX_P2A_ACK;
+ }
+ break;
+ default:
+ return SBI_ENOTSUPP;
+ }
+
+ if (do_tx) {
+ ret = smq_tx(mctl, tx_qid, srvgrp_chan->servicegroup_id, xfer);
+ if (ret)
+ return ret;
+ }
+
+ if (do_rx) {
+ ret = smq_rx(mctl, rx_qid, srvgrp_chan->servicegroup_id, xfer);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static struct mbox_chan *rpmi_shmem_mbox_request_chan(
+ struct mbox_controller *mbox,
+ u32 *chan_args)
+{
+ int ret;
+ u32 tval[2] = { 0 };
+ struct rpmi_srvgrp_chan *srvgrp_chan;
+ struct rpmi_shmem_mbox_controller *mctl =
+ container_of(mbox,
+ struct rpmi_shmem_mbox_controller,
+ controller);
+
+ /* Service group id not defined or in reserved range is invalid */
+ if (chan_args[0] >= RPMI_SRVGRP_ID_MAX_COUNT &&
+ chan_args[0] <= RPMI_SRVGRP_RESERVE_END)
+ return NULL;
+
+ /* Base serivce group is always present so probe other groups */
+ if (chan_args[0] != RPMI_SRVGRP_BASE) {
+ /* Probe service group */
+ ret = smq_base_get_two_u32(mctl,
+ RPMI_BASE_SRV_PROBE_SERVICE_GROUP,
+ chan_args, tval);
+ if (ret || !tval[1])
+ return NULL;
+ }
+
+ srvgrp_chan = sbi_zalloc(sizeof(*srvgrp_chan));
+ if (!srvgrp_chan)
+ return NULL;
+
+ srvgrp_chan->servicegroup_id = chan_args[0];
+ srvgrp_chan->servicegroup_version = tval[1];
+
+ return &srvgrp_chan->chan;
+}
+
+static void rpmi_shmem_mbox_free_chan(struct mbox_controller *mbox,
+ struct mbox_chan *chan)
+{
+ struct rpmi_srvgrp_chan *srvgrp_chan = to_srvgrp_chan(chan);
+ sbi_free(srvgrp_chan);
+}
+
+extern struct fdt_mailbox fdt_mailbox_rpmi_shmem;
+
+static int rpmi_shmem_transport_init(struct rpmi_shmem_mbox_controller *mctl,
+ const void *fdt, int nodeoff)
+{
+ const char *name;
+ int count, len, ret, qid;
+ uint64_t reg_addr, reg_size;
+ const fdt32_t *prop_slotsz;
+ struct smq_queue_ctx *qctx;
+
+ ret = fdt_node_check_compatible(fdt, nodeoff,
+ "riscv,rpmi-shmem-mbox");
+ if (ret)
+ return ret;
+
+ /* get queue slot size in bytes */
+ prop_slotsz = fdt_getprop(fdt, nodeoff, "riscv,slot-size", &len);
+ if (!prop_slotsz)
+ return SBI_ENOENT;
+
+ mctl->slot_size = fdt32_to_cpu(*prop_slotsz);
+ if (mctl->slot_size < RPMI_SLOT_SIZE_MIN) {
+ sbi_printf("%s: slot_size < mimnum required message size\n",
+ __func__);
+ mctl->slot_size = RPMI_SLOT_SIZE_MIN;
+ }
+
+ /*
+ * queue names count is taken as the number of queues
+ * supported which make it mandatory to provide the
+ * name of the queue.
+ */
+ count = fdt_stringlist_count(fdt, nodeoff, "reg-names");
+ if (count < 0 ||
+ count > (RPMI_QUEUE_IDX_MAX_COUNT + RPMI_REG_IDX_MAX_COUNT))
+ return SBI_EINVAL;
+
+ mctl->queue_count = count - RPMI_REG_IDX_MAX_COUNT;
+
+ /* parse all queues and populate queues context structure */
+ for (qid = 0; qid < mctl->queue_count; qid++) {
+ qctx = &mctl->queue_ctx_tbl[qid];
+
+ /* get each queue share-memory base address and size*/
+ ret = fdt_get_node_addr_size(fdt, nodeoff, qid,
+ ®_addr, ®_size);
+ if (ret < 0 || !reg_addr || !reg_size)
+ return SBI_ENOENT;
+
+ ret = sbi_domain_root_add_memrange(reg_addr, reg_size, reg_size,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (ret)
+ return ret;
+
+ /* calculate number of slots in each queue */
+ qctx->num_slots =
+ (reg_size - (mctl->slot_size * RPMI_QUEUE_HEADER_SLOTS)) / mctl->slot_size;
+
+ /* setup queue pointers */
+ qctx->headptr = ((void *)(unsigned long)reg_addr) +
+ RPMI_QUEUE_HEAD_SLOT * mctl->slot_size;
+ qctx->tailptr = ((void *)(unsigned long)reg_addr) +
+ RPMI_QUEUE_TAIL_SLOT * mctl->slot_size;
+ qctx->buffer = ((void *)(unsigned long)reg_addr) +
+ RPMI_QUEUE_HEADER_SLOTS * mctl->slot_size;
+
+ /* get the queue name */
+ name = fdt_stringlist_get(fdt, nodeoff, "reg-names",
+ qid, &len);
+ if (!name || (name && len < 0))
+ return len;
+
+ sbi_memcpy(qctx->name, name, len);
+
+ /* store the index as queue_id */
+ qctx->queue_id = qid;
+
+ SPIN_LOCK_INIT(qctx->queue_lock);
+ }
+
+ /* get the db-reg property name */
+ name = fdt_stringlist_get(fdt, nodeoff, "reg-names", qid, &len);
+ if (!name || (name && len < 0))
+ return len;
+
+ /* fetch doorbell register address*/
+ ret = fdt_get_node_addr_size(fdt, nodeoff, qid, ®_addr,
+ ®_size);
+ if (!ret && !(strncmp(name, "db-reg", strlen("db-reg")))) {
+ mctl->mb_regs = (void *)(unsigned long)reg_addr;
+ ret = sbi_domain_root_add_memrange(reg_addr, reg_size, reg_size,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (ret)
+ return ret;
+ }
+
+ return SBI_SUCCESS;
+}
+
+static int rpmi_shmem_mbox_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ struct rpmi_base_get_attributes_resp resp;
+ struct rpmi_shmem_mbox_controller *mctl;
+ struct rpmi_srvgrp_chan *base_srvgrp;
+ u32 tval[2], args[1];
+ int ret = 0;
+
+ mctl = sbi_zalloc(sizeof(*mctl));
+ if (!mctl)
+ return SBI_ENOMEM;
+
+ /* Initialization transport from device tree */
+ ret = rpmi_shmem_transport_init(mctl, fdt, nodeoff);
+ if (ret)
+ goto fail_free_controller;
+
+ /* Register mailbox controller */
+ mctl->controller.id = nodeoff;
+ mctl->controller.max_xfer_len =
+ mctl->slot_size - sizeof(struct rpmi_message_header);
+ mctl->controller.driver = &fdt_mailbox_rpmi_shmem;
+ mctl->controller.request_chan = rpmi_shmem_mbox_request_chan;
+ mctl->controller.free_chan = rpmi_shmem_mbox_free_chan;
+ mctl->controller.xfer = rpmi_shmem_mbox_xfer;
+ ret = mbox_controller_add(&mctl->controller);
+ if (ret)
+ goto fail_free_controller;
+
+ /* Request base service group channel */
+ tval[0] = RPMI_SRVGRP_BASE;
+ mctl->base_chan = mbox_controller_request_chan(&mctl->controller,
+ tval);
+ if (!mctl->base_chan) {
+ ret = SBI_ENOENT;
+ goto fail_remove_controller;
+ }
+
+ /* Update base service group version */
+ base_srvgrp = to_srvgrp_chan(mctl->base_chan);
+ args[0] = RPMI_SRVGRP_BASE;
+ ret = smq_base_get_two_u32(mctl, RPMI_BASE_SRV_PROBE_SERVICE_GROUP,
+ &args[0], tval);
+ if (ret)
+ goto fail_free_chan;
+ base_srvgrp->servicegroup_version = tval[1];
+ if (base_srvgrp->servicegroup_version < RPMI_BASE_VERSION_MIN) {
+ ret = SBI_EINVAL;
+ goto fail_free_chan;
+ }
+
+ /* Get implementation id */
+ ret = smq_base_get_two_u32(mctl,
+ RPMI_BASE_SRV_GET_IMPLEMENTATION_VERSION,
+ NULL, tval);
+ if (ret)
+ goto fail_free_chan;
+ mctl->impl_version = tval[1];
+
+ /* Get implementation version */
+ ret = smq_base_get_two_u32(mctl, RPMI_BASE_SRV_GET_IMPLEMENTATION_IDN,
+ NULL, tval);
+ if (ret)
+ goto fail_free_chan;
+ mctl->impl_id = tval[1];
+
+ /* Get specification version */
+ ret = smq_base_get_two_u32(mctl, RPMI_BASE_SRV_GET_SPEC_VERSION,
+ NULL, tval);
+ if (ret)
+ goto fail_free_chan;
+ mctl->spec_version = tval[1];
+ if (mctl->spec_version < RPMI_BASE_VERSION_MIN ||
+ mctl->spec_version != base_srvgrp->servicegroup_version) {
+ ret = SBI_EINVAL;
+ goto fail_free_chan;
+ }
+
+ /* Get optional features implementation flags */
+ ret = rpmi_normal_request_with_status(
+ mctl->base_chan, RPMI_BASE_SRV_GET_ATTRIBUTES,
+ NULL, 0, 0,
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (ret)
+ goto fail_free_chan;
+
+ /* 1: M-mode, 0: S-mode */
+ mctl->base_flags.f0_priv_level =
+ resp.f0 & RPMI_BASE_FLAGS_F0_PRIVILEGE ? 1 : 0;
+ /* 1: Supported, 0: Not Supported */
+ mctl->base_flags.f0_ev_notif_en =
+ resp.f0 & RPMI_BASE_FLAGS_F0_EV_NOTIFY ? 1 : 0;
+ /* 1: Supported, 0: Not Supported */
+ mctl->base_flags.f0_msi_en =
+ resp.f0 & RPMI_BASE_FLAGS_F0_MSI_EN ? 1 : 0;
+
+ /* We only use M-mode RPMI context in OpenSBI */
+ if (!mctl->base_flags.f0_priv_level) {
+ ret = SBI_ENODEV;
+ goto fail_free_chan;
+ }
+
+ /*
+ * Continue without platform information string if not
+ * available or if an error is encountered while fetching
+ */
+ rpmi_get_platform_info(mctl);
+
+ return 0;
+
+fail_free_chan:
+ mbox_controller_free_chan(mctl->base_chan);
+fail_remove_controller:
+ mbox_controller_remove(&mctl->controller);
+fail_free_controller:
+ sbi_free(mctl);
+ return ret;
+}
+
+static const struct fdt_match rpmi_shmem_mbox_match[] = {
+ { .compatible = "riscv,rpmi-shmem-mbox" },
+ { },
+};
+
+struct fdt_mailbox fdt_mailbox_rpmi_shmem = {
+ .driver = {
+ .match_table = rpmi_shmem_mbox_match,
+ .init = rpmi_shmem_mbox_init,
+ },
+ .xlate = fdt_mailbox_simple_xlate,
+};
diff --git a/lib/utils/mailbox/objects.mk b/lib/utils/mailbox/objects.mk
index 2135898c..746b0313 100644
--- a/lib/utils/mailbox/objects.mk
+++ b/lib/utils/mailbox/objects.mk
@@ -11,3 +11,8 @@ libsbiutils-objs-$(CONFIG_FDT_MAILBOX) += mailbox/fdt_mailbox.o
libsbiutils-objs-$(CONFIG_FDT_MAILBOX) += mailbox/fdt_mailbox_drivers.carray.o
libsbiutils-objs-$(CONFIG_MAILBOX) += mailbox/mailbox.o
+
+libsbiutils-objs-$(CONFIG_RPMI_MAILBOX) += mailbox/rpmi_mailbox.o
+
+carray-fdt_mailbox_drivers-$(CONFIG_FDT_MAILBOX_RPMI_SHMEM) += fdt_mailbox_rpmi_shmem
+libsbiutils-objs-$(CONFIG_FDT_MAILBOX_RPMI_SHMEM) += mailbox/fdt_mailbox_rpmi_shmem.o
diff --git a/lib/utils/mailbox/rpmi_mailbox.c b/lib/utils/mailbox/rpmi_mailbox.c
new file mode 100644
index 00000000..371c719b
--- /dev/null
+++ b/lib/utils/mailbox/rpmi_mailbox.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <sbi/sbi_error.h>
+#include <sbi_utils/mailbox/mailbox.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+
+int rpmi_xlate_error(enum rpmi_error error)
+{
+ switch(error) {
+ case RPMI_SUCCESS:
+ return SBI_OK;
+ case RPMI_ERR_FAILED:
+ return SBI_EFAIL;
+ case RPMI_ERR_NOTSUPP:
+ return SBI_ENOTSUPP;
+ case RPMI_ERR_INVALID_PARAM:
+ return SBI_EINVAL;
+ case RPMI_ERR_DENIED:
+ return SBI_EDENIED;
+ case RPMI_ERR_INVALID_ADDR:
+ return SBI_EINVALID_ADDR;
+ case RPMI_ERR_ALREADY:
+ return SBI_EALREADY;
+ case RPMI_ERR_EXTENSION:
+ return SBI_EFAIL;
+ case RPMI_ERR_HW_FAULT:
+ return SBI_EIO;
+ case RPMI_ERR_BUSY:
+ return SBI_EFAIL;
+ case RPMI_ERR_INVALID_STATE:
+ return SBI_EINVALID_STATE;
+ case RPMI_ERR_BAD_RANGE:
+ return SBI_EBAD_RANGE;
+ case RPMI_ERR_TIMEOUT:
+ return SBI_ETIMEDOUT;
+ case RPMI_ERR_IO:
+ return SBI_EIO;
+ case RPMI_ERR_NO_DATA:
+ return SBI_EFAIL;
+ default:
+ return SBI_EUNKNOWN;
+ }
+}
+
+int rpmi_normal_request_with_status(
+ struct mbox_chan *chan, u32 service_id,
+ void *req, u32 req_words, u32 req_endian_words,
+ void *resp, u32 resp_words, u32 resp_endian_words)
+{
+ int ret;
+ struct mbox_xfer xfer;
+ struct rpmi_message_args args = { 0 };
+
+ args.type = RPMI_MSG_NORMAL_REQUEST;
+ args.service_id = service_id;
+ args.tx_endian_words = req_endian_words;
+ args.rx_endian_words = resp_endian_words;
+ mbox_xfer_init_txrx(&xfer, &args,
+ req, sizeof(u32) * req_words, RPMI_DEF_TX_TIMEOUT,
+ resp, sizeof(u32) * resp_words, RPMI_DEF_RX_TIMEOUT);
+
+ ret = mbox_chan_xfer(chan, &xfer);
+ if (ret)
+ return ret;
+
+ return rpmi_xlate_error(((u32 *)resp)[0]);
+}
+
+int rpmi_posted_request(
+ struct mbox_chan *chan, u32 service_id,
+ void *req, u32 req_words, u32 req_endian_words)
+{
+ struct mbox_xfer xfer;
+ struct rpmi_message_args args = { 0 };
+
+ args.type = RPMI_MSG_POSTED_REQUEST;
+ args.flags = RPMI_MSG_FLAGS_NO_RX;
+ args.service_id = service_id;
+ args.tx_endian_words = req_endian_words;
+ mbox_xfer_init_tx(&xfer, &args,
+ req, sizeof(u32) * req_words, RPMI_DEF_TX_TIMEOUT);
+
+ return mbox_chan_xfer(chan, &xfer);
+}
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 079bc4fe..233a9a89 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -20,6 +20,9 @@ CONFIG_FDT_IRQCHIP=y
CONFIG_FDT_IRQCHIP_APLIC=y
CONFIG_FDT_IRQCHIP_IMSIC=y
CONFIG_FDT_IRQCHIP_PLIC=y
+CONFIG_FDT_MAILBOX=y
+CONFIG_RPMI_MAILBOX=y
+CONFIG_FDT_MAILBOX_RPMI_SHMEM=y
CONFIG_FDT_REGMAP=y
CONFIG_FDT_REGMAP_SYSCON=y
CONFIG_FDT_RESET=y
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 05/17] lib/utils: reset: Add RPMI System Reset driver
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (3 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 04/17] lib/utils: Add RPMI messaging protocol and shared memory transport support Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 06/17] lib: utils: Add simple FDT based system suspend driver framework Anup Patel
` (12 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Rahul Pathak <rpathak@ventanamicro.com>
Add RPMI based driver for system reset and enable it in the generic
platform defconfig
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mailbox/rpmi_msgprot.h | 27 +++++
lib/utils/reset/Kconfig | 5 +
lib/utils/reset/fdt_reset_rpmi.c | 141 +++++++++++++++++++++++
lib/utils/reset/objects.mk | 3 +
platform/generic/configs/defconfig | 1 +
5 files changed, 177 insertions(+)
create mode 100644 lib/utils/reset/fdt_reset_rpmi.c
diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h
index f9f65447..31c3034b 100644
--- a/include/sbi_utils/mailbox/rpmi_msgprot.h
+++ b/include/sbi_utils/mailbox/rpmi_msgprot.h
@@ -196,6 +196,7 @@ struct rpmi_message_args {
enum rpmi_servicegroup_id {
RPMI_SRVGRP_ID_MIN = 0,
RPMI_SRVGRP_BASE = 0x0001,
+ RPMI_SRVGRP_SYSTEM_RESET = 0x0002,
RPMI_SRVGRP_ID_MAX_COUNT,
/* Reserved range for service groups */
@@ -252,4 +253,30 @@ struct rpmi_base_get_platform_info_resp {
char plat_info[];
};
+/** RPMI System Reset ServiceGroup Service IDs */
+enum rpmi_system_reset_service_id {
+ RPMI_SYSRST_SRV_ENABLE_NOTIFICATION = 0x01,
+ RPMI_SYSRST_SRV_GET_ATTRIBUTES = 0x02,
+ RPMI_SYSRST_SRV_SYSTEM_RESET = 0x03,
+ RPMI_SYSRST_SRV_ID_MAX_COUNT,
+};
+
+/** RPMI System Reset types */
+enum rpmi_sysrst_reset_type {
+ RPMI_SYSRST_TYPE_SHUTDOWN = 0x0,
+ RPMI_SYSRST_TYPE_COLD_REBOOT = 0x1,
+ RPMI_SYSRST_TYPE_WARM_REBOOT = 0x2,
+ RPMI_SYSRST_TYPE_MAX,
+};
+
+#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_POS (1)
+#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_MASK \
+ (1U << RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_POS)
+
+/** Response for system reset attributes */
+struct rpmi_sysrst_get_reset_attributes_resp {
+ s32 status;
+ u32 flags;
+};
+
#endif /* !__RPMI_MSGPROT_H__ */
diff --git a/lib/utils/reset/Kconfig b/lib/utils/reset/Kconfig
index 6c077fe7..68e66716 100644
--- a/lib/utils/reset/Kconfig
+++ b/lib/utils/reset/Kconfig
@@ -24,6 +24,11 @@ config FDT_RESET_HTIF
select SYS_HTIF
default n
+config FDT_RESET_RPMI
+ bool "RPMI FDT reset driver"
+ depends on FDT_MAILBOX && RPMI_MAILBOX
+ default n
+
config FDT_RESET_SG2042_HWMON_MCU
bool "Sophgo SG2042 hwmon MCU FDT reset driver"
default n
diff --git a/lib/utils/reset/fdt_reset_rpmi.c b/lib/utils/reset/fdt_reset_rpmi.c
new file mode 100644
index 00000000..1ec4396b
--- /dev/null
+++ b/lib/utils/reset/fdt_reset_rpmi.c
@@ -0,0 +1,141 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Rahul Pathak <rpathak@ventanamicro.com>
+ */
+
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_system.h>
+#include <sbi/sbi_console.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/reset/fdt_reset.h>
+#include <sbi_utils/mailbox/fdt_mailbox.h>
+#include <sbi_utils/mailbox/rpmi_msgprot.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+
+/* struct rpmi_sysreset: RPMI System Reset Context */
+struct rpmi_sysreset {
+ int warm_reset_support;
+ struct mbox_chan *chan;
+};
+
+static struct rpmi_sysreset sysreset_ctx;
+
+static int rpmi_system_reset_type_check(u32 reset_type)
+{
+ int ret;
+ struct rpmi_sysrst_get_reset_attributes_resp resp;
+
+ ret = rpmi_normal_request_with_status(sysreset_ctx.chan,
+ RPMI_SYSRST_SRV_GET_ATTRIBUTES, &reset_type,
+ rpmi_u32_count(reset_type), rpmi_u32_count(reset_type),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (ret) {
+ return 0;
+ }
+
+ return (resp.flags & RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE_MASK) ? 1 : 0;
+}
+
+/**
+ * rpmi_do_system_reset: Do system reset
+ *
+ * @reset_type: RPMI System Reset Type
+ */
+static void rpmi_do_system_reset(u32 reset_type)
+{
+ int ret;
+
+ ret = rpmi_posted_request(sysreset_ctx.chan,
+ RPMI_SYSRST_SRV_SYSTEM_RESET,
+ &reset_type, rpmi_u32_count(reset_type),
+ rpmi_u32_count(reset_type));
+ if (ret)
+ sbi_printf("system reset failed [type: %d]: ret: %d\n",
+ reset_type, ret);
+}
+
+/**
+ * rpmi_system_reset_check: Check the support for
+ * various reset types
+ *
+ * @type: SBI System Reset Type
+ * @reason: Reason for system reset
+ */
+static int rpmi_system_reset_check(u32 type, u32 reason)
+{
+ switch (type) {
+ case SBI_SRST_RESET_TYPE_SHUTDOWN:
+ case SBI_SRST_RESET_TYPE_COLD_REBOOT:
+ return 1;
+ case SBI_SRST_RESET_TYPE_WARM_REBOOT:
+ return sysreset_ctx.warm_reset_support;
+ default:
+ return 0;
+ }
+}
+
+static void rpmi_system_reset(u32 type, u32 reason)
+{
+ u32 reset_type;
+
+ switch (type) {
+ case SBI_SRST_RESET_TYPE_SHUTDOWN:
+ reset_type = RPMI_SYSRST_TYPE_SHUTDOWN;
+ break;
+ case SBI_SRST_RESET_TYPE_COLD_REBOOT:
+ reset_type = RPMI_SYSRST_TYPE_COLD_REBOOT;
+ break;
+ case SBI_SRST_RESET_TYPE_WARM_REBOOT:
+ reset_type = RPMI_SYSRST_TYPE_WARM_REBOOT;
+ break;
+ default:
+ return;
+ }
+
+ rpmi_do_system_reset(reset_type);
+}
+
+static struct sbi_system_reset_device rpmi_reset_dev = {
+ .name = "rpmi-system-reset",
+ .system_reset_check = rpmi_system_reset_check,
+ .system_reset = rpmi_system_reset,
+};
+
+static int rpmi_reset_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ int ret;
+
+ /* If channel already available then do nothing. */
+ if (sysreset_ctx.chan)
+ return 0;
+
+ /*
+ * If channel request failed then other end does not support
+ * system reset group so do nothing.
+ */
+ ret = fdt_mailbox_request_chan(fdt, nodeoff, 0, &sysreset_ctx.chan);
+ if (ret)
+ return SBI_ENODEV;
+
+ sysreset_ctx.warm_reset_support =
+ rpmi_system_reset_type_check(RPMI_SYSRST_TYPE_WARM_REBOOT);
+
+ sbi_system_reset_add_device(&rpmi_reset_dev);
+
+ return SBI_OK;
+}
+
+static const struct fdt_match rpmi_reset_match[] = {
+ { .compatible = "riscv,rpmi-system-reset" },
+ {},
+};
+
+struct fdt_driver fdt_reset_rpmi = {
+ .match_table = rpmi_reset_match,
+ .init = rpmi_reset_init,
+};
diff --git a/lib/utils/reset/objects.mk b/lib/utils/reset/objects.mk
index a84336cf..8f3774c5 100644
--- a/lib/utils/reset/objects.mk
+++ b/lib/utils/reset/objects.mk
@@ -29,3 +29,6 @@ libsbiutils-objs-$(CONFIG_FDT_RESET_SUNXI_WDT) += reset/fdt_reset_sunxi_wdt.o
carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SYSCON) += fdt_syscon_poweroff
carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SYSCON) += fdt_syscon_reboot
libsbiutils-objs-$(CONFIG_FDT_RESET_SYSCON) += reset/fdt_reset_syscon.o
+
+carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_RPMI) += fdt_reset_rpmi
+libsbiutils-objs-$(CONFIG_FDT_RESET_RPMI) += reset/fdt_reset_rpmi.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 233a9a89..48f8df4c 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -29,6 +29,7 @@ CONFIG_FDT_RESET=y
CONFIG_FDT_RESET_ATCWDT200=y
CONFIG_FDT_RESET_GPIO=y
CONFIG_FDT_RESET_HTIF=y
+CONFIG_FDT_RESET_RPMI=y
CONFIG_FDT_RESET_SUNXI_WDT=y
CONFIG_FDT_RESET_SG2042_HWMON_MCU=y
CONFIG_FDT_RESET_SYSCON=y
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 06/17] lib: utils: Add simple FDT based system suspend driver framework
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (4 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 05/17] lib/utils: reset: Add RPMI System Reset driver Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 07/17] lib: utils/suspend: Add RPMI system suspend driver Anup Patel
` (11 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
The generic platform can have multiple system suspend drivers so add a
simple FDT based system suspend driver framework.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/suspend/fdt_suspend.h | 26 ++++++++++++++++++++
lib/utils/Kconfig | 2 ++
lib/utils/suspend/Kconfig | 10 ++++++++
lib/utils/suspend/fdt_suspend.c | 22 +++++++++++++++++
lib/utils/suspend/fdt_suspend_drivers.carray | 3 +++
lib/utils/suspend/objects.mk | 11 +++++++++
platform/generic/configs/defconfig | 1 +
platform/generic/platform.c | 2 ++
8 files changed, 77 insertions(+)
create mode 100644 include/sbi_utils/suspend/fdt_suspend.h
create mode 100644 lib/utils/suspend/Kconfig
create mode 100644 lib/utils/suspend/fdt_suspend.c
create mode 100644 lib/utils/suspend/fdt_suspend_drivers.carray
create mode 100644 lib/utils/suspend/objects.mk
diff --git a/include/sbi_utils/suspend/fdt_suspend.h b/include/sbi_utils/suspend/fdt_suspend.h
new file mode 100644
index 00000000..bfc6c69a
--- /dev/null
+++ b/include/sbi_utils/suspend/fdt_suspend.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#ifndef __FDT_SUSPEND_H__
+#define __FDT_SUSPEND_H__
+
+#include <sbi/sbi_types.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+#ifdef CONFIG_FDT_SUSPEND
+
+void fdt_suspend_init(const void *fdt);
+
+#else
+
+static inline void fdt_suspend_init(const void *fdt) { }
+
+#endif
+
+#endif
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig
index 6aa7843c..3f32c1ca 100644
--- a/lib/utils/Kconfig
+++ b/lib/utils/Kconfig
@@ -22,6 +22,8 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/reset/Kconfig"
source "$(OPENSBI_SRC_DIR)/lib/utils/serial/Kconfig"
+source "$(OPENSBI_SRC_DIR)/lib/utils/suspend/Kconfig"
+
source "$(OPENSBI_SRC_DIR)/lib/utils/sys/Kconfig"
source "$(OPENSBI_SRC_DIR)/lib/utils/timer/Kconfig"
diff --git a/lib/utils/suspend/Kconfig b/lib/utils/suspend/Kconfig
new file mode 100644
index 00000000..416ae795
--- /dev/null
+++ b/lib/utils/suspend/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+menu "System Suspend Support"
+
+config FDT_SUSPEND
+ bool "FDT based suspend drivers"
+ depends on FDT
+ default n
+
+endmenu
diff --git a/lib/utils/suspend/fdt_suspend.c b/lib/utils/suspend/fdt_suspend.c
new file mode 100644
index 00000000..bd4691a0
--- /dev/null
+++ b/lib/utils/suspend/fdt_suspend.c
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <sbi_utils/suspend/fdt_suspend.h>
+
+/* List of FDT suspend drivers generated at compile time */
+extern const struct fdt_driver *const fdt_suspend_drivers[];
+
+void fdt_suspend_init(const void *fdt)
+{
+ /*
+ * Platforms might have multiple system suspend devices or
+ * might not have any so probe all and don't fail.
+ */
+ fdt_driver_init_all(fdt, fdt_suspend_drivers);
+}
diff --git a/lib/utils/suspend/fdt_suspend_drivers.carray b/lib/utils/suspend/fdt_suspend_drivers.carray
new file mode 100644
index 00000000..a0c857fc
--- /dev/null
+++ b/lib/utils/suspend/fdt_suspend_drivers.carray
@@ -0,0 +1,3 @@
+HEADER: sbi_utils/suspend/fdt_suspend.h
+TYPE: const struct fdt_driver
+NAME: fdt_suspend_drivers
diff --git a/lib/utils/suspend/objects.mk b/lib/utils/suspend/objects.mk
new file mode 100644
index 00000000..30d897d1
--- /dev/null
+++ b/lib/utils/suspend/objects.mk
@@ -0,0 +1,11 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 Ventana Micro Systems Inc.
+#
+# Authors:
+# Anup Patel <apatel@ventanamicro.com>
+#
+
+libsbiutils-objs-$(CONFIG_FDT_SUSPEND) += suspend/fdt_suspend.o
+libsbiutils-objs-$(CONFIG_FDT_SUSPEND) += suspend/fdt_suspend_drivers.carray.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 48f8df4c..ec439d74 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -44,6 +44,7 @@ CONFIG_FDT_SERIAL_LITEX=y
CONFIG_FDT_SERIAL_UART8250=y
CONFIG_FDT_SERIAL_XILINX_UARTLITE=y
CONFIG_SERIAL_SEMIHOSTING=y
+CONFIG_FDT_SUSPEND=y
CONFIG_FDT_TIMER=y
CONFIG_FDT_TIMER_MTIMER=y
CONFIG_FDT_TIMER_PLMT=y
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index fb074d4b..30da839f 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -24,6 +24,7 @@
#include <sbi_utils/irqchip/fdt_irqchip.h>
#include <sbi_utils/irqchip/imsic.h>
#include <sbi_utils/serial/fdt_serial.h>
+#include <sbi_utils/suspend/fdt_suspend.h>
#include <sbi_utils/timer/fdt_timer.h>
#include <sbi_utils/ipi/fdt_ipi.h>
#include <sbi_utils/reset/fdt_reset.h>
@@ -247,6 +248,7 @@ static int generic_early_init(bool cold_boot)
if (cold_boot) {
fdt_reset_init(fdt);
+ fdt_suspend_init(fdt);
if (semihosting_enabled())
rc = semihosting_init();
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 07/17] lib: utils/suspend: Add RPMI system suspend driver
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (5 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 06/17] lib: utils: Add simple FDT based system suspend driver framework Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 08/17] lib: sbi: Add optional resume address to hart suspend Anup Patel
` (10 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Add RPMI based system suspend driver.
To test this, execute the follwoing in Linux:
$ echo mem > /sys/power/state
To wake up, execute the following command on qemu monitor terminal:
(qemu) system_wakeup
Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mailbox/rpmi_msgprot.h | 35 ++++++
lib/utils/suspend/Kconfig | 9 ++
lib/utils/suspend/fdt_suspend_rpmi.c | 138 +++++++++++++++++++++++
lib/utils/suspend/objects.mk | 3 +
platform/generic/configs/defconfig | 1 +
5 files changed, 186 insertions(+)
create mode 100644 lib/utils/suspend/fdt_suspend_rpmi.c
diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h
index 31c3034b..4de86adf 100644
--- a/include/sbi_utils/mailbox/rpmi_msgprot.h
+++ b/include/sbi_utils/mailbox/rpmi_msgprot.h
@@ -5,6 +5,7 @@
*
* Authors:
* Rahul Pathak <rpathak@ventanamicro.com>
+ * Subrahmanya Lingappa <slingappa@ventanamicro.com>
*/
#ifndef __RPMI_MSGPROT_H__
@@ -197,6 +198,7 @@ enum rpmi_servicegroup_id {
RPMI_SRVGRP_ID_MIN = 0,
RPMI_SRVGRP_BASE = 0x0001,
RPMI_SRVGRP_SYSTEM_RESET = 0x0002,
+ RPMI_SRVGRP_SYSTEM_SUSPEND = 0x0003,
RPMI_SRVGRP_ID_MAX_COUNT,
/* Reserved range for service groups */
@@ -279,4 +281,37 @@ struct rpmi_sysrst_get_reset_attributes_resp {
u32 flags;
};
+/** RPMI System Suspend ServiceGroup Service IDs */
+enum rpmi_system_suspend_service_id {
+ RPMI_SYSSUSP_SRV_ENABLE_NOTIFICATION = 0x01,
+ RPMI_SYSSUSP_SRV_GET_ATTRIBUTES = 0x02,
+ RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND = 0x03,
+ RPMI_SYSSUSP_SRV_ID_MAX_COUNT,
+};
+
+/** Request for system suspend attributes */
+struct rpmi_syssusp_get_attr_req {
+ u32 susp_type;
+};
+
+#define RPMI_SYSSUSP_ATTRS_FLAGS_RESUMEADDR (1U << 1)
+#define RPMI_SYSSUSP_ATTRS_FLAGS_SUSPENDTYPE 1U
+
+/** Response for system suspend attributes */
+struct rpmi_syssusp_get_attr_resp {
+ s32 status;
+ u32 flags;
+};
+
+struct rpmi_syssusp_suspend_req {
+ u32 hartid;
+ u32 suspend_type;
+ u32 resume_addr_lo;
+ u32 resume_addr_hi;
+};
+
+struct rpmi_syssusp_suspend_resp {
+ s32 status;
+};
+
#endif /* !__RPMI_MSGPROT_H__ */
diff --git a/lib/utils/suspend/Kconfig b/lib/utils/suspend/Kconfig
index 416ae795..2cbea75c 100644
--- a/lib/utils/suspend/Kconfig
+++ b/lib/utils/suspend/Kconfig
@@ -7,4 +7,13 @@ config FDT_SUSPEND
depends on FDT
default n
+if FDT_SUSPEND
+
+config FDT_SUSPEND_RPMI
+ bool "FDT RPMI suspend driver"
+ depends on FDT_MAILBOX && RPMI_MAILBOX
+ default n
+
+endif
+
endmenu
diff --git a/lib/utils/suspend/fdt_suspend_rpmi.c b/lib/utils/suspend/fdt_suspend_rpmi.c
new file mode 100644
index 00000000..11696648
--- /dev/null
+++ b/lib/utils/suspend/fdt_suspend_rpmi.c
@@ -0,0 +1,138 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Subrahmanya Lingappa <slingappa@ventanamicro.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_system.h>
+#include <sbi/riscv_asm.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/mailbox/fdt_mailbox.h>
+#include <sbi_utils/mailbox/mailbox.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+#include <sbi_utils/suspend/fdt_suspend.h>
+
+struct rpmi_syssusp {
+ struct mbox_chan *chan;
+ bool cust_res_addr_supported;
+ bool suspend_supported;
+};
+
+static struct rpmi_syssusp syssusp_ctx;
+
+static int rpmi_syssusp_attrs(uint32_t *attrs)
+{
+ int rc;
+ struct rpmi_syssusp_get_attr_resp resp;
+ struct rpmi_syssusp_get_attr_req req;
+
+ req.susp_type = SBI_SUSP_SLEEP_TYPE_SUSPEND;
+
+ rc = rpmi_normal_request_with_status(
+ syssusp_ctx.chan, RPMI_SYSSUSP_SRV_GET_ATTRIBUTES,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ *attrs = resp.flags;
+
+ return 0;
+}
+
+static int rpmi_syssusp(uint32_t suspend_type, ulong resume_addr)
+{
+ int rc;
+ struct rpmi_syssusp_suspend_req req;
+ struct rpmi_syssusp_suspend_resp resp;
+
+ req.hartid = current_hartid();
+ req.suspend_type = suspend_type;
+ req.resume_addr_lo = resume_addr;
+ req.resume_addr_hi = (u64)resume_addr >> 32;
+
+ rc = rpmi_normal_request_with_status(
+ syssusp_ctx.chan, RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ /* Wait for interrupt */
+ wfi();
+
+ return 0;
+}
+
+static int rpmi_system_suspend_check(u32 sleep_type)
+{
+ return ((sleep_type == SBI_SUSP_SLEEP_TYPE_SUSPEND) &&
+ syssusp_ctx.suspend_supported) ? 0 : SBI_EINVAL;
+}
+
+static int rpmi_system_suspend(u32 sleep_type, ulong resume_addr)
+{
+ int rc;
+
+ if (sleep_type != SBI_SUSP_SLEEP_TYPE_SUSPEND)
+ return SBI_ENOTSUPP;
+
+ rc = rpmi_syssusp(sleep_type, resume_addr);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static struct sbi_system_suspend_device rpmi_suspend_dev = {
+ .name = "rpmi-system-suspend",
+ .system_suspend_check = rpmi_system_suspend_check,
+ .system_suspend = rpmi_system_suspend,
+};
+
+static int rpmi_suspend_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ int rc;
+ uint32_t attrs = 0;
+
+ /* If channel already available then do nothing. */
+ if (syssusp_ctx.chan)
+ return 0;
+
+ /*
+ * If channel request failed then other end does not support
+ * suspend service group so do nothing.
+ */
+ rc = fdt_mailbox_request_chan(fdt, nodeoff, 0, &syssusp_ctx.chan);
+ if (rc)
+ return SBI_ENODEV;
+
+ /* Get suspend attributes */
+ rc = rpmi_syssusp_attrs(&attrs);
+ if (rc)
+ return rc;
+
+ syssusp_ctx.suspend_supported =
+ attrs & RPMI_SYSSUSP_ATTRS_FLAGS_SUSPENDTYPE;
+ syssusp_ctx.cust_res_addr_supported =
+ attrs & RPMI_SYSSUSP_ATTRS_FLAGS_RESUMEADDR;
+
+ sbi_system_suspend_set_device(&rpmi_suspend_dev);
+
+ return 0;
+}
+
+static const struct fdt_match rpmi_suspend_match[] = {
+ { .compatible = "riscv,rpmi-system-suspend" },
+ {},
+};
+
+struct fdt_driver fdt_suspend_rpmi = {
+ .match_table = rpmi_suspend_match,
+ .init = rpmi_suspend_init,
+};
diff --git a/lib/utils/suspend/objects.mk b/lib/utils/suspend/objects.mk
index 30d897d1..657670a8 100644
--- a/lib/utils/suspend/objects.mk
+++ b/lib/utils/suspend/objects.mk
@@ -9,3 +9,6 @@
libsbiutils-objs-$(CONFIG_FDT_SUSPEND) += suspend/fdt_suspend.o
libsbiutils-objs-$(CONFIG_FDT_SUSPEND) += suspend/fdt_suspend_drivers.carray.o
+
+carray-fdt_suspend_drivers-$(CONFIG_FDT_SUSPEND_RPMI) += fdt_suspend_rpmi
+libsbiutils-objs-$(CONFIG_FDT_SUSPEND_RPMI) += suspend/fdt_suspend_rpmi.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index ec439d74..54300fb5 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -45,6 +45,7 @@ CONFIG_FDT_SERIAL_UART8250=y
CONFIG_FDT_SERIAL_XILINX_UARTLITE=y
CONFIG_SERIAL_SEMIHOSTING=y
CONFIG_FDT_SUSPEND=y
+CONFIG_FDT_SUSPEND_RPMI=y
CONFIG_FDT_TIMER=y
CONFIG_FDT_TIMER_MTIMER=y
CONFIG_FDT_TIMER_PLMT=y
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 08/17] lib: sbi: Add optional resume address to hart suspend
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (6 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 07/17] lib: utils/suspend: Add RPMI system suspend driver Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 09/17] lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks Anup Patel
` (9 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Add an optional resume address to the platform specific hart suspend call.
Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi/sbi_hsm.h | 6 +++++-
lib/sbi/sbi_hsm.c | 6 +++---
platform/generic/allwinner/sun20i-d1.c | 2 +-
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/include/sbi/sbi_hsm.h b/include/sbi/sbi_hsm.h
index ae098f45..38f90516 100644
--- a/include/sbi/sbi_hsm.h
+++ b/include/sbi/sbi_hsm.h
@@ -40,8 +40,12 @@ struct sbi_hsm_device {
*
* For successful non-retentive suspend, the hart will resume from
* the warm boot entry point.
+ *
+ * NOTE: mmode_resume_addr(resume address) is optional hence it
+ * may or may not be honored by the platform. If its not honored
+ * then platform must ensure to resume from the warmboot address.
*/
- int (*hart_suspend)(u32 suspend_type);
+ int (*hart_suspend)(u32 suspend_type, ulong mmode_resume_addr);
/**
* Perform platform-specific actions to resume from a suspended state.
diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
index a3d6947a..cf0eb84b 100644
--- a/lib/sbi/sbi_hsm.c
+++ b/lib/sbi/sbi_hsm.c
@@ -223,10 +223,10 @@ static int hsm_device_hart_stop(void)
return SBI_ENOTSUPP;
}
-static int hsm_device_hart_suspend(u32 suspend_type)
+static int hsm_device_hart_suspend(u32 suspend_type, ulong mmode_resume_addr)
{
if (hsm_dev && hsm_dev->hart_suspend)
- return hsm_dev->hart_suspend(suspend_type);
+ return hsm_dev->hart_suspend(suspend_type, mmode_resume_addr);
return SBI_ENOTSUPP;
}
@@ -532,7 +532,7 @@ int sbi_hsm_hart_suspend(struct sbi_scratch *scratch, u32 suspend_type,
__sbi_hsm_suspend_non_ret_save(scratch);
/* Try platform specific suspend */
- ret = hsm_device_hart_suspend(suspend_type);
+ ret = hsm_device_hart_suspend(suspend_type, scratch->warmboot_addr);
if (ret == SBI_ENOTSUPP) {
/* Try generic implementation of default suspend types */
if (suspend_type == SBI_HSM_SUSPEND_RET_DEFAULT ||
diff --git a/platform/generic/allwinner/sun20i-d1.c b/platform/generic/allwinner/sun20i-d1.c
index b65013c2..c31ebdb2 100644
--- a/platform/generic/allwinner/sun20i-d1.c
+++ b/platform/generic/allwinner/sun20i-d1.c
@@ -130,7 +130,7 @@ static void sun20i_d1_riscv_cfg_init(void)
writel_relaxed(entry >> 32, SUN20I_D1_RISCV_CFG_BASE + RESET_ENTRY_HI_REG);
}
-static int sun20i_d1_hart_suspend(u32 suspend_type)
+static int sun20i_d1_hart_suspend(u32 suspend_type, ulong mmode_resume_addr)
{
/* Use the generic code for retentive suspend. */
if (!(suspend_type & SBI_HSM_SUSP_NON_RET_BIT))
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 09/17] lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (7 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 08/17] lib: sbi: Add optional resume address to hart suspend Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 10/17] lib: utils: Add simple FDT based HSM driver framework Anup Patel
` (8 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
It should possible to fixup FDT from any part of OpenSBI so add
fdt_register_general_fixup() which allows dynamic registration of
FDT fixup callbacks.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/fdt/fdt_fixup.h | 15 ++++++++++++++
lib/utils/fdt/fdt_fixup.c | 33 +++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/include/sbi_utils/fdt/fdt_fixup.h b/include/sbi_utils/fdt/fdt_fixup.h
index 21a53011..93249968 100644
--- a/include/sbi_utils/fdt/fdt_fixup.h
+++ b/include/sbi_utils/fdt/fdt_fixup.h
@@ -9,6 +9,8 @@
#ifndef __FDT_FIXUP_H__
#define __FDT_FIXUP_H__
+#include <sbi/sbi_list.h>
+
struct sbi_cpu_idle_state {
const char *name;
uint32_t suspend_param;
@@ -93,6 +95,19 @@ void fdt_plic_fixup(void *fdt);
*/
int fdt_reserved_memory_fixup(void *fdt);
+/** Representation of a general fixup */
+struct fdt_general_fixup {
+ struct sbi_dlist head;
+ const char *name;
+ void (*do_fixup)(struct fdt_general_fixup *f, void *fdt);
+};
+
+/** Register a general fixup */
+int fdt_register_general_fixup(struct fdt_general_fixup *fixup);
+
+/** UnRegister a general fixup */
+void fdt_unregister_general_fixup(struct fdt_general_fixup *fixup);
+
/**
* General device tree fix-up
*
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
index 9e013dfa..192d6dd5 100644
--- a/lib/utils/fdt/fdt_fixup.c
+++ b/lib/utils/fdt/fdt_fixup.c
@@ -401,8 +401,38 @@ void fdt_config_fixup(void *fdt)
fdt_nop_node(fdt, config_offset);
}
+static SBI_LIST_HEAD(fixup_list);
+
+int fdt_register_general_fixup(struct fdt_general_fixup *fixup)
+{
+ struct fdt_general_fixup *f;
+
+ if (!fixup || !fixup->name || !fixup->do_fixup)
+ return SBI_EINVAL;
+
+ sbi_list_for_each_entry(f, &fixup_list, head) {
+ if (f == fixup)
+ return SBI_EALREADY;
+ }
+
+ SBI_INIT_LIST_HEAD(&fixup->head);
+ sbi_list_add_tail(&fixup->head, &fixup_list);
+
+ return 0;
+}
+
+void fdt_unregister_general_fixup(struct fdt_general_fixup *fixup)
+{
+ if (!fixup)
+ return;
+
+ sbi_list_del(&fixup->head);
+}
+
void fdt_fixups(void *fdt)
{
+ struct fdt_general_fixup *f;
+
fdt_aplic_fixup(fdt);
fdt_imsic_fixup(fdt);
@@ -416,4 +446,7 @@ void fdt_fixups(void *fdt)
#endif
fdt_config_fixup(fdt);
+
+ sbi_list_for_each_entry(f, &fixup_list, head)
+ f->do_fixup(f, fdt);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 10/17] lib: utils: Add simple FDT based HSM driver framework
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (8 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 09/17] lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 11/17] lib: utils/hsm: Add RPMI HSM driver Anup Patel
` (7 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
The generic platform can have multiple HSM drivers so add a simple
FDT based HSM driver framework.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/hsm/fdt_hsm.h | 26 ++++++++++++++++++++++++++
lib/utils/Kconfig | 2 ++
lib/utils/hsm/Kconfig | 10 ++++++++++
lib/utils/hsm/fdt_hsm.c | 22 ++++++++++++++++++++++
lib/utils/hsm/fdt_hsm_drivers.carray | 3 +++
lib/utils/hsm/objects.mk | 11 +++++++++++
platform/generic/configs/defconfig | 1 +
platform/generic/platform.c | 2 ++
8 files changed, 77 insertions(+)
create mode 100644 include/sbi_utils/hsm/fdt_hsm.h
create mode 100644 lib/utils/hsm/Kconfig
create mode 100644 lib/utils/hsm/fdt_hsm.c
create mode 100644 lib/utils/hsm/fdt_hsm_drivers.carray
create mode 100644 lib/utils/hsm/objects.mk
diff --git a/include/sbi_utils/hsm/fdt_hsm.h b/include/sbi_utils/hsm/fdt_hsm.h
new file mode 100644
index 00000000..58061afc
--- /dev/null
+++ b/include/sbi_utils/hsm/fdt_hsm.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#ifndef __FDT_HSM_H__
+#define __FDT_HSM_H__
+
+#include <sbi/sbi_types.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+#ifdef CONFIG_FDT_HSM
+
+void fdt_hsm_init(const void *fdt);
+
+#else
+
+static inline void fdt_hsm_init(const void *fdt) { }
+
+#endif
+
+#endif
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig
index 3f32c1ca..c860a185 100644
--- a/lib/utils/Kconfig
+++ b/lib/utils/Kconfig
@@ -6,6 +6,8 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/fdt/Kconfig"
source "$(OPENSBI_SRC_DIR)/lib/utils/gpio/Kconfig"
+source "$(OPENSBI_SRC_DIR)/lib/utils/hsm/Kconfig"
+
source "$(OPENSBI_SRC_DIR)/lib/utils/i2c/Kconfig"
source "$(OPENSBI_SRC_DIR)/lib/utils/ipi/Kconfig"
diff --git a/lib/utils/hsm/Kconfig b/lib/utils/hsm/Kconfig
new file mode 100644
index 00000000..31506116
--- /dev/null
+++ b/lib/utils/hsm/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+menu "HSM Device Support"
+
+config FDT_HSM
+ bool "FDT based HSM drivers"
+ depends on FDT
+ default n
+
+endmenu
diff --git a/lib/utils/hsm/fdt_hsm.c b/lib/utils/hsm/fdt_hsm.c
new file mode 100644
index 00000000..162b9867
--- /dev/null
+++ b/lib/utils/hsm/fdt_hsm.c
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <sbi_utils/hsm/fdt_hsm.h>
+
+/* List of FDT HSM drivers generated at compile time */
+extern const struct fdt_driver *const fdt_hsm_drivers[];
+
+void fdt_hsm_init(const void *fdt)
+{
+ /*
+ * Platforms might have multiple HSM devices or might
+ * not have any so probe all and don't fail.
+ */
+ fdt_driver_init_all(fdt, fdt_hsm_drivers);
+}
diff --git a/lib/utils/hsm/fdt_hsm_drivers.carray b/lib/utils/hsm/fdt_hsm_drivers.carray
new file mode 100644
index 00000000..73680a25
--- /dev/null
+++ b/lib/utils/hsm/fdt_hsm_drivers.carray
@@ -0,0 +1,3 @@
+HEADER: sbi_utils/hsm/fdt_hsm.h
+TYPE: const struct fdt_driver
+NAME: fdt_hsm_drivers
diff --git a/lib/utils/hsm/objects.mk b/lib/utils/hsm/objects.mk
new file mode 100644
index 00000000..49337bf5
--- /dev/null
+++ b/lib/utils/hsm/objects.mk
@@ -0,0 +1,11 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 Ventana Micro Systems Inc.
+#
+# Authors:
+# Anup Patel <apatel@ventanamicro.com>
+#
+
+libsbiutils-objs-$(CONFIG_FDT_HSM) += hsm/fdt_hsm.o
+libsbiutils-objs-$(CONFIG_FDT_HSM) += hsm/fdt_hsm_drivers.carray.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 54300fb5..2efc7136 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -10,6 +10,7 @@ CONFIG_FDT_GPIO=y
CONFIG_FDT_GPIO_DESIGNWARE=y
CONFIG_FDT_GPIO_SIFIVE=y
CONFIG_FDT_GPIO_STARFIVE=y
+CONFIG_FDT_HSM=y
CONFIG_FDT_I2C=y
CONFIG_FDT_I2C_SIFIVE=y
CONFIG_FDT_I2C_DW=y
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index 30da839f..48228e67 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -21,6 +21,7 @@
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/fdt/fdt_pmu.h>
+#include <sbi_utils/hsm/fdt_hsm.h>
#include <sbi_utils/irqchip/fdt_irqchip.h>
#include <sbi_utils/irqchip/imsic.h>
#include <sbi_utils/serial/fdt_serial.h>
@@ -249,6 +250,7 @@ static int generic_early_init(bool cold_boot)
if (cold_boot) {
fdt_reset_init(fdt);
fdt_suspend_init(fdt);
+ fdt_hsm_init(fdt);
if (semihosting_enabled())
rc = semihosting_init();
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 11/17] lib: utils/hsm: Add RPMI HSM driver
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (9 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 10/17] lib: utils: Add simple FDT based HSM driver framework Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 12/17] lib: utils: Add simple FDT based CPPC driver framework Anup Patel
` (6 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Subrahmanya Lingappa <slingappa@ventanamicro.com>
The RPMI HSM service group provides set of routine to query and control
power states of a Hart. Add RPMI based Hart State Management (HSM) driver.
Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mailbox/rpmi_msgprot.h | 92 ++++++
lib/utils/hsm/Kconfig | 9 +
lib/utils/hsm/fdt_hsm_rpmi.c | 362 +++++++++++++++++++++++
lib/utils/hsm/objects.mk | 3 +
platform/generic/configs/defconfig | 1 +
5 files changed, 467 insertions(+)
create mode 100644 lib/utils/hsm/fdt_hsm_rpmi.c
diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h
index 4de86adf..8e2b23e2 100644
--- a/include/sbi_utils/mailbox/rpmi_msgprot.h
+++ b/include/sbi_utils/mailbox/rpmi_msgprot.h
@@ -199,6 +199,7 @@ enum rpmi_servicegroup_id {
RPMI_SRVGRP_BASE = 0x0001,
RPMI_SRVGRP_SYSTEM_RESET = 0x0002,
RPMI_SRVGRP_SYSTEM_SUSPEND = 0x0003,
+ RPMI_SRVGRP_HSM = 0x0004,
RPMI_SRVGRP_ID_MAX_COUNT,
/* Reserved range for service groups */
@@ -314,4 +315,95 @@ struct rpmi_syssusp_suspend_resp {
s32 status;
};
+/** RPMI HSM State Management ServiceGroup Service IDs */
+enum rpmi_hsm_service_id {
+ RPMI_HSM_SRV_ENABLE_NOTIFICATION = 0x01,
+ RPMI_HSM_SRV_GET_HART_STATUS = 0x02,
+ RPMI_HSM_SRV_GET_HART_LIST = 0x03,
+ RPMI_HSM_SRV_GET_SUSPEND_TYPES = 0x04,
+ RPMI_HSM_SRV_GET_SUSPEND_INFO = 0x05,
+ RPMI_HSM_SRV_HART_START = 0x06,
+ RPMI_HSM_SRV_HART_STOP = 0x07,
+ RPMI_HSM_SRV_HART_SUSPEND = 0x08,
+ RPMI_HSM_SRV_ID_MAX = 0x09,
+};
+
+/* HSM service group request and response structs */
+struct rpmi_hsm_hart_start_req {
+ u32 hartid;
+ u32 start_addr_lo;
+ u32 start_addr_hi;
+};
+
+struct rpmi_hsm_hart_start_resp {
+ s32 status;
+};
+
+struct rpmi_hsm_hart_stop_req {
+ u32 hartid;
+};
+
+struct rpmi_hsm_hart_stop_resp {
+ s32 status;
+};
+
+struct rpmi_hsm_hart_susp_req {
+ u32 hartid;
+ u32 suspend_type;
+ u32 resume_addr_lo;
+ u32 resume_addr_hi;
+};
+
+struct rpmi_hsm_hart_susp_resp {
+ s32 status;
+};
+
+struct rpmi_hsm_get_hart_status_req {
+ u32 hartid;
+};
+
+struct rpmi_hsm_get_hart_status_resp {
+ s32 status;
+ u32 hart_status;
+};
+
+struct rpmi_hsm_get_hart_list_req {
+ u32 start_index;
+};
+
+struct rpmi_hsm_get_hart_list_resp {
+ s32 status;
+ u32 remaining;
+ u32 returned;
+ /* remaining space need to be adjusted for the above 3 u32's */
+ u32 hartid[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)];
+};
+
+struct rpmi_hsm_get_susp_types_req {
+ u32 start_index;
+};
+
+struct rpmi_hsm_get_susp_types_resp {
+ s32 status;
+ u32 remaining;
+ u32 returned;
+ /* remaining space need to be adjusted for the above 3 u32's */
+ u32 types[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)];
+};
+
+struct rpmi_hsm_get_susp_info_req {
+ u32 suspend_type;
+};
+
+#define RPMI_HSM_SUSPEND_INFO_FLAGS_TIMER_STOP 1U
+
+struct rpmi_hsm_get_susp_info_resp {
+ s32 status;
+ u32 flags;
+ u32 entry_latency_us;
+ u32 exit_latency_us;
+ u32 wakeup_latency_us;
+ u32 min_residency_us;
+};
+
#endif /* !__RPMI_MSGPROT_H__ */
diff --git a/lib/utils/hsm/Kconfig b/lib/utils/hsm/Kconfig
index 31506116..1ad7958f 100644
--- a/lib/utils/hsm/Kconfig
+++ b/lib/utils/hsm/Kconfig
@@ -7,4 +7,13 @@ config FDT_HSM
depends on FDT
default n
+if FDT_HSM
+
+config FDT_HSM_RPMI
+ bool "FDT RPMI HSM driver"
+ depends on FDT_MAILBOX && RPMI_MAILBOX
+ default n
+
+endif
+
endmenu
diff --git a/lib/utils/hsm/fdt_hsm_rpmi.c b/lib/utils/hsm/fdt_hsm_rpmi.c
new file mode 100644
index 00000000..975d3484
--- /dev/null
+++ b/lib/utils/hsm/fdt_hsm_rpmi.c
@@ -0,0 +1,362 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Subrahmanya Lingappa <slingappa@ventanamicro.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/fdt/fdt_fixup.h>
+#include <sbi_utils/hsm/fdt_hsm.h>
+#include <sbi_utils/mailbox/fdt_mailbox.h>
+#include <sbi_utils/mailbox/mailbox.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+
+#define MAX_HSM_SUPSEND_STATE_NAMELEN 16
+
+struct rpmi_hsm_suspend {
+ u32 num_states;
+ struct sbi_cpu_idle_state *states;
+};
+
+struct rpmi_hsm {
+ struct mbox_chan *chan;
+ struct rpmi_hsm_suspend *susp;
+};
+
+static unsigned long rpmi_hsm_offset;
+
+static struct rpmi_hsm *rpmi_hsm_get_pointer(u32 hartid)
+{
+ struct sbi_scratch *scratch;
+
+ scratch = sbi_hartid_to_scratch(hartid);
+ if (!scratch || !rpmi_hsm_offset)
+ return NULL;
+
+ return sbi_scratch_offset_ptr(scratch, rpmi_hsm_offset);
+}
+
+static int rpmi_hsm_start(u32 hartid, ulong resume_addr)
+{
+ struct rpmi_hsm_hart_start_req req;
+ struct rpmi_hsm_hart_start_resp resp;
+ struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(hartid);
+
+ if (!rpmi)
+ return SBI_ENOSYS;
+
+ req.hartid = hartid;
+ req.start_addr_lo = resume_addr;
+ req.start_addr_hi = (u64)resume_addr >> 32;
+
+ return rpmi_normal_request_with_status(
+ rpmi->chan, RPMI_HSM_SRV_HART_START,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+}
+
+static int rpmi_hsm_stop(void)
+{
+ int rc;
+ struct rpmi_hsm_hart_stop_req req;
+ struct rpmi_hsm_hart_stop_resp resp;
+ void (*jump_warmboot)(void) =
+ (void (*)(void))sbi_scratch_thishart_ptr()->warmboot_addr;
+ struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid());
+
+ if (!rpmi)
+ return SBI_ENOSYS;
+
+ req.hartid = current_hartid();
+
+ rc = rpmi_normal_request_with_status(
+ rpmi->chan, RPMI_HSM_SRV_HART_STOP,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ /* Wait for interrupt */
+ wfi();
+
+ jump_warmboot();
+
+ return 0;
+}
+
+static bool is_rpmi_hsm_susp_supported(struct rpmi_hsm_suspend *susp, u32 type)
+{
+ int i;
+
+ for (i = 0; i < susp->num_states; i++)
+ if (type == susp->states[i].suspend_param)
+ return true;
+
+ return false;
+}
+
+static int rpmi_hsm_suspend(u32 type, ulong resume_addr)
+{
+ int rc;
+ struct rpmi_hsm_hart_susp_req req;
+ struct rpmi_hsm_hart_susp_resp resp;
+ struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid());
+
+ if (!rpmi)
+ return SBI_ENOSYS;
+
+ /* check if harts support this suspend type */
+ if (!is_rpmi_hsm_susp_supported(rpmi->susp, type))
+ return SBI_EINVAL;
+
+ req.hartid = current_hartid();
+ req.suspend_type = type;
+ req.resume_addr_lo = resume_addr;
+ req.resume_addr_hi = (u64)resume_addr >> 32;
+
+ rc = rpmi_normal_request_with_status(
+ rpmi->chan, RPMI_HSM_SRV_HART_SUSPEND,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ /* Wait for interrupt */
+ wfi();
+
+ return 0;
+}
+
+static struct sbi_hsm_device sbi_hsm_rpmi = {
+ .name = "rpmi-hsm",
+ .hart_start = rpmi_hsm_start,
+ .hart_stop = rpmi_hsm_stop,
+ .hart_suspend = rpmi_hsm_suspend,
+};
+
+static void rpmi_hsm_do_fixup(struct fdt_general_fixup *f, void *fdt)
+{
+ struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid());
+
+ if (!rpmi || !rpmi->susp || !rpmi->susp->num_states)
+ return;
+
+ fdt_add_cpu_idle_states(fdt, rpmi->susp->states);
+}
+
+static struct fdt_general_fixup rpmi_hsm_fixup = {
+ .name = "rpmi-hsm-fixup",
+ .do_fixup = rpmi_hsm_do_fixup,
+};
+
+static int rpmi_hsm_get_num_suspend_states(struct mbox_chan *chan,
+ struct rpmi_hsm_suspend *susp)
+{
+ int rc;
+ struct rpmi_hsm_get_susp_types_req req;
+ struct rpmi_hsm_get_susp_types_resp resp;
+
+ req.start_index = 0;
+ rc = rpmi_normal_request_with_status(
+ chan, RPMI_HSM_SRV_GET_SUSPEND_TYPES,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ susp->num_states = resp.returned + resp.remaining;
+ return 0;
+}
+
+static int rpmi_hsm_get_suspend_states(struct mbox_chan *chan,
+ struct rpmi_hsm_suspend *susp)
+{
+ int rc, i, cnt = 0;
+ struct rpmi_hsm_get_susp_types_req req;
+ struct rpmi_hsm_get_susp_types_resp resp;
+ struct rpmi_hsm_get_susp_info_req dreq;
+ struct rpmi_hsm_get_susp_info_resp dresp;
+ struct sbi_cpu_idle_state *state;
+
+ if (!susp->num_states)
+ return 0;
+
+ req.start_index = 0;
+ do {
+ rc = rpmi_normal_request_with_status(
+ chan, RPMI_HSM_SRV_GET_SUSPEND_TYPES,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ for (i = 0; i < resp.returned && cnt < susp->num_states; i++)
+ susp->states[cnt++].suspend_param = resp.types[i];
+ req.start_index = i;
+ } while (resp.remaining);
+
+ for (i = 0; i < susp->num_states; i++) {
+ state = &susp->states[i];
+
+ dreq.suspend_type = state->suspend_param;
+ rc = rpmi_normal_request_with_status(
+ chan, RPMI_HSM_SRV_GET_SUSPEND_INFO,
+ &dreq, rpmi_u32_count(dreq), rpmi_u32_count(dreq),
+ &dresp, rpmi_u32_count(dresp), rpmi_u32_count(dresp));
+ if (rc)
+ return rc;
+
+ state->local_timer_stop =
+ (dresp.flags & RPMI_HSM_SUSPEND_INFO_FLAGS_TIMER_STOP) ? true : false;
+ state->entry_latency_us = dresp.entry_latency_us;
+ state->exit_latency_us = dresp.exit_latency_us;
+ state->wakeup_latency_us = dresp.wakeup_latency_us;
+ state->min_residency_us = dresp.min_residency_us;
+ }
+
+ return 0;
+}
+
+static int rpmi_hsm_update_hart_scratch(struct mbox_chan *chan,
+ struct rpmi_hsm_suspend *susp)
+{
+ int rc, i;
+ struct rpmi_hsm_get_hart_list_req req;
+ struct rpmi_hsm_get_hart_list_resp resp;
+ struct rpmi_hsm *rpmi = rpmi_hsm_get_pointer(current_hartid());
+
+ req.start_index = 0;
+ do {
+ rc = rpmi_normal_request_with_status(
+ chan, RPMI_HSM_SRV_GET_HART_LIST,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ for (i = 0; i < resp.returned; i++) {
+ rpmi = rpmi_hsm_get_pointer(resp.hartid[i]);
+ if (!rpmi)
+ return SBI_ENOSYS;
+
+ rpmi->chan = chan;
+ rpmi->susp = susp;
+ }
+
+ req.start_index += resp.returned;
+ } while (resp.remaining);
+
+ return 0;
+}
+
+static int rpmi_hsm_cold_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ int rc, i;
+ struct mbox_chan *chan;
+ struct rpmi_hsm_suspend *susp;
+
+ if (!rpmi_hsm_offset) {
+ rpmi_hsm_offset =
+ sbi_scratch_alloc_type_offset(struct rpmi_hsm);
+ if (!rpmi_hsm_offset)
+ return SBI_ENOMEM;
+ }
+
+ /*
+ * If channel request failed then other end does not support
+ * HSM service group so do nothing.
+ */
+ rc = fdt_mailbox_request_chan(fdt, nodeoff, 0, &chan);
+ if (rc)
+ return SBI_ENODEV;
+
+ /* Allocate context for HART suspend states */
+ susp = sbi_zalloc(sizeof(*susp));
+ if (!susp)
+ return SBI_ENOMEM;
+
+ /* Get number of HART suspend states */
+ rc = rpmi_hsm_get_num_suspend_states(chan, susp);
+ if (rc)
+ goto fail_free_susp;
+
+ /* Skip HART suspend state discovery for zero HART suspend states */
+ if (!susp->num_states)
+ goto skip_suspend_states;
+
+ /* Allocate array of HART suspend states */
+ susp->states = sbi_calloc(susp->num_states + 1, sizeof(*susp->states));
+ if (!susp->states) {
+ rc = SBI_ENOMEM;
+ goto fail_free_susp;
+ }
+
+ /* Allocate name of each HART suspend state */
+ for (i = 0; i < susp->num_states; i++) {
+ susp->states[i].name =
+ sbi_zalloc(MAX_HSM_SUPSEND_STATE_NAMELEN);
+ if (!susp->states[i].name) {
+ do {
+ i--;
+ sbi_free((void *)susp->states[i].name);
+ } while (i > 0);
+
+ rc = SBI_ENOMEM;
+ goto fail_free_susp_states;
+ }
+ sbi_snprintf((char *)susp->states[i].name,
+ MAX_HSM_SUPSEND_STATE_NAMELEN, "cpu-susp%d", i);
+ }
+
+ /* Get details about each HART suspend state */
+ rc = rpmi_hsm_get_suspend_states(chan, susp);
+ if (rc)
+ goto fail_free_susp_state_names;
+
+skip_suspend_states:
+ /* Update per-HART scratch space */
+ rc = rpmi_hsm_update_hart_scratch(chan, susp);
+ if (rc)
+ goto fail_free_susp_state_names;
+
+ /* Register HSM fixup callback */
+ rc = fdt_register_general_fixup(&rpmi_hsm_fixup);
+ if (rc)
+ goto fail_free_susp_state_names;
+
+ /* Register HSM device */
+ if (!susp->num_states)
+ sbi_hsm_rpmi.hart_suspend = NULL;
+ sbi_hsm_set_device(&sbi_hsm_rpmi);
+
+ return 0;
+
+fail_free_susp_state_names:
+ for (i = 0; i < susp->num_states; i++)
+ sbi_free((void *)susp->states[i].name);
+fail_free_susp_states:
+ if (susp->num_states)
+ sbi_free(susp->states);
+fail_free_susp:
+ sbi_free(susp);
+ return rc;
+}
+
+static const struct fdt_match rpmi_hsm_match[] = {
+ { .compatible = "riscv,rpmi-hsm" },
+ {},
+};
+
+struct fdt_driver fdt_hsm_rpmi = {
+ .match_table = rpmi_hsm_match,
+ .init = rpmi_hsm_cold_init,
+};
diff --git a/lib/utils/hsm/objects.mk b/lib/utils/hsm/objects.mk
index 49337bf5..b54b6f6c 100644
--- a/lib/utils/hsm/objects.mk
+++ b/lib/utils/hsm/objects.mk
@@ -9,3 +9,6 @@
libsbiutils-objs-$(CONFIG_FDT_HSM) += hsm/fdt_hsm.o
libsbiutils-objs-$(CONFIG_FDT_HSM) += hsm/fdt_hsm_drivers.carray.o
+
+carray-fdt_hsm_drivers-$(CONFIG_FDT_HSM_RPMI) += fdt_hsm_rpmi
+libsbiutils-objs-$(CONFIG_FDT_HSM_RPMI) += hsm/fdt_hsm_rpmi.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 2efc7136..78fc96b6 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -11,6 +11,7 @@ CONFIG_FDT_GPIO_DESIGNWARE=y
CONFIG_FDT_GPIO_SIFIVE=y
CONFIG_FDT_GPIO_STARFIVE=y
CONFIG_FDT_HSM=y
+CONFIG_FDT_HSM_RPMI=y
CONFIG_FDT_I2C=y
CONFIG_FDT_I2C_SIFIVE=y
CONFIG_FDT_I2C_DW=y
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 12/17] lib: utils: Add simple FDT based CPPC driver framework
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (10 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 11/17] lib: utils/hsm: Add RPMI HSM driver Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 13/17] lib: utils/cppc: Add RPMI CPPC driver Anup Patel
` (5 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
The generic platform can have multiple CPPC drivers so add a simple
FDT based CPPC driver framework.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/cppc/fdt_cppc.h | 26 ++++++++++++++++++++++++++
lib/utils/Kconfig | 2 ++
lib/utils/cppc/Kconfig | 10 ++++++++++
lib/utils/cppc/fdt_cppc.c | 22 ++++++++++++++++++++++
lib/utils/cppc/fdt_cppc_drivers.carray | 3 +++
lib/utils/cppc/objects.mk | 11 +++++++++++
platform/generic/configs/defconfig | 1 +
platform/generic/platform.c | 2 ++
8 files changed, 77 insertions(+)
create mode 100644 include/sbi_utils/cppc/fdt_cppc.h
create mode 100644 lib/utils/cppc/Kconfig
create mode 100644 lib/utils/cppc/fdt_cppc.c
create mode 100644 lib/utils/cppc/fdt_cppc_drivers.carray
create mode 100644 lib/utils/cppc/objects.mk
diff --git a/include/sbi_utils/cppc/fdt_cppc.h b/include/sbi_utils/cppc/fdt_cppc.h
new file mode 100644
index 00000000..433c6d32
--- /dev/null
+++ b/include/sbi_utils/cppc/fdt_cppc.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#ifndef __FDT_CPPC_H__
+#define __FDT_CPPC_H__
+
+#include <sbi/sbi_types.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+#ifdef CONFIG_FDT_CPPC
+
+void fdt_cppc_init(const void *fdt);
+
+#else
+
+static inline void fdt_cppc_init(const void *fdt) { }
+
+#endif
+
+#endif
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig
index c860a185..002d6f8f 100644
--- a/lib/utils/Kconfig
+++ b/lib/utils/Kconfig
@@ -2,6 +2,8 @@
menu "Utils and Drivers Support"
+source "$(OPENSBI_SRC_DIR)/lib/utils/cppc/Kconfig"
+
source "$(OPENSBI_SRC_DIR)/lib/utils/fdt/Kconfig"
source "$(OPENSBI_SRC_DIR)/lib/utils/gpio/Kconfig"
diff --git a/lib/utils/cppc/Kconfig b/lib/utils/cppc/Kconfig
new file mode 100644
index 00000000..08d1c97f
--- /dev/null
+++ b/lib/utils/cppc/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+menu "CPPC Device Support"
+
+config FDT_CPPC
+ bool "FDT based CPPC drivers"
+ depends on FDT
+ default n
+
+endmenu
diff --git a/lib/utils/cppc/fdt_cppc.c b/lib/utils/cppc/fdt_cppc.c
new file mode 100644
index 00000000..0e1ecb24
--- /dev/null
+++ b/lib/utils/cppc/fdt_cppc.c
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <sbi_utils/cppc/fdt_cppc.h>
+
+/* List of FDT CPPC drivers generated at compile time */
+extern const struct fdt_driver *const fdt_cppc_drivers[];
+
+void fdt_cppc_init(const void *fdt)
+{
+ /*
+ * Platforms might have multiple CPPC devices or might
+ * not have any so probe all and don't fail.
+ */
+ fdt_driver_init_all(fdt, fdt_cppc_drivers);
+}
diff --git a/lib/utils/cppc/fdt_cppc_drivers.carray b/lib/utils/cppc/fdt_cppc_drivers.carray
new file mode 100644
index 00000000..b25c7888
--- /dev/null
+++ b/lib/utils/cppc/fdt_cppc_drivers.carray
@@ -0,0 +1,3 @@
+HEADER: sbi_utils/cppc/fdt_cppc.h
+TYPE: const struct fdt_driver
+NAME: fdt_cppc_drivers
diff --git a/lib/utils/cppc/objects.mk b/lib/utils/cppc/objects.mk
new file mode 100644
index 00000000..fb37478a
--- /dev/null
+++ b/lib/utils/cppc/objects.mk
@@ -0,0 +1,11 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 Ventana Micro Systems Inc.
+#
+# Authors:
+# Anup Patel <apatel@ventanamicro.com>
+#
+
+libsbiutils-objs-$(CONFIG_FDT_CPPC) += cppc/fdt_cppc.o
+libsbiutils-objs-$(CONFIG_FDT_CPPC) += cppc/fdt_cppc_drivers.carray.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 78fc96b6..bd18c3c1 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -6,6 +6,7 @@ CONFIG_PLATFORM_SIFIVE_FU740=y
CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
+CONFIG_FDT_CPPC=y
CONFIG_FDT_GPIO=y
CONFIG_FDT_GPIO_DESIGNWARE=y
CONFIG_FDT_GPIO_SIFIVE=y
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index 48228e67..6f830744 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -17,6 +17,7 @@
#include <sbi/sbi_string.h>
#include <sbi/sbi_system.h>
#include <sbi/sbi_tlb.h>
+#include <sbi_utils/cppc/fdt_cppc.h>
#include <sbi_utils/fdt/fdt_domain.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/fdt/fdt_helper.h>
@@ -251,6 +252,7 @@ static int generic_early_init(bool cold_boot)
fdt_reset_init(fdt);
fdt_suspend_init(fdt);
fdt_hsm_init(fdt);
+ fdt_cppc_init(fdt);
if (semihosting_enabled())
rc = semihosting_init();
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 13/17] lib: utils/cppc: Add RPMI CPPC driver
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (11 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 12/17] lib: utils: Add simple FDT based CPPC driver framework Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 14/17] lib: sbi: Add SBI Message Proxy (MPXY) framework Anup Patel
` (4 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Add RPMI based driver for CPPC register read, write and probe.
Signed-off-by: Subrahmanya Lingappa <slingappa@ventanamicro.com>
Co-developed-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Sunil V L <sunilvl@ventanamicro.com>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mailbox/rpmi_msgprot.h | 105 +++++++
lib/utils/cppc/Kconfig | 9 +
lib/utils/cppc/fdt_cppc_rpmi.c | 377 +++++++++++++++++++++++
lib/utils/cppc/objects.mk | 3 +
platform/generic/configs/defconfig | 1 +
5 files changed, 495 insertions(+)
create mode 100644 lib/utils/cppc/fdt_cppc_rpmi.c
diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h
index 8e2b23e2..f7c80360 100644
--- a/include/sbi_utils/mailbox/rpmi_msgprot.h
+++ b/include/sbi_utils/mailbox/rpmi_msgprot.h
@@ -200,6 +200,7 @@ enum rpmi_servicegroup_id {
RPMI_SRVGRP_SYSTEM_RESET = 0x0002,
RPMI_SRVGRP_SYSTEM_SUSPEND = 0x0003,
RPMI_SRVGRP_HSM = 0x0004,
+ RPMI_SRVGRP_CPPC = 0x0005,
RPMI_SRVGRP_ID_MAX_COUNT,
/* Reserved range for service groups */
@@ -406,4 +407,108 @@ struct rpmi_hsm_get_susp_info_resp {
u32 min_residency_us;
};
+/** RPMI CPPC ServiceGroup Service IDs */
+enum rpmi_cppc_service_id {
+ RPMI_CPPC_SRV_ENABLE_NOTIFICATION = 0x01,
+ RPMI_CPPC_SRV_PROBE_REG = 0x02,
+ RPMI_CPPC_SRV_READ_REG = 0x03,
+ RPMI_CPPC_SRV_WRITE_REG = 0x04,
+ RPMI_CPPC_SRV_GET_FAST_CHANNEL_REGION = 0x05,
+ RPMI_CPPC_SRV_GET_FAST_CHANNEL_OFFSET = 0x06,
+ RPMI_CPPC_SRV_GET_HART_LIST = 0x07,
+ RPMI_CPPC_SRV_MAX_COUNT,
+};
+
+struct rpmi_cppc_probe_req {
+ u32 hart_id;
+ u32 reg_id;
+};
+
+struct rpmi_cppc_probe_resp {
+ s32 status;
+ u32 reg_len;
+};
+
+struct rpmi_cppc_read_reg_req {
+ u32 hart_id;
+ u32 reg_id;
+};
+
+struct rpmi_cppc_read_reg_resp {
+ s32 status;
+ u32 data_lo;
+ u32 data_hi;
+};
+
+struct rpmi_cppc_write_reg_req {
+ u32 hart_id;
+ u32 reg_id;
+ u32 data_lo;
+ u32 data_hi;
+};
+
+struct rpmi_cppc_write_reg_resp {
+ s32 status;
+};
+
+struct rpmi_cppc_get_fastchan_offset_req {
+ u32 hart_id;
+};
+
+struct rpmi_cppc_get_fastchan_offset_resp {
+ s32 status;
+ u32 fc_perf_request_offset_lo;
+ u32 fc_perf_request_offset_hi;
+ u32 fc_perf_feedback_offset_lo;
+ u32 fc_perf_feedback_offset_hi;
+};
+
+#define RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_POS 3
+#define RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_MASK \
+ (3U << RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_POS)
+#define RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_POS 1
+#define RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_MASK \
+ (3U << RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_POS)
+#define RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_SUPPORTED (1U << 0)
+
+struct rpmi_cppc_get_fastchan_region_resp {
+ s32 status;
+ u32 flags;
+ u32 region_addr_lo;
+ u32 region_addr_hi;
+ u32 region_size_lo;
+ u32 region_size_hi;
+ u32 db_addr_lo;
+ u32 db_addr_hi;
+ u32 db_setmask_lo;
+ u32 db_setmask_hi;
+ u32 db_preservemask_lo;
+ u32 db_preservemask_hi;
+};
+
+enum rpmi_cppc_fast_channel_db_width {
+ RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_8 = 0x0,
+ RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_16 = 0x1,
+ RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_32 = 0x2,
+ RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_64 = 0x3,
+};
+
+enum rpmi_cppc_fast_channel_cppc_mode {
+ RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_PASSIVE = 0x0,
+ RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_ACTIVE = 0x1,
+ RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_MAX_IDX,
+};
+
+struct rpmi_cppc_hart_list_req {
+ u32 start_index;
+};
+
+struct rpmi_cppc_hart_list_resp {
+ s32 status;
+ u32 remaining;
+ u32 returned;
+ /* remaining space need to be adjusted for the above 3 u32's */
+ u32 hartid[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)];
+};
+
#endif /* !__RPMI_MSGPROT_H__ */
diff --git a/lib/utils/cppc/Kconfig b/lib/utils/cppc/Kconfig
index 08d1c97f..494f6894 100644
--- a/lib/utils/cppc/Kconfig
+++ b/lib/utils/cppc/Kconfig
@@ -7,4 +7,13 @@ config FDT_CPPC
depends on FDT
default n
+if FDT_CPPC
+
+config FDT_CPPC_RPMI
+ bool "FDT RPMI CPPC driver"
+ depends on FDT_MAILBOX && RPMI_MAILBOX
+ default n
+
+endif
+
endmenu
diff --git a/lib/utils/cppc/fdt_cppc_rpmi.c b/lib/utils/cppc/fdt_cppc_rpmi.c
new file mode 100644
index 00000000..26e2d4f6
--- /dev/null
+++ b/lib/utils/cppc/fdt_cppc_rpmi.c
@@ -0,0 +1,377 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Subrahmanya Lingappa <slingappa@ventanamicro.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_cppc.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi_utils/cppc/fdt_cppc.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/mailbox/fdt_mailbox.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+
+/**
+ * Per hart RPMI CPPC fast channel size (bytes)
+ * PASSIVE MODE:
+ * 0x0: DESIRED_PERFORMANCE (4-byte)
+ * 0x4: __RESERVED (4-byte)
+ * ACTIVE MODE: (not supported yet)
+ * 0x0: MINIMUM PERFORMANCE (4-byte)
+ * 0x4: MAXIMUM PERFORMANCE (4-byte)
+ */
+#define RPMI_CPPC_HART_FASTCHAN_SIZE 0x8
+
+struct rpmi_cppc {
+ struct mbox_chan *chan;
+ bool fc_supported;
+ bool fc_db_supported;
+ enum rpmi_cppc_fast_channel_db_width fc_db_width;
+ enum rpmi_cppc_fast_channel_cppc_mode mode;
+ ulong fc_perf_request_addr;
+ ulong fc_perf_feedback_addr;
+ ulong fc_db_addr;
+ u64 fc_db_setmask;
+ u64 fc_db_preservemask;
+};
+
+static unsigned long rpmi_cppc_offset;
+
+static struct rpmi_cppc *rpmi_cppc_get_pointer(u32 hartid)
+{
+ struct sbi_scratch *scratch;
+
+ scratch = sbi_hartid_to_scratch(hartid);
+ if (!scratch || !rpmi_cppc_offset)
+ return NULL;
+
+ return sbi_scratch_offset_ptr(scratch, rpmi_cppc_offset);
+}
+
+static void rpmi_cppc_fc_db_trigger(struct rpmi_cppc *cppc)
+{
+ u8 db_val_u8 = 0;
+ u16 db_val_u16 = 0;
+ u32 db_val_u32 = 0;
+
+ switch (cppc->fc_db_width) {
+ case RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_8:
+ db_val_u8 = readb((void *)cppc->fc_db_addr);
+ db_val_u8 = (u8)cppc->fc_db_setmask |
+ (db_val_u8 & (u8)cppc->fc_db_preservemask);
+
+ writeb(db_val_u8, (void *)cppc->fc_db_addr);
+ break;
+ case RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_16:
+ db_val_u16 = readw((void *)cppc->fc_db_addr);
+ db_val_u16 = (u16)cppc->fc_db_setmask |
+ (db_val_u16 & (u16)cppc->fc_db_preservemask);
+
+ writew(db_val_u16, (void *)cppc->fc_db_addr);
+ break;
+ case RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_32:
+ db_val_u32 = readl((void *)cppc->fc_db_addr);
+ db_val_u32 = (u32)cppc->fc_db_setmask |
+ (db_val_u32 & (u32)cppc->fc_db_preservemask);
+
+ writel(db_val_u32, (void *)cppc->fc_db_addr);
+ break;
+ case RPMI_CPPC_FAST_CHANNEL_DB_WIDTH_64:
+#if __riscv_xlen != 32
+ u64 db_val_u64 = 0;
+ db_val_u64 = readq((void *)cppc->fc_db_addr);
+ db_val_u64 = cppc->fc_db_setmask |
+ (db_val_u64 & cppc->fc_db_preservemask);
+
+ writeq(db_val_u64, (void *)cppc->fc_db_addr);
+#else
+ u32 db_val_u32_hi = 0;
+ db_val_u32 = readl((void *)cppc->fc_db_addr);
+ db_val_u32_hi = readl((void *)(cppc->fc_db_addr + 4));
+
+ db_val_u32 = (u32)cppc->fc_db_setmask |
+ (db_val_u32 & (u32)cppc->fc_db_preservemask);
+ db_val_u32_hi = (u32)(cppc->fc_db_setmask >> 32) |
+ (db_val_u32 & (u32)(cppc->fc_db_preservemask >> 32));
+
+ writel(db_val_u32, (void *)cppc->fc_db_addr);
+ writel(db_val_u32_hi, (void *)(cppc->fc_db_addr + 4));
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+static int rpmi_cppc_read(unsigned long reg, u64 *val)
+{
+ int rc = SBI_SUCCESS;
+ struct rpmi_cppc_read_reg_req req;
+ struct rpmi_cppc_read_reg_resp resp;
+ struct rpmi_cppc *cppc;
+
+ req.hart_id = current_hartid();
+ req.reg_id = reg;
+ cppc = rpmi_cppc_get_pointer(req.hart_id);
+
+ rc = rpmi_normal_request_with_status(
+ cppc->chan, RPMI_CPPC_SRV_READ_REG,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+#if __riscv_xlen == 32
+ *val = resp.data_lo;
+#else
+ *val = (u64)resp.data_hi << 32 | resp.data_lo;
+#endif
+ return rc;
+}
+
+static int rpmi_cppc_write(unsigned long reg, u64 val)
+{
+ int rc = SBI_SUCCESS;
+ u32 hart_id = current_hartid();
+ struct rpmi_cppc_write_reg_req req;
+ struct rpmi_cppc_write_reg_resp resp;
+ struct rpmi_cppc *cppc = rpmi_cppc_get_pointer(hart_id);
+
+ if (reg != SBI_CPPC_DESIRED_PERF || !cppc->fc_supported) {
+ req.hart_id = hart_id;
+ req.reg_id = reg;
+ req.data_lo = val & 0xFFFFFFFF;
+ req.data_hi = val >> 32;
+
+ rc = rpmi_normal_request_with_status(
+ cppc->chan, RPMI_CPPC_SRV_WRITE_REG,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ } else {
+ /* use fast path writes for desired_perf in passive mode */
+ writel((u32)val, (void *)cppc->fc_perf_request_addr);
+
+ if (cppc->fc_db_supported)
+ rpmi_cppc_fc_db_trigger(cppc);
+ }
+
+ return rc;
+}
+
+static int rpmi_cppc_probe(unsigned long reg)
+{
+ int rc;
+ struct rpmi_cppc *cppc;
+ struct rpmi_cppc_probe_resp resp;
+ struct rpmi_cppc_probe_req req;
+
+ req.hart_id = current_hartid();
+ req.reg_id = reg;
+
+ cppc = rpmi_cppc_get_pointer(req.hart_id);
+ if (!cppc)
+ return SBI_ENOSYS;
+
+ rc = rpmi_normal_request_with_status(
+ cppc->chan, RPMI_CPPC_SRV_PROBE_REG,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ return resp.reg_len;
+}
+
+static struct sbi_cppc_device sbi_rpmi_cppc = {
+ .name = "rpmi-cppc",
+ .cppc_read = rpmi_cppc_read,
+ .cppc_write = rpmi_cppc_write,
+ .cppc_probe = rpmi_cppc_probe,
+};
+
+static int rpmi_cppc_update_hart_scratch(struct mbox_chan *chan)
+{
+ int rc, i;
+ bool fc_supported = false;
+ bool fc_db_supported = false;
+ struct rpmi_cppc_hart_list_req req;
+ struct rpmi_cppc_hart_list_resp resp;
+ struct rpmi_cppc_get_fastchan_offset_req hfreq;
+ struct rpmi_cppc_get_fastchan_offset_resp hfresp;
+ struct rpmi_cppc_get_fastchan_region_resp fresp;
+ enum rpmi_cppc_fast_channel_db_width fc_db_width = 0;
+ enum rpmi_cppc_fast_channel_cppc_mode cppc_mode = 0;
+ struct rpmi_cppc *cppc;
+ unsigned long fc_region_addr = 0;
+ unsigned long fc_region_size = 0;
+ unsigned long fc_db_addr = 0;
+ u64 fc_db_setmask = 0;
+ u64 fc_db_preservemask = 0;
+
+ rc = rpmi_normal_request_with_status(
+ chan, RPMI_CPPC_SRV_GET_FAST_CHANNEL_REGION,
+ NULL, 0, 0,
+ &fresp, rpmi_u32_count(fresp), rpmi_u32_count(fresp));
+ if (rc && rc != SBI_ENOTSUPP)
+ return rc;
+
+ /* At this point fast channel availability is confirmed */
+ fc_supported = (rc != SBI_ENOTSUPP)? true : false;
+
+ /* If fast channel is supported, add the fast channel
+ * region in root domain as MMIO RW. And, get the doorbell
+ * information from the response */
+ if (fc_supported) {
+#if __riscv_xlen == 32
+ fc_region_addr = fresp.region_addr_lo;
+ fc_region_size = fresp.region_size_lo;
+ fc_db_addr = fresp.db_addr_lo;
+#else
+ fc_region_addr = (ulong)fresp.region_addr_hi << 32 |
+ fresp.region_addr_lo;
+ fc_region_size = (ulong)fresp.region_size_hi << 32 |
+ fresp.region_size_lo;
+ fc_db_addr = (ulong)fresp.db_addr_hi << 32 | fresp.db_addr_lo;
+
+#endif
+ rc = sbi_domain_root_add_memrange(fc_region_addr,
+ fc_region_size,
+ RPMI_CPPC_HART_FASTCHAN_SIZE,
+ (SBI_DOMAIN_MEMREGION_MMIO |
+ SBI_DOMAIN_MEMREGION_M_READABLE |
+ SBI_DOMAIN_MEMREGION_M_WRITABLE));
+ if (rc)
+ return rc;
+
+ cppc_mode = (fresp.flags & RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_MASK) >>
+ RPMI_CPPC_FAST_CHANNEL_CPPC_MODE_POS;
+ fc_db_supported = fresp.flags &
+ RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_SUPPORTED;
+ fc_db_width = (fresp.flags &
+ RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_MASK) >>
+ RPMI_CPPC_FAST_CHANNEL_FLAGS_DB_WIDTH_POS;
+ fc_db_setmask = (u64)fresp.db_setmask_hi << 32 |
+ fresp.db_setmask_lo;
+ fc_db_preservemask = (u64)fresp.db_preservemask_hi << 32 |
+ fresp.db_preservemask_lo;
+ }
+
+ /* Get the hart list and depending on the fast channel support
+ * initialize the per hart cppc structure */
+ req.start_index = 0;
+ do {
+ rc = rpmi_normal_request_with_status(
+ chan, RPMI_CPPC_SRV_GET_HART_LIST,
+ &req, rpmi_u32_count(req), rpmi_u32_count(req),
+ &resp, rpmi_u32_count(resp), rpmi_u32_count(resp));
+ if (rc)
+ return rc;
+
+ /* For each returned harts, get their fastchan offset and
+ * complete the initialization of per hart cppc structure */
+ for (i = 0; i < resp.returned; i++) {
+ cppc = rpmi_cppc_get_pointer(resp.hartid[i]);
+ if (!cppc)
+ return SBI_ENOSYS;
+
+ cppc->chan = chan;
+ cppc->mode = cppc_mode;
+ cppc->fc_supported = fc_supported;
+
+ if (fc_supported) {
+ hfreq.hart_id = resp.hartid[i];
+ rc = rpmi_normal_request_with_status(
+ chan,
+ RPMI_CPPC_SRV_GET_FAST_CHANNEL_OFFSET,
+ &hfreq,
+ rpmi_u32_count(hfreq),
+ rpmi_u32_count(hfreq),
+ &hfresp,
+ rpmi_u32_count(hfresp),
+ rpmi_u32_count(hfresp));
+ if (rc)
+ continue;
+
+#if __riscv_xlen == 32
+ cppc->fc_perf_request_addr = fc_region_addr +
+ hfresp.fc_perf_request_offset_lo;
+ cppc->fc_perf_feedback_addr = fc_region_addr +
+ hfresp.fc_perf_feedback_offset_lo;
+#else
+ cppc->fc_perf_request_addr = fc_region_addr +
+ ((ulong)hfresp.fc_perf_request_offset_hi << 32 |
+ hfresp.fc_perf_request_offset_lo);
+
+ cppc->fc_perf_feedback_addr = fc_region_addr +
+ ((ulong)hfresp.fc_perf_feedback_offset_hi << 32 |
+ hfresp.fc_perf_feedback_offset_lo);
+#endif
+ cppc->fc_db_supported = fc_db_supported;
+ cppc->fc_db_addr = fc_db_addr;
+ cppc->fc_db_width = fc_db_width;
+
+ cppc->fc_db_setmask = fc_db_setmask;
+ cppc->fc_db_preservemask = fc_db_preservemask;
+ }
+ else {
+ cppc->fc_perf_request_addr = 0;
+ cppc->fc_perf_feedback_addr = 0;
+ cppc->fc_db_supported = 0;
+ cppc->fc_db_addr = 0;
+ cppc->fc_db_width = 0;
+ cppc->fc_db_setmask = 0;
+ cppc->fc_db_preservemask = 0;
+ }
+ }
+ req.start_index += resp.returned;
+ } while (resp.remaining);
+
+ return 0;
+}
+
+static int rpmi_cppc_cold_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ int rc;
+ struct mbox_chan *chan;
+
+ if (!rpmi_cppc_offset) {
+ rpmi_cppc_offset =
+ sbi_scratch_alloc_type_offset(struct rpmi_cppc);
+ if (!rpmi_cppc_offset)
+ return SBI_ENOMEM;
+ }
+
+ /*
+ * If channel request failed then other end does not support
+ * CPPC service group so do nothing.
+ */
+ rc = fdt_mailbox_request_chan(fdt, nodeoff, 0, &chan);
+ if (rc)
+ return SBI_ENODEV;
+
+ /* Update per-HART scratch space */
+ rc = rpmi_cppc_update_hart_scratch(chan);
+ if (rc)
+ return rc;
+
+ sbi_cppc_set_device(&sbi_rpmi_cppc);
+
+ return 0;
+}
+
+static const struct fdt_match rpmi_cppc_match[] = {
+ { .compatible = "riscv,rpmi-cppc" },
+ {},
+};
+
+struct fdt_driver fdt_cppc_rpmi = {
+ .match_table = rpmi_cppc_match,
+ .init = rpmi_cppc_cold_init,
+};
diff --git a/lib/utils/cppc/objects.mk b/lib/utils/cppc/objects.mk
index fb37478a..07dc7d89 100644
--- a/lib/utils/cppc/objects.mk
+++ b/lib/utils/cppc/objects.mk
@@ -9,3 +9,6 @@
libsbiutils-objs-$(CONFIG_FDT_CPPC) += cppc/fdt_cppc.o
libsbiutils-objs-$(CONFIG_FDT_CPPC) += cppc/fdt_cppc_drivers.carray.o
+
+carray-fdt_cppc_drivers-$(CONFIG_FDT_CPPC_RPMI) += fdt_cppc_rpmi
+libsbiutils-objs-$(CONFIG_FDT_CPPC_RPMI) += cppc/fdt_cppc_rpmi.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index bd18c3c1..384918f9 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -7,6 +7,7 @@ CONFIG_PLATFORM_SOPHGO_SG2042=y
CONFIG_PLATFORM_STARFIVE_JH7110=y
CONFIG_PLATFORM_THEAD=y
CONFIG_FDT_CPPC=y
+CONFIG_FDT_CPPC_RPMI=y
CONFIG_FDT_GPIO=y
CONFIG_FDT_GPIO_DESIGNWARE=y
CONFIG_FDT_GPIO_SIFIVE=y
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 14/17] lib: sbi: Add SBI Message Proxy (MPXY) framework
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (12 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 13/17] lib: utils/cppc: Add RPMI CPPC driver Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 15/17] lib: sbi: Implement SBI MPXY extension Anup Patel
` (3 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Rahul Pathak <rpathak@ventanamicro.com>
Introduce SBI Message Proxy (MPXY) framework which allows platform specific
code or drivers to register message protocol specific channels.
This framework enables the supervisor software to send messages belonging
to different message protocols via OpenSBI firmware.
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Signed-off-by: Himanshu Chauhan <hchauhan@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi/sbi_ecall_interface.h | 2 +
include/sbi/sbi_error.h | 15 +-
include/sbi/sbi_mpxy.h | 183 ++++++++
include/sbi/sbi_platform.h | 17 +
lib/sbi/objects.mk | 1 +
lib/sbi/sbi_init.c | 6 +
lib/sbi/sbi_mpxy.c | 698 ++++++++++++++++++++++++++++++
7 files changed, 915 insertions(+), 7 deletions(-)
create mode 100644 include/sbi/sbi_mpxy.h
create mode 100644 lib/sbi/sbi_mpxy.c
diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index 3aa57466..90c4ce11 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -432,6 +432,8 @@ enum sbi_sse_state {
#define SBI_ERR_NO_SHMEM -9
#define SBI_ERR_INVALID_STATE -10
#define SBI_ERR_BAD_RANGE -11
+#define SBI_ERR_TIMEOUT -12
+#define SBI_ERR_IO -13
#define SBI_LAST_ERR SBI_ERR_BAD_RANGE
diff --git a/include/sbi/sbi_error.h b/include/sbi/sbi_error.h
index fb78bf62..b40b3319 100644
--- a/include/sbi/sbi_error.h
+++ b/include/sbi/sbi_error.h
@@ -26,16 +26,17 @@
#define SBI_ENO_SHMEM SBI_ERR_NO_SHMEM
#define SBI_EINVALID_STATE SBI_ERR_INVALID_STATE
#define SBI_EBAD_RANGE SBI_ERR_BAD_RANGE
+#define SBI_ETIMEOUT SBI_ERR_TIMEOUT
+#define SBI_ETIMEDOUT SBI_ERR_TIMEOUT
+#define SBI_EIO SBI_ERR_IO
#define SBI_ENODEV -1000
#define SBI_ENOSYS -1001
-#define SBI_ETIMEDOUT -1002
-#define SBI_EIO -1003
-#define SBI_EILL -1004
-#define SBI_ENOSPC -1005
-#define SBI_ENOMEM -1006
-#define SBI_EUNKNOWN -1007
-#define SBI_ENOENT -1008
+#define SBI_EILL -1002
+#define SBI_ENOSPC -1003
+#define SBI_ENOMEM -1004
+#define SBI_EUNKNOWN -1005
+#define SBI_ENOENT -1006
/* clang-format on */
diff --git a/include/sbi/sbi_mpxy.h b/include/sbi/sbi_mpxy.h
new file mode 100644
index 00000000..e30a17d1
--- /dev/null
+++ b/include/sbi/sbi_mpxy.h
@@ -0,0 +1,183 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Rahul Pathak <rpathak@ventanamicro.com>
+ */
+
+#ifndef __SBI_MPXY_H__
+#define __SBI_MPXY_H__
+
+#include <sbi/sbi_list.h>
+
+struct sbi_scratch;
+
+#define SBI_MPXY_MSGPROTO_VERSION(Major, Minor) ((Major << 16) | Minor)
+
+enum sbi_mpxy_attr_id {
+ /* Standard channel attributes managed by MPXY framework */
+ SBI_MPXY_ATTR_MSG_PROT_ID = 0x00000000,
+ SBI_MPXY_ATTR_MSG_PROT_VER = 0x00000001,
+ SBI_MPXY_ATTR_MSG_MAX_LEN = 0x00000002,
+ SBI_MPXY_ATTR_MSG_SEND_TIMEOUT = 0x00000003,
+ SBI_MPXY_ATTR_MSG_COMPLETION_TIMEOUT = 0x00000004,
+ SBI_MPXY_ATTR_CHANNEL_CAPABILITY = 0x00000005,
+ SBI_MPXY_ATTR_SSE_EVENT_ID = 0x00000006,
+ SBI_MPXY_ATTR_MSI_CONTROL = 0x00000007,
+ SBI_MPXY_ATTR_MSI_ADDR_LO = 0x00000008,
+ SBI_MPXY_ATTR_MSI_ADDR_HI = 0x00000009,
+ SBI_MPXY_ATTR_MSI_DATA = 0x0000000A,
+ SBI_MPXY_ATTR_EVENTS_STATE_CONTROL = 0x0000000B,
+ SBI_MPXY_ATTR_STD_ATTR_MAX_IDX,
+ /* Message protocol specific attributes, managed by
+ * message protocol driver */
+ SBI_MPXY_ATTR_MSGPROTO_ATTR_START = 0x80000000,
+ SBI_MPXY_ATTR_MSGPROTO_ATTR_END = 0xffffffff
+};
+
+/**
+ * SBI MPXY Message Protocol IDs
+ */
+enum sbi_mpxy_msgproto_id {
+ SBI_MPXY_MSGPROTO_RPMI_ID = 0x00000000,
+ SBI_MPXY_MSGPROTO_MAX_IDX,
+ /** Vendor specific message protocol IDs */
+ SBI_MPXY_MSGPROTO_VENDOR_START = 0x80000000,
+ SBI_MPXY_MSGPROTO_VENDOR_END = 0xffffffff
+};
+
+enum SBI_EXT_MPXY_SHMEM_FLAGS {
+ SBI_EXT_MPXY_SHMEM_FLAG_OVERWRITE = 0b00,
+ SBI_EXT_MPXY_SHMEM_FLAG_OVERWRITE_RETURN = 0b01,
+ SBI_EXT_MPXY_SHMEM_FLAG_MAX_IDX
+};
+
+struct sbi_mpxy_msi_info {
+ /* MSI target address low 32-bit */
+ u32 msi_addr_lo;
+ /* MSI target address high 32-bit */
+ u32 msi_addr_hi;
+ /* MSI data */
+ u32 msi_data;
+};
+
+/**
+ * Channel attributes.
+ * NOTE: The sequence of attribute fields are as per the
+ * defined sequence in the attribute table in spec(or as
+ * per the enum sbi_mpxy_attr_id).
+ */
+struct sbi_mpxy_channel_attrs {
+ /* Message protocol ID */
+ u32 msg_proto_id;
+ /* Message protocol Version */
+ u32 msg_proto_version;
+ /* Message protocol maximum message data length(bytes) */
+ u32 msg_data_maxlen;
+ /* Message protocol message send timeout
+ * in microseconds */
+ u32 msg_send_timeout;
+ /* Message protocol message response timeout in
+ * microseconds. Its the aggregate of msg_send_timeout
+ * and the timeout in receiving the response */
+ u32 msg_completion_timeout;
+ /* Bit array for channel capabilities */
+ u32 capability;
+ u32 sse_event_id;
+ u32 msi_control;
+ struct sbi_mpxy_msi_info msi_info;
+ /* Events State Control */
+ u32 eventsstate_ctrl;
+};
+
+/** A Message proxy channel accessible through SBI interface */
+struct sbi_mpxy_channel {
+ /** List head to a set of channels */
+ struct sbi_dlist head;
+ u32 channel_id;
+ struct sbi_mpxy_channel_attrs attrs;
+
+ /**
+ * Read message protocol attributes
+ * NOTE: inmem requires little-endian byte-ordering
+ */
+ int (*read_attributes)(struct sbi_mpxy_channel *channel,
+ u32 *outmem,
+ u32 base_attr_id,
+ u32 attr_count);
+
+ /**
+ * Write message protocol attributes
+ * NOTE: outmem requires little-endian byte-ordering
+ */
+ int (*write_attributes)(struct sbi_mpxy_channel *channel,
+ u32 *inmem,
+ u32 base_attr_id,
+ u32 attr_count);
+ /**
+ * Send a message and wait for response
+ * NOTE: msgbuf requires little-endian byte-ordering
+ */
+ int (*send_message_with_response)(struct sbi_mpxy_channel *channel,
+ u32 msg_id, void *msgbuf, u32 msg_len,
+ void *respbuf, u32 resp_max_len,
+ unsigned long *resp_len);
+
+ /** Send message without response */
+ int (*send_message_without_response)(struct sbi_mpxy_channel *channel,
+ u32 msg_id, void *msgbuf, u32 msg_len);
+
+ /**
+ * Get notifications events if supported on a channel
+ * NOTE: eventsbuf requires little-endian byte-ordering
+ */
+ int (*get_notification_events)(struct sbi_mpxy_channel *channel,
+ void *eventsbuf, u32 bufsize,
+ unsigned long *events_len);
+
+ /**
+ * Callback to enable the events state reporting
+ * in the message protocol implementation
+ */
+ void (*switch_eventsstate)(u32 enable);
+};
+
+/** Register a Message proxy channel */
+int sbi_mpxy_register_channel(struct sbi_mpxy_channel *channel);
+
+/** Initialize Message proxy subsystem */
+int sbi_mpxy_init(struct sbi_scratch *scratch);
+
+/** Check if some Message proxy channel is available */
+bool sbi_mpxy_channel_available(void);
+
+/** Set Message proxy shared memory on the calling HART */
+int sbi_mpxy_set_shmem(unsigned long shmem_size,
+ unsigned long shmem_phys_lo,
+ unsigned long shmem_phys_hi,
+ unsigned long flags);
+
+/** Get channel IDs list */
+int sbi_mpxy_get_channel_ids(u32 start_index);
+
+/** Read MPXY channel attributes */
+int sbi_mpxy_read_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count);
+
+/** Write MPXY channel attributes */
+int sbi_mpxy_write_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count);
+
+/**
+ * Send a message over a MPXY channel.
+ * In case if response is not expected, resp_data_len will be NULL.
+ */
+int sbi_mpxy_send_message(u32 channel_id, u8 msg_id,
+ unsigned long msg_data_len,
+ unsigned long *resp_data_len);
+
+/** Get Message proxy notification events */
+int sbi_mpxy_get_notification_events(u32 channel_id,
+ unsigned long *events_len);
+
+#endif
diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index dc852a5c..6d5fbc7d 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -126,6 +126,9 @@ struct sbi_platform_operations {
/** Initialize platform timer during cold boot */
int (*timer_init)(void);
+ /** Initialize the platform Message Proxy(MPXY) driver */
+ int (*mpxy_init)(void);
+
/** Check if SBI vendor extension is implemented or not */
bool (*vendor_ext_check)(void);
/** platform specific SBI extension implementation provider */
@@ -582,6 +585,20 @@ static inline int sbi_platform_timer_init(const struct sbi_platform *plat)
return 0;
}
+/**
+ * Initialize the platform Message Proxy drivers
+ *
+ * @param plat pointer to struct sbi_platform
+ *
+ * @return 0 on success and negative error code on failure
+ */
+static inline int sbi_platform_mpxy_init(const struct sbi_platform *plat)
+{
+ if (plat && sbi_platform_ops(plat)->mpxy_init)
+ return sbi_platform_ops(plat)->mpxy_init();
+ return 0;
+}
+
/**
* Check if SBI vendor extension is implemented or not.
*
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index a6f7c5fa..80b82f8e 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -83,6 +83,7 @@ libsbi-objs-y += sbi_irqchip.o
libsbi-objs-y += sbi_platform.o
libsbi-objs-y += sbi_pmu.o
libsbi-objs-y += sbi_dbtr.o
+libsbi-objs-y += sbi_mpxy.o
libsbi-objs-y += sbi_scratch.o
libsbi-objs-y += sbi_sse.o
libsbi-objs-y += sbi_string.o
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 8a2cfaef..0736345d 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -24,6 +24,7 @@
#include <sbi/sbi_platform.h>
#include <sbi/sbi_pmu.h>
#include <sbi/sbi_dbtr.h>
+#include <sbi/sbi_mpxy.h>
#include <sbi/sbi_sse.h>
#include <sbi/sbi_system.h>
#include <sbi/sbi_string.h>
@@ -311,6 +312,11 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
sbi_hart_hang();
}
+ rc = sbi_mpxy_init(scratch);
+ if (rc) {
+ sbi_printf("%s: mpxy init failed (error %d)\n", __func__, rc);
+ sbi_hart_hang();
+ }
/*
* Note: Finalize domains after HSM initialization so that we
* can startup non-root domains.
diff --git a/lib/sbi/sbi_mpxy.c b/lib/sbi/sbi_mpxy.c
new file mode 100644
index 00000000..639478bf
--- /dev/null
+++ b/lib/sbi/sbi_mpxy.c
@@ -0,0 +1,698 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Rahul Pathak <rpathak@ventanamicro.com>
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_platform.h>
+#include <sbi/sbi_mpxy.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_string.h>
+#include <sbi/sbi_bitops.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_byteorder.h>
+
+/** Offset of pointer to MPXY state in scratch space */
+static unsigned long mpxy_state_offset;
+
+/** List of MPXY proxy channels */
+static SBI_LIST_HEAD(mpxy_channel_list);
+
+/** Invalid Physical Address(all bits 1) */
+#define INVALID_ADDR (-1U)
+
+/** MPXY Attribute size in bytes */
+#define ATTR_SIZE (4)
+
+/** Channel Capability - MSI */
+#define CAP_MSI_POS 0
+#define CAP_MSI_MASK (1U << CAP_MSI_POS)
+
+/** Channel Capability - SSE */
+#define CAP_SSE_POS 1
+#define CAP_SSE_MASK (1U << CAP_SSE_POS)
+
+/** Channel Capability - Events State */
+#define CAP_EVENTSSTATE_POS 2
+#define CAP_EVENTSSTATE_MASK (1U << CAP_EVENTSSTATE_POS)
+
+/** Channel Capability - Get Notification function support */
+#define CAP_GET_NOTIFICATIONS_POS 3
+#define CAP_GET_NOTIFICATIONS_MASK (1U << CAP_GET_NOTIFICATIONS_POS)
+
+/** Channel Capability - Send Message Without Response function support */
+#define CAP_SEND_MSG_WITHOUT_RESP_POS 4
+#define CAP_SEND_MSG_WITHOUT_RESP_MASK (1U << CAP_SEND_MSG_WITHOUT_RESP_POS)
+
+/** Channel Capability - Send Message With Response function support */
+#define CAP_SEND_MSG_WITH_RESP_POS 5
+#define CAP_SEND_MSG_WITH_RESP_MASK (1U << CAP_SEND_MSG_WITH_RESP_POS)
+
+/** Helpers to enable/disable channel capability bits
+ * _c: capability variable
+ * _m: capability mask
+ */
+#define CAP_ENABLE(_c, _m) INSERT_FIELD(_c, _m, 1)
+#define CAP_DISABLE(_c, _m) INSERT_FIELD(_c, _m, 0)
+#define CAP_GET(_c, _m) EXTRACT_FIELD(_c, _m)
+
+#if __riscv_xlen == 64
+#define SHMEM_PHYS_ADDR(_hi, _lo) (_lo)
+#elif __riscv_xlen == 32
+#define SHMEM_PHYS_ADDR(_hi, _lo) (((u64)(_hi) << 32) | (_lo))
+#else
+#error "Undefined XLEN"
+#endif
+
+/** Per hart shared memory */
+struct mpxy_shmem {
+ unsigned long shmem_size;
+ unsigned long shmem_addr_lo;
+ unsigned long shmem_addr_hi;
+};
+
+struct mpxy_state {
+ /* MSI support in MPXY */
+ bool msi_avail;
+ /* SSE support in MPXY */
+ bool sse_avail;
+ /* MPXY Shared memory details */
+ struct mpxy_shmem shmem;
+};
+
+/** Disable hart shared memory */
+static inline void sbi_mpxy_shmem_disable(struct mpxy_state *ms)
+{
+ ms->shmem.shmem_size = 0;
+ ms->shmem.shmem_addr_lo = INVALID_ADDR;
+ ms->shmem.shmem_addr_hi = INVALID_ADDR;
+}
+
+/** Check if shared memory is already setup on hart */
+static inline bool mpxy_shmem_enabled(struct mpxy_state *ms)
+{
+ return (ms->shmem.shmem_addr_lo == INVALID_ADDR
+ && ms->shmem.shmem_addr_hi == INVALID_ADDR) ?
+ false : true;
+}
+
+/** Get hart shared memory base address */
+static inline void *hart_shmem_base(struct mpxy_state *ms)
+{
+ return (void *)(unsigned long)SHMEM_PHYS_ADDR(ms->shmem.shmem_addr_hi,
+ ms->shmem.shmem_addr_lo);
+}
+
+/** Make sure all attributes are packed for direct memcpy in ATTR_READ */
+#define assert_field_offset(field, attr_offset) \
+ _Static_assert( \
+ ((offsetof(struct sbi_mpxy_channel_attrs, field)) / \
+ sizeof(u32)) == attr_offset, \
+ "field " #field \
+ " from struct sbi_mpxy_channel_attrs invalid offset, expected " #attr_offset)
+
+assert_field_offset(msg_proto_id, SBI_MPXY_ATTR_MSG_PROT_ID);
+assert_field_offset(msg_proto_version, SBI_MPXY_ATTR_MSG_PROT_VER);
+assert_field_offset(msg_data_maxlen, SBI_MPXY_ATTR_MSG_MAX_LEN);
+assert_field_offset(msg_send_timeout, SBI_MPXY_ATTR_MSG_SEND_TIMEOUT);
+assert_field_offset(msg_completion_timeout, SBI_MPXY_ATTR_MSG_COMPLETION_TIMEOUT);
+assert_field_offset(capability, SBI_MPXY_ATTR_CHANNEL_CAPABILITY);
+assert_field_offset(sse_event_id, SBI_MPXY_ATTR_SSE_EVENT_ID);
+assert_field_offset(msi_control, SBI_MPXY_ATTR_MSI_CONTROL);
+assert_field_offset(msi_info.msi_addr_lo, SBI_MPXY_ATTR_MSI_ADDR_LO);
+assert_field_offset(msi_info.msi_addr_hi, SBI_MPXY_ATTR_MSI_ADDR_HI);
+assert_field_offset(msi_info.msi_data, SBI_MPXY_ATTR_MSI_DATA);
+assert_field_offset(eventsstate_ctrl, SBI_MPXY_ATTR_EVENTS_STATE_CONTROL);
+
+/**
+ * Check if the attribute is a standard attribute or
+ * a message protocol specific attribute
+ * attr_id[31] = 0 for standard
+ * attr_id[31] = 1 for message protocol specific
+ */
+static inline bool mpxy_is_std_attr(u32 attr_id)
+{
+ return (attr_id >> 31) ? false : true;
+}
+
+/** Find channel_id in registered channels list */
+static struct sbi_mpxy_channel *mpxy_find_channel(u32 channel_id)
+{
+ struct sbi_mpxy_channel *channel;
+
+ sbi_list_for_each_entry(channel, &mpxy_channel_list, head)
+ if (channel->channel_id == channel_id)
+ return channel;
+
+ return NULL;
+}
+
+/** Copy attributes word size */
+static void mpxy_copy_std_attrs(u32 *outmem, u32 *inmem, u32 count)
+{
+ int idx;
+ for (idx = 0; idx < count; idx++)
+ outmem[idx] = cpu_to_le32(inmem[idx]);
+}
+
+/** Check if any channel is registered with mpxy framework */
+bool sbi_mpxy_channel_available(void)
+{
+ return sbi_list_empty(&mpxy_channel_list) ? false : true;
+}
+
+static void mpxy_std_attrs_init(struct sbi_mpxy_channel *channel)
+{
+ u32 capability = 0;
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+
+ /* Reset values */
+ channel->attrs.msi_control = 0;
+ channel->attrs.msi_info.msi_data = 0;
+ channel->attrs.msi_info.msi_addr_lo = 0;
+ channel->attrs.msi_info.msi_addr_hi = 0;
+ channel->attrs.capability = 0;
+ channel->attrs.eventsstate_ctrl = 0;
+
+ if (channel->send_message_with_response)
+ capability = CAP_ENABLE(capability, CAP_SEND_MSG_WITH_RESP_MASK);
+
+ if (channel->send_message_without_response)
+ capability = CAP_ENABLE(capability, CAP_SEND_MSG_WITHOUT_RESP_MASK);
+
+ if (channel->get_notification_events) {
+ capability = CAP_ENABLE(capability, CAP_GET_NOTIFICATIONS_MASK);
+ /**
+ * Check if MSI or SSE available for notification interrrupt.
+ * Priority given to MSI if both MSI and SSE are avaialble.
+ */
+ if (ms->msi_avail)
+ capability = CAP_ENABLE(capability, CAP_MSI_MASK);
+ else if (ms->sse_avail) {
+ capability = CAP_ENABLE(capability, CAP_SSE_MASK);
+ /* TODO: Assign SSE EVENT_ID for the channel */
+ }
+
+ /**
+ * switch_eventstate callback support means support for events
+ * state reporting supoprt. Enable events state reporting in
+ * channel capability.
+ */
+ if (channel->switch_eventsstate)
+ capability = CAP_ENABLE(capability, CAP_EVENTSSTATE_MASK);
+ }
+
+ channel->attrs.capability = capability;
+}
+
+/**
+ * Register a channel with MPXY framework.
+ * Called by message protocol drivers
+ */
+int sbi_mpxy_register_channel(struct sbi_mpxy_channel *channel)
+{
+ if (!channel)
+ return SBI_EINVAL;
+
+ if (mpxy_find_channel(channel->channel_id))
+ return SBI_EALREADY;
+
+ /* Initialize channel specific attributes */
+ mpxy_std_attrs_init(channel);
+
+ SBI_INIT_LIST_HEAD(&channel->head);
+ sbi_list_add_tail(&channel->head, &mpxy_channel_list);
+
+ return SBI_OK;
+}
+
+int sbi_mpxy_init(struct sbi_scratch *scratch)
+{
+ mpxy_state_offset = sbi_scratch_alloc_type_offset(struct mpxy_state);
+ if (!mpxy_state_offset)
+ return SBI_ENOMEM;
+
+ /**
+ * TODO: Proper support for checking msi support from platform.
+ * Currently disable msi and sse and use polling
+ */
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+ ms->msi_avail = false;
+ ms->sse_avail = false;
+
+ sbi_mpxy_shmem_disable(ms);
+
+ return sbi_platform_mpxy_init(sbi_platform_ptr(scratch));
+}
+
+int sbi_mpxy_set_shmem(unsigned long shmem_size, unsigned long shmem_phys_lo,
+ unsigned long shmem_phys_hi, unsigned long flags)
+{
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+ unsigned long *ret_buf;
+
+ /** Disable shared memory if both hi and lo have all bit 1s */
+ if (shmem_phys_lo == INVALID_ADDR &&
+ shmem_phys_hi == INVALID_ADDR) {
+ sbi_mpxy_shmem_disable(ms);
+ return SBI_SUCCESS;
+ }
+
+ if (flags >= SBI_EXT_MPXY_SHMEM_FLAG_MAX_IDX)
+ return SBI_ERR_INVALID_PARAM;
+
+ /** Check shared memory size and address aligned to 4K Page */
+ if (!shmem_size || (shmem_size & ~PAGE_MASK) ||
+ (shmem_phys_lo & ~PAGE_MASK))
+ return SBI_ERR_INVALID_PARAM;
+
+ if (!sbi_domain_check_addr_range(sbi_domain_thishart_ptr(),
+ SHMEM_PHYS_ADDR(shmem_phys_hi, shmem_phys_lo),
+ shmem_size, PRV_S,
+ SBI_DOMAIN_READ | SBI_DOMAIN_WRITE))
+ return SBI_ERR_INVALID_ADDRESS;
+
+ /** Save the current shmem details in new shmem region */
+ if (flags == SBI_EXT_MPXY_SHMEM_FLAG_OVERWRITE_RETURN) {
+ ret_buf = (unsigned long *)(ulong)SHMEM_PHYS_ADDR(shmem_phys_hi,
+ shmem_phys_lo);
+ sbi_hart_map_saddr((unsigned long)ret_buf, shmem_size);
+ ret_buf[0] = cpu_to_lle(ms->shmem.shmem_size);
+ ret_buf[1] = cpu_to_lle(ms->shmem.shmem_addr_lo);
+ ret_buf[2] = cpu_to_lle(ms->shmem.shmem_addr_hi);
+ sbi_hart_unmap_saddr();
+ }
+
+ /** Setup the new shared memory */
+ ms->shmem.shmem_size = shmem_size;
+ ms->shmem.shmem_addr_lo = shmem_phys_lo;
+ ms->shmem.shmem_addr_hi = shmem_phys_hi;
+
+ return SBI_SUCCESS;
+}
+
+int sbi_mpxy_get_channel_ids(u32 start_index)
+{
+ u32 node_index = 0, node_ret = 0;
+ u32 remaining, returned, max_channelids;
+ u32 channels_count = 0;
+ u32 *shmem_base;
+ struct sbi_mpxy_channel *channel;
+
+ /* Check if the shared memory is being setup or not. */
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+
+ if (!mpxy_shmem_enabled(ms))
+ return SBI_ERR_NO_SHMEM;
+
+ sbi_list_for_each_entry(channel, &mpxy_channel_list, head)
+ channels_count += 1;
+
+ if (start_index > channels_count)
+ return SBI_ERR_INVALID_PARAM;
+
+ shmem_base = hart_shmem_base(ms);
+ sbi_hart_map_saddr((unsigned long)hart_shmem_base(ms),
+ ms->shmem.shmem_size);
+
+ /** number of channel ids which can be stored in shmem adjusting
+ * for remaining and returned fields */
+ max_channelids = (ms->shmem.shmem_size / sizeof(u32)) - 2;
+ /* total remaining from the start index */
+ remaining = channels_count - start_index;
+ /* how many can be returned */
+ returned = (remaining > max_channelids)? max_channelids : remaining;
+
+ // Iterate over the list of channels to get the channel ids.
+ sbi_list_for_each_entry(channel, &mpxy_channel_list, head) {
+ if (node_index >= start_index &&
+ node_index < (start_index + returned)) {
+ shmem_base[2 + node_ret] = cpu_to_le32(channel->channel_id);
+ node_ret += 1;
+ }
+
+ node_index += 1;
+ }
+
+ /* final remaininig channel ids */
+ remaining = channels_count - (start_index + returned);
+
+ shmem_base[0] = cpu_to_le32(remaining);
+ shmem_base[1] = cpu_to_le32(returned);
+
+ sbi_hart_unmap_saddr();
+
+ return SBI_SUCCESS;
+}
+
+int sbi_mpxy_read_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count)
+{
+ int ret = SBI_SUCCESS;
+ u32 *attr_ptr, end_id;
+ void *shmem_base;
+
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+
+ if (!mpxy_shmem_enabled(ms))
+ return SBI_ERR_NO_SHMEM;
+
+ struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
+ if (!channel)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ /* base attribute id is not a defined std attribute or reserved */
+ if (base_attr_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX &&
+ base_attr_id < SBI_MPXY_ATTR_MSGPROTO_ATTR_START)
+ return SBI_ERR_INVALID_PARAM;
+
+ /* Sanity check for base_attr_id and attr_count */
+ if (!attr_count || (attr_count > (ms->shmem.shmem_size / ATTR_SIZE)))
+ return SBI_ERR_INVALID_PARAM;
+
+ shmem_base = hart_shmem_base(ms);
+ end_id = base_attr_id + attr_count - 1;
+
+ sbi_hart_map_saddr((unsigned long)hart_shmem_base(ms),
+ ms->shmem.shmem_size);
+
+ /* Standard attributes range check */
+ if (mpxy_is_std_attr(base_attr_id)) {
+ if (end_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX) {
+ ret = SBI_EBAD_RANGE;
+ goto out;
+ }
+
+ attr_ptr = (u32 *)&channel->attrs;
+ mpxy_copy_std_attrs((u32 *)shmem_base, &attr_ptr[base_attr_id],
+ attr_count);
+ } else {
+ /**
+ * Even if the message protocol driver does not provide
+ * read attribute callback, return bad range error instead
+ * of not supported to let client distinguish it from channel
+ * id not supported.
+ * Check the complate range supported for message protocol
+ * attributes. Actual supported attributes will be checked
+ * by the message protocol driver.
+ */
+ if (!channel->read_attributes ||
+ end_id > SBI_MPXY_ATTR_MSGPROTO_ATTR_END) {
+ ret = SBI_ERR_BAD_RANGE;
+ goto out;
+ }
+
+ /**
+ * Function expected to return the SBI supported errors
+ * At this point both base attribute id and only the mpxy
+ * supported range been verified. Platform callback must
+ * check if the range requested is supported by message
+ * protocol driver */
+ ret = channel->read_attributes(channel,
+ (u32 *)shmem_base,
+ base_attr_id, attr_count);
+ }
+out:
+ sbi_hart_unmap_saddr();
+ return ret;
+}
+
+/**
+ * Verify the channel standard attribute wrt to write permission
+ * and the value to be set if valid or not.
+ * Only attributes needs to be checked which are defined Read/Write
+ * permission. Other with Readonly permission will result in error.
+ *
+ * Attributes values to be written must also be checked because
+ * before writing a range of attributes, we need to make sure that
+ * either complete range of attributes is written successfully or not
+ * at all.
+ */
+static int mpxy_check_write_std_attr(struct sbi_mpxy_channel *channel,
+ u32 attr_id, u32 attr_val)
+{
+ int ret = SBI_SUCCESS;
+ struct sbi_mpxy_channel_attrs *attrs = &channel->attrs;
+
+ switch(attr_id) {
+ case SBI_MPXY_ATTR_MSI_CONTROL:
+ if (attr_val > 1)
+ ret = SBI_ERR_INVALID_PARAM;
+ if (attr_val == 1 &&
+ (attrs->msi_info.msi_addr_lo == INVALID_ADDR) &&
+ (attrs->msi_info.msi_addr_hi == INVALID_ADDR))
+ ret = SBI_ERR_DENIED;
+ break;
+ case SBI_MPXY_ATTR_MSI_ADDR_LO:
+ case SBI_MPXY_ATTR_MSI_ADDR_HI:
+ case SBI_MPXY_ATTR_MSI_DATA:
+ ret = SBI_SUCCESS;
+ break;
+ case SBI_MPXY_ATTR_EVENTS_STATE_CONTROL:
+ if (attr_val > 1)
+ ret = SBI_ERR_INVALID_PARAM;
+ break;
+ default:
+ /** All RO access attributes falls under default */
+ ret = SBI_ERR_BAD_RANGE;
+ };
+
+ return ret;
+}
+
+/**
+ * Write the attribute value
+ */
+static void mpxy_write_std_attr(struct sbi_mpxy_channel *channel, u32 attr_id,
+ u32 attr_val)
+{
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+
+ struct sbi_mpxy_channel_attrs *attrs = &channel->attrs;
+
+ switch(attr_id) {
+ case SBI_MPXY_ATTR_MSI_CONTROL:
+ if (ms->msi_avail && attr_val <= 1)
+ attrs->msi_control = attr_val;
+ break;
+ case SBI_MPXY_ATTR_MSI_ADDR_LO:
+ if (ms->msi_avail)
+ attrs->msi_info.msi_addr_lo = attr_val;
+ break;
+ case SBI_MPXY_ATTR_MSI_ADDR_HI:
+ if (ms->msi_avail)
+ attrs->msi_info.msi_addr_hi = attr_val;
+ break;
+ case SBI_MPXY_ATTR_MSI_DATA:
+ if (ms->msi_avail)
+ attrs->msi_info.msi_data = attr_val;
+ break;
+ case SBI_MPXY_ATTR_EVENTS_STATE_CONTROL:
+ if (channel->switch_eventsstate && attr_val <= 1) {
+ attrs->eventsstate_ctrl = attr_val;
+ /* message protocol callback to enable/disable
+ * events state reporting. */
+ channel->switch_eventsstate(attr_val);
+ }
+
+ break;
+ };
+}
+
+int sbi_mpxy_write_attrs(u32 channel_id, u32 base_attr_id, u32 attr_count)
+{
+ int ret, mem_idx;
+ void *shmem_base;
+ u32 *mem_ptr, attr_id, end_id, attr_val;
+
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+
+ if (!mpxy_shmem_enabled(ms))
+ return SBI_ERR_NO_SHMEM;
+
+ struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
+ if (!channel)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ /* base attribute id is not a defined std attribute or reserved */
+ if (base_attr_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX &&
+ base_attr_id < SBI_MPXY_ATTR_MSGPROTO_ATTR_START)
+ return SBI_ERR_INVALID_PARAM;
+
+ /* Sanity check for base_attr_id and attr_count */
+ if (!attr_count || (attr_count > (ms->shmem.shmem_size / ATTR_SIZE)))
+ return SBI_ERR_INVALID_PARAM;
+
+ shmem_base = hart_shmem_base(ms);
+ end_id = base_attr_id + attr_count - 1;
+
+ sbi_hart_map_saddr((unsigned long)shmem_base, ms->shmem.shmem_size);
+
+ mem_ptr = (u32 *)shmem_base;
+
+ if (mpxy_is_std_attr(base_attr_id)) {
+ if (end_id >= SBI_MPXY_ATTR_STD_ATTR_MAX_IDX) {
+ ret = SBI_ERR_BAD_RANGE;
+ goto out;
+ }
+
+ /** Verify the attribute ids range and values */
+ mem_idx = 0;
+ for (attr_id = base_attr_id; attr_id <= end_id; attr_id++) {
+ attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
+ ret = mpxy_check_write_std_attr(channel,
+ attr_id, attr_val);
+ if (ret)
+ goto out;
+ }
+
+ /* Write the attribute ids values */
+ mem_idx = 0;
+ for (attr_id = base_attr_id; attr_id <= end_id; attr_id++) {
+ attr_val = le32_to_cpu(mem_ptr[mem_idx++]);
+ mpxy_write_std_attr(channel, attr_id, attr_val);
+ }
+ } else {/**
+ * Message protocol specific attributes:
+ * If attributes belong to message protocol, they
+ * are simply passed to the message protocol driver
+ * callback after checking the valid range.
+ * Attributes contiguous range & permission & other checks
+ * are done by the mpxy and message protocol glue layer.
+ */
+ /**
+ * Even if the message protocol driver does not provide
+ * write attribute callback, return bad range error instead
+ * of not supported to let client distinguish it from channel
+ * id not supported.
+ */
+ if (!channel->write_attributes ||
+ end_id > SBI_MPXY_ATTR_MSGPROTO_ATTR_END) {
+ ret = SBI_ERR_BAD_RANGE;
+ goto out;
+ }
+
+ /**
+ * Function expected to return the SBI supported errors
+ * At this point both base attribute id and only the mpxy
+ * supported range been verified. Platform callback must
+ * check if the range requested is supported by message
+ * protocol driver */
+ ret = channel->write_attributes(channel,
+ (u32 *)shmem_base,
+ base_attr_id, attr_count);
+ }
+out:
+ sbi_hart_unmap_saddr();
+ return ret;
+}
+
+int sbi_mpxy_send_message(u32 channel_id, u8 msg_id,
+ unsigned long msg_data_len,
+ unsigned long *resp_data_len)
+{
+ int ret;
+ void *shmem_base, *resp_buf;
+ u32 resp_bufsize;
+
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+
+ if (!mpxy_shmem_enabled(ms))
+ return SBI_ERR_NO_SHMEM;
+
+ struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
+ if (!channel)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ if (resp_data_len && !channel->send_message_with_response)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ if (!resp_data_len && !channel->send_message_without_response)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ if (msg_data_len > ms->shmem.shmem_size ||
+ msg_data_len > channel->attrs.msg_data_maxlen)
+ return SBI_ERR_INVALID_PARAM;
+
+ shmem_base = hart_shmem_base(ms);
+ sbi_hart_map_saddr((unsigned long)shmem_base, ms->shmem.shmem_size);
+
+ if (resp_data_len) {
+ resp_buf = shmem_base;
+ resp_bufsize = ms->shmem.shmem_size;
+ ret = channel->send_message_with_response(channel, msg_id,
+ shmem_base,
+ msg_data_len,
+ resp_buf,
+ resp_bufsize,
+ resp_data_len);
+ }
+ else {
+ ret = channel->send_message_without_response(channel, msg_id,
+ shmem_base,
+ msg_data_len);
+ }
+
+ sbi_hart_unmap_saddr();
+
+ if (ret == SBI_ERR_TIMEOUT || ret == SBI_ERR_IO)
+ return ret;
+ else if (ret)
+ return SBI_ERR_FAILED;
+
+ if (resp_data_len &&
+ (*resp_data_len > ms->shmem.shmem_size ||
+ *resp_data_len > channel->attrs.msg_data_maxlen))
+ return SBI_ERR_FAILED;
+
+ return SBI_SUCCESS;
+}
+
+int sbi_mpxy_get_notification_events(u32 channel_id, unsigned long *events_len)
+{
+ int ret;
+ void *eventsbuf, *shmem_base;
+
+ struct mpxy_state *ms =
+ sbi_scratch_thishart_offset_ptr(mpxy_state_offset);
+
+ if (!mpxy_shmem_enabled(ms))
+ return SBI_ERR_NO_SHMEM;
+
+ struct sbi_mpxy_channel *channel = mpxy_find_channel(channel_id);
+ if (!channel)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ if (!channel->get_notification_events)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ shmem_base = hart_shmem_base(ms);
+ sbi_hart_map_saddr((unsigned long)shmem_base, ms->shmem.shmem_size);
+ eventsbuf = shmem_base;
+ ret = channel->get_notification_events(channel, eventsbuf,
+ ms->shmem.shmem_size,
+ events_len);
+ sbi_hart_unmap_saddr();
+
+ if (ret)
+ return ret;
+
+ if (*events_len > ms->shmem.shmem_size)
+ return SBI_ERR_FAILED;
+
+ return SBI_SUCCESS;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 15/17] lib: sbi: Implement SBI MPXY extension
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (13 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 14/17] lib: sbi: Add SBI Message Proxy (MPXY) framework Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 16/17] lib: utils: Add simple FDT based MPXY driver framework Anup Patel
` (2 subsequent siblings)
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
Implement the SBI MPXY extension which provides an SBI interface to
the supervisor software for send messages via MPXY framework.
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi/sbi_ecall_interface.h | 10 +++++
lib/sbi/Kconfig | 3 ++
lib/sbi/objects.mk | 3 ++
lib/sbi/sbi_ecall_mpxy.c | 68 +++++++++++++++++++++++++++++++
4 files changed, 84 insertions(+)
create mode 100644 lib/sbi/sbi_ecall_mpxy.c
diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index 90c4ce11..c015ed93 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -35,6 +35,7 @@
#define SBI_EXT_DBTR 0x44425452
#define SBI_EXT_SSE 0x535345
#define SBI_EXT_FWFT 0x46574654
+#define SBI_EXT_MPXY 0x4D505859
/* SBI function IDs for BASE extension*/
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
@@ -410,6 +411,15 @@ enum sbi_sse_state {
#define SBI_SSE_EVENT_GLOBAL_BIT (1 << 15)
#define SBI_SSE_EVENT_PLATFORM_BIT (1 << 14)
+/* SBI function IDs for MPXY extension */
+#define SBI_EXT_MPXY_SET_SHMEM 0x0
+#define SBI_EXT_MPXY_GET_CHANNEL_IDS 0x1
+#define SBI_EXT_MPXY_READ_ATTRS 0x2
+#define SBI_EXT_MPXY_WRITE_ATTRS 0x3
+#define SBI_EXT_MPXY_SEND_MSG_WITH_RESP 0x4
+#define SBI_EXT_MPXY_SEND_MSG_NO_RESP 0x5
+#define SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS 0x6
+
/* SBI base specification related macros */
#define SBI_SPEC_VERSION_MAJOR_OFFSET 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index bd8ba2b6..c6cc04bc 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -66,4 +66,7 @@ config SBI_ECALL_SSE
bool "SSE extension"
default y
+config SBI_ECALL_MPXY
+ bool "MPXY extension"
+ default y
endmenu
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 80b82f8e..12e9e2bd 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -61,6 +61,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_DBTR) += sbi_ecall_dbtr.o
carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_SSE) += ecall_sse
libsbi-objs-$(CONFIG_SBI_ECALL_SSE) += sbi_ecall_sse.o
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_MPXY) += ecall_mpxy
+libsbi-objs-$(CONFIG_SBI_ECALL_MPXY) += sbi_ecall_mpxy.o
+
libsbi-objs-y += sbi_bitmap.o
libsbi-objs-y += sbi_bitops.o
libsbi-objs-y += sbi_console.o
diff --git a/lib/sbi/sbi_ecall_mpxy.c b/lib/sbi/sbi_ecall_mpxy.c
new file mode 100644
index 00000000..5f717b76
--- /dev/null
+++ b/lib/sbi/sbi_ecall_mpxy.c
@@ -0,0 +1,68 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_mpxy.h>
+
+static int sbi_ecall_mpxy_handler(unsigned long extid, unsigned long funcid,
+ struct sbi_trap_regs *regs,
+ struct sbi_ecall_return *out)
+{
+ int ret = 0;
+
+ switch (funcid) {
+ case SBI_EXT_MPXY_SET_SHMEM:
+ ret = sbi_mpxy_set_shmem(regs->a0, regs->a1, regs->a2, regs->a3);
+ break;
+ case SBI_EXT_MPXY_GET_CHANNEL_IDS:
+ ret = sbi_mpxy_get_channel_ids(regs->a0);
+ break;
+ case SBI_EXT_MPXY_READ_ATTRS:
+ ret = sbi_mpxy_read_attrs(regs->a0, regs->a1, regs->a2);
+ break;
+ case SBI_EXT_MPXY_WRITE_ATTRS:
+ ret = sbi_mpxy_write_attrs(regs->a0, regs->a1, regs->a2);
+ break;
+ case SBI_EXT_MPXY_SEND_MSG_WITH_RESP:
+ ret = sbi_mpxy_send_message(regs->a0, regs->a1,
+ regs->a2, &out->value);
+ break;
+ case SBI_EXT_MPXY_SEND_MSG_NO_RESP:
+ ret = sbi_mpxy_send_message(regs->a0, regs->a1, regs->a2,
+ NULL);
+ break;
+ case SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS:
+ ret = sbi_mpxy_get_notification_events(regs->a0, &out->value);
+ break;
+ default:
+ ret = SBI_ENOTSUPP;
+ }
+
+ return ret;
+}
+
+struct sbi_ecall_extension ecall_mpxy;
+
+static int sbi_ecall_mpxy_register_extensions(void)
+{
+ if (!sbi_mpxy_channel_available())
+ return 0;
+
+ return sbi_ecall_register_extension(&ecall_mpxy);
+}
+
+struct sbi_ecall_extension ecall_mpxy = {
+ .extid_start = SBI_EXT_MPXY,
+ .extid_end = SBI_EXT_MPXY,
+ .register_extensions = sbi_ecall_mpxy_register_extensions,
+ .handle = sbi_ecall_mpxy_handler,
+};
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 16/17] lib: utils: Add simple FDT based MPXY driver framework
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (14 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 15/17] lib: sbi: Implement SBI MPXY extension Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-11-29 15:50 ` [PATCH v2 17/17] lib: utils/mpxy: Add RPMI client driver for MPXY Anup Patel
2024-12-06 3:55 ` [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
The generic platform can have multiple MPXY drivers so add a simple
FDT based MPXY driver framework.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mpxy/fdt_mpxy.h | 26 ++++++++++++++++++++++++++
lib/utils/Kconfig | 2 ++
lib/utils/mpxy/Kconfig | 10 ++++++++++
lib/utils/mpxy/fdt_mpxy.c | 22 ++++++++++++++++++++++
lib/utils/mpxy/fdt_mpxy_drivers.carray | 3 +++
lib/utils/mpxy/objects.mk | 11 +++++++++++
platform/generic/configs/defconfig | 1 +
platform/generic/platform.c | 10 ++++++++++
8 files changed, 85 insertions(+)
create mode 100644 include/sbi_utils/mpxy/fdt_mpxy.h
create mode 100644 lib/utils/mpxy/Kconfig
create mode 100644 lib/utils/mpxy/fdt_mpxy.c
create mode 100644 lib/utils/mpxy/fdt_mpxy_drivers.carray
create mode 100644 lib/utils/mpxy/objects.mk
diff --git a/include/sbi_utils/mpxy/fdt_mpxy.h b/include/sbi_utils/mpxy/fdt_mpxy.h
new file mode 100644
index 00000000..2ba9d28f
--- /dev/null
+++ b/include/sbi_utils/mpxy/fdt_mpxy.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#ifndef __FDT_MPXY_H__
+#define __FDT_MPXY_H__
+
+#include <sbi/sbi_types.h>
+#include <sbi_utils/fdt/fdt_driver.h>
+
+#ifdef CONFIG_FDT_MPXY
+
+void fdt_mpxy_init(const void *fdt);
+
+#else
+
+static inline void fdt_mpxy_init(const void *fdt) { }
+
+#endif
+
+#endif
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig
index 002d6f8f..901ba564 100644
--- a/lib/utils/Kconfig
+++ b/lib/utils/Kconfig
@@ -32,4 +32,6 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/sys/Kconfig"
source "$(OPENSBI_SRC_DIR)/lib/utils/timer/Kconfig"
+source "$(OPENSBI_SRC_DIR)/lib/utils/mpxy/Kconfig"
+
endmenu
diff --git a/lib/utils/mpxy/Kconfig b/lib/utils/mpxy/Kconfig
new file mode 100644
index 00000000..d084b09a
--- /dev/null
+++ b/lib/utils/mpxy/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-2-Clause
+
+menu "MPXY Device Support"
+
+config FDT_MPXY
+ bool "FDT based MPXY drivers"
+ depends on FDT
+ default n
+
+endmenu
diff --git a/lib/utils/mpxy/fdt_mpxy.c b/lib/utils/mpxy/fdt_mpxy.c
new file mode 100644
index 00000000..6984ec74
--- /dev/null
+++ b/lib/utils/mpxy/fdt_mpxy.c
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <sbi_utils/mpxy/fdt_mpxy.h>
+
+/* List of FDT MPXY drivers generated at compile time */
+extern const struct fdt_driver *const fdt_mpxy_drivers[];
+
+void fdt_mpxy_init(const void *fdt)
+{
+ /*
+ * Platforms might have multiple MPXY devices or might not
+ * have any MPXY devices so don't fail.
+ */
+ fdt_driver_init_all(fdt, fdt_mpxy_drivers);
+}
diff --git a/lib/utils/mpxy/fdt_mpxy_drivers.carray b/lib/utils/mpxy/fdt_mpxy_drivers.carray
new file mode 100644
index 00000000..3cac0155
--- /dev/null
+++ b/lib/utils/mpxy/fdt_mpxy_drivers.carray
@@ -0,0 +1,3 @@
+HEADER: sbi_utils/mpxy/fdt_mpxy.h
+TYPE: const struct fdt_driver
+NAME: fdt_mpxy_drivers
diff --git a/lib/utils/mpxy/objects.mk b/lib/utils/mpxy/objects.mk
new file mode 100644
index 00000000..43e73c94
--- /dev/null
+++ b/lib/utils/mpxy/objects.mk
@@ -0,0 +1,11 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 Ventana Micro Systems Inc.
+#
+# Authors:
+# Anup Patel <apatel@ventanamicro.com>
+#
+
+libsbiutils-objs-$(CONFIG_FDT_MPXY) += mpxy/fdt_mpxy.o
+libsbiutils-objs-$(CONFIG_FDT_MPXY) += mpxy/fdt_mpxy_drivers.carray.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 384918f9..1f0880ee 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -53,3 +53,4 @@ CONFIG_FDT_SUSPEND_RPMI=y
CONFIG_FDT_TIMER=y
CONFIG_FDT_TIMER_MTIMER=y
CONFIG_FDT_TIMER_PLMT=y
+CONFIG_FDT_MPXY=y
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index 6f830744..f7888b43 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -17,6 +17,7 @@
#include <sbi/sbi_string.h>
#include <sbi/sbi_system.h>
#include <sbi/sbi_tlb.h>
+#include <sbi_utils/mpxy/fdt_mpxy.h>
#include <sbi_utils/cppc/fdt_cppc.h>
#include <sbi_utils/fdt/fdt_domain.h>
#include <sbi_utils/fdt/fdt_fixup.h>
@@ -414,6 +415,14 @@ static uint64_t generic_pmu_xlate_to_mhpmevent(uint32_t event_idx,
return evt_val;
}
+static int generic_mpxy_init(void)
+{
+ const void *fdt = fdt_get_address();
+
+ fdt_mpxy_init(fdt);
+ return 0;
+}
+
const struct sbi_platform_operations platform_ops = {
.cold_boot_allowed = generic_cold_boot_allowed,
.nascent_init = generic_nascent_init,
@@ -430,6 +439,7 @@ const struct sbi_platform_operations platform_ops = {
.get_tlbr_flush_limit = generic_tlbr_flush_limit,
.get_tlb_num_entries = generic_tlb_num_entries,
.timer_init = fdt_timer_init,
+ .mpxy_init = generic_mpxy_init,
.vendor_ext_check = generic_vendor_ext_check,
.vendor_ext_provider = generic_vendor_ext_provider,
};
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 17/17] lib: utils/mpxy: Add RPMI client driver for MPXY
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (15 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 16/17] lib: utils: Add simple FDT based MPXY driver framework Anup Patel
@ 2024-11-29 15:50 ` Anup Patel
2024-12-06 3:55 ` [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
17 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-11-29 15:50 UTC (permalink / raw)
To: opensbi
From: Rahul Pathak <rpathak@ventanamicro.com>
Add a generic RPMI mailbox client driver which provides a MPXY channel.
Initially, this driver only supports RPMI clock service group but can
be extended to support multiple RPMI service groups.
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Co-developed-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/mailbox/rpmi_msgprot.h | 93 +++++
lib/utils/mpxy/Kconfig | 9 +
lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c | 442 +++++++++++++++++++++++
lib/utils/mpxy/objects.mk | 3 +
platform/generic/configs/defconfig | 1 +
5 files changed, 548 insertions(+)
create mode 100644 lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c
diff --git a/include/sbi_utils/mailbox/rpmi_msgprot.h b/include/sbi_utils/mailbox/rpmi_msgprot.h
index f7c80360..9575dc72 100644
--- a/include/sbi_utils/mailbox/rpmi_msgprot.h
+++ b/include/sbi_utils/mailbox/rpmi_msgprot.h
@@ -201,6 +201,7 @@ enum rpmi_servicegroup_id {
RPMI_SRVGRP_SYSTEM_SUSPEND = 0x0003,
RPMI_SRVGRP_HSM = 0x0004,
RPMI_SRVGRP_CPPC = 0x0005,
+ RPMI_SRVGRP_CLOCK = 0x0007,
RPMI_SRVGRP_ID_MAX_COUNT,
/* Reserved range for service groups */
@@ -511,4 +512,96 @@ struct rpmi_cppc_hart_list_resp {
u32 hartid[(RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN) - (sizeof(u32) * 3)) / sizeof(u32)];
};
+/** RPMI Clock ServiceGroup Service IDs */
+enum rpmi_clock_service_id {
+ RPMI_CLOCK_SRV_ENABLE_NOTIFICATION = 0x01,
+ RPMI_CLOCK_SRV_GET_NUM_CLOCKS = 0x02,
+ RPMI_CLOCK_SRV_GET_ATTRIBUTES = 0x03,
+ RPMI_CLOCK_SRV_GET_SUPPORTED_RATES = 0x04,
+ RPMI_CLOCK_SRV_SET_CONFIG = 0x05,
+ RPMI_CLOCK_SRV_GET_CONFIG = 0x06,
+ RPMI_CLOCK_SRV_SET_RATE = 0x07,
+ RPMI_CLOCK_SRV_GET_RATE = 0x08,
+ RPMI_CLOCK_SRV_MAX_COUNT,
+};
+
+struct rpmi_clock_get_num_clocks_resp {
+ s32 status;
+ u32 num_clocks;
+};
+
+struct rpmi_clock_get_attributes_req {
+ u32 clock_id;
+};
+
+struct rpmi_clock_get_attributes_resp {
+ s32 status;
+#define RPMI_CLOCK_FLAGS_FORMAT_POS 30
+#define RPMI_CLOCK_FLAGS_FORMAT_MASK \
+ (3U << RPMI_CLOCK_FLAGS_CLOCK_FORMAT_POS)
+#define RPMI_CLOCK_FLAGS_FORMAT_DISCRETE 0
+#define RPMI_CLOCK_FLAGS_FORMAT_LINEAR 1
+ u32 flags;
+ u32 num_rates;
+ u32 transition_latency;
+ u8 name[16];
+};
+
+struct rpmi_clock_get_supported_rates_req {
+ u32 clock_id;
+ u32 clock_rate_index;
+};
+
+struct rpmi_clock_get_supported_rates_resp {
+ s32 status;
+ u32 flags;
+ u32 remaining;
+ u32 returned;
+ u32 clock_rate[0];
+};
+
+struct rpmi_clock_set_config_req {
+ u32 clock_id;
+#define RPMI_CLOCK_CONFIG_ENABLE (1U << 0)
+ u32 config;
+};
+
+struct rpmi_clock_set_config_resp {
+ s32 status;
+};
+
+struct rpmi_clock_get_config_req {
+ u32 clock_id;
+};
+
+struct rpmi_clock_get_config_resp {
+ s32 status;
+ u32 config;
+};
+
+struct rpmi_clock_set_rate_req {
+ u32 clock_id;
+#define RPMI_CLOCK_SET_RATE_FLAGS_MASK (3U << 0)
+#define RPMI_CLOCK_SET_RATE_FLAGS_ROUND_DOWN 0
+#define RPMI_CLOCK_SET_RATE_FLAGS_ROUND_UP 1
+#define RPMI_CLOCK_SET_RATE_FLAGS_ROUND_PLAT 2
+ u32 flags;
+ u32 clock_rate_low;
+ u32 clock_rate_high;
+};
+
+struct rpmi_clock_set_rate_resp {
+ s32 status;
+};
+
+struct rpmi_clock_get_rate_req {
+ u32 clock_id;
+};
+
+struct rpmi_clock_get_rate_resp {
+ s32 status;
+ u32 clock_rate_low;
+ u32 clock_rate_high;
+};
+
#endif /* !__RPMI_MSGPROT_H__ */
diff --git a/lib/utils/mpxy/Kconfig b/lib/utils/mpxy/Kconfig
index d084b09a..131fb91a 100644
--- a/lib/utils/mpxy/Kconfig
+++ b/lib/utils/mpxy/Kconfig
@@ -7,4 +7,13 @@ config FDT_MPXY
depends on FDT
default n
+if FDT_MPXY
+
+config FDT_MPXY_RPMI_MBOX
+ bool "FDT MPXY mailbox client driver"
+ depends on FDT_MAILBOX
+ default n
+
+endif
+
endmenu
diff --git a/lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c b/lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c
new file mode 100644
index 00000000..c09a4c52
--- /dev/null
+++ b/lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c
@@ -0,0 +1,442 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Rahul Pathak <rpathak@ventanamicro.com>
+ * Anup Patel <apatel@ventanamicro.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/sbi_mpxy.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/mpxy/fdt_mpxy.h>
+#include <sbi_utils/mailbox/fdt_mailbox.h>
+#include <sbi_utils/mailbox/rpmi_msgprot.h>
+#include <sbi/sbi_console.h>
+
+#define RPMI_MAJOR_VER (1)
+#define RPMI_MINOR_VER (0)
+
+/** Convert the mpxy attribute ID to attribute array index */
+#define attr_id2index(attr_id) (attr_id - SBI_MPXY_ATTR_MSGPROTO_ATTR_START)
+
+enum mpxy_msgprot_rpmi_attr_id {
+ MPXY_MSGPROT_RPMI_ATTR_SERVICEGROUP_ID = SBI_MPXY_ATTR_MSGPROTO_ATTR_START,
+ MPXY_MSGPROT_RPMI_ATTR_SERVICEGROUP_VERSION,
+ MPXY_MSGPROT_RPMI_ATTR_MAX_ID,
+};
+
+/**
+ * MPXY message protocol attributes for RPMI
+ * Order of attribute fields must follow the
+ * attribute IDs in `enum mpxy_msgprot_rpmi_attr_id`
+ */
+struct mpxy_rpmi_channel_attrs {
+ u32 servicegrp_id;
+ u32 servicegrp_ver;
+};
+
+/* RPMI mbox data per service group */
+struct mpxy_mbox_data {
+ u32 servicegrp_id;
+ u32 num_services;
+ u32 notifications_support;
+ void *priv_data;
+};
+
+/* RPMI service data per service group */
+struct rpmi_service_data {
+ u8 id;
+ u32 min_tx_len;
+ u32 max_tx_len;
+ u32 min_rx_len;
+ u32 max_rx_len;
+};
+
+/**
+ * MPXY mbox instance per MPXY channel. This ties
+ * an MPXY channel with an RPMI Service group.
+ */
+struct mpxy_mbox {
+ struct mbox_chan *chan;
+ struct mpxy_mbox_data *mbox_data;
+ struct mpxy_rpmi_channel_attrs msgprot_attrs;
+ struct sbi_mpxy_channel channel;
+};
+
+/** Make sure all attributes are packed for direct memcpy */
+#define assert_field_offset(field, attr_offset) \
+ _Static_assert( \
+ ((offsetof(struct mpxy_rpmi_channel_attrs, field)) / \
+ sizeof(u32)) == (attr_offset - SBI_MPXY_ATTR_MSGPROTO_ATTR_START),\
+ "field " #field \
+ " from struct mpxy_rpmi_channel_attrs invalid offset, expected " #attr_offset)
+
+assert_field_offset(servicegrp_id, MPXY_MSGPROT_RPMI_ATTR_SERVICEGROUP_ID);
+
+/**
+ * Discover the RPMI service data using message_id
+ * MPXY message_id == RPMI service_id
+ */
+static struct rpmi_service_data *mpxy_find_rpmi_srvid(u32 message_id,
+ struct mpxy_mbox_data *mbox_data)
+{
+ int mid = 0;
+ struct rpmi_service_data *srv = mbox_data->priv_data;
+ for (mid = 0; srv[mid].id < mbox_data->num_services; mid++) {
+ if (srv[mid].id == (u8)message_id)
+ return &srv[mid];
+ }
+
+ return NULL;
+}
+
+/** Copy attributes word size */
+static void mpxy_copy_attrs(u32 *outmem, u32 *inmem, u32 count)
+{
+ u32 idx;
+ for (idx = 0; idx < count; idx++)
+ outmem[idx] = cpu_to_le32(inmem[idx]);
+}
+
+static int mpxy_mbox_read_attributes(struct sbi_mpxy_channel *channel,
+ u32 *outmem, u32 base_attr_id,
+ u32 attr_count)
+{
+ u32 end_id;
+ struct mpxy_mbox *rmb =
+ container_of(channel, struct mpxy_mbox, channel);
+
+ u32 *attr_array = (u32 *)&rmb->msgprot_attrs;
+
+ end_id = base_attr_id + attr_count - 1;
+
+ if (end_id >= MPXY_MSGPROT_RPMI_ATTR_MAX_ID)
+ return SBI_EBAD_RANGE;
+
+ mpxy_copy_attrs(outmem, &attr_array[attr_id2index(base_attr_id)],
+ attr_count);
+
+ return SBI_OK;
+}
+
+/**
+ * Verify the channel standard attribute wrt to write permission
+ * and the value to be set if valid or not.
+ * Only attributes needs to be checked which are defined Read/Write
+ * permission. Other with Readonly permission will result in error.
+ *
+ * Attributes values to be written must also be checked because
+ * before writing a range of attributes, we need to make sure that
+ * either complete range of attributes is written successfully or not
+ * at all.
+ */
+static int mpxy_check_write_attr(u32 attr_id, u32 attr_val)
+{
+ int ret = SBI_OK;
+
+ switch(attr_id) {
+ /** All RO access attributes falls under default */
+ default:
+ ret = SBI_EBAD_RANGE;
+ };
+
+ return ret;
+}
+
+static void mpxy_write_attr(struct mpxy_rpmi_channel_attrs *attrs,
+ u32 attr_id,
+ u32 attr_val)
+{
+ /* No writable attributes in RPMI */
+}
+
+static int mpxy_mbox_write_attributes(struct sbi_mpxy_channel *channel,
+ u32 *outmem, u32 base_attr_id,
+ u32 attr_count)
+{
+ int ret, mem_idx;
+ u32 end_id, attr_val, idx;
+ struct mpxy_mbox *rmb =
+ container_of(channel, struct mpxy_mbox, channel);
+
+ end_id = base_attr_id + attr_count - 1;
+
+ if (end_id >= MPXY_MSGPROT_RPMI_ATTR_MAX_ID)
+ return SBI_EBAD_RANGE;
+
+ mem_idx = 0;
+ for (idx = base_attr_id; idx <= end_id; idx++) {
+ attr_val = le32_to_cpu(outmem[mem_idx++]);
+ ret = mpxy_check_write_attr(idx, attr_val);
+ if (ret)
+ return ret;
+ }
+
+ mem_idx = 0;
+ for (idx = base_attr_id; idx <= end_id; idx++) {
+ attr_val = le32_to_cpu(outmem[mem_idx++]);
+ mpxy_write_attr(&rmb->msgprot_attrs, idx, attr_val);
+ }
+
+ return SBI_OK;
+}
+
+static int __mpxy_mbox_send_message(struct sbi_mpxy_channel *channel,
+ u32 message_id, void *tx, u32 tx_len,
+ void *rx, u32 rx_max_len,
+ unsigned long *ack_len)
+{
+ int ret;
+ u32 rx_len = 0;
+ struct mbox_xfer xfer;
+ struct rpmi_message_args args = {0};
+ struct mpxy_mbox *rmb =
+ container_of(channel, struct mpxy_mbox, channel);
+ struct rpmi_service_data *srv =
+ mpxy_find_rpmi_srvid(message_id, rmb->mbox_data);
+ if (!srv)
+ return SBI_ENOTSUPP;
+
+ /** message data size to be sent is in the
+ * supported service data size range */
+ if (tx_len < srv->min_tx_len || tx_len > srv->max_tx_len)
+ return SBI_EFAIL;
+
+ if (ack_len) {
+ /** MPXY buffer cannnot hold service min response data */
+ if (rx_max_len < srv->min_rx_len)
+ return SBI_EFAIL;
+
+ /* Max rx data size it can expect */
+ if (srv->max_rx_len < channel->attrs.msg_data_maxlen)
+ rx_len = srv->max_rx_len;
+ else
+ rx_len = channel->attrs.msg_data_maxlen;
+
+ args.type = RPMI_MSG_NORMAL_REQUEST;
+ args.flags = (rx) ? 0 : RPMI_MSG_FLAGS_NO_RX;
+ args.service_id = srv->id;
+ mbox_xfer_init_txrx(&xfer, &args,
+ tx, tx_len, RPMI_DEF_TX_TIMEOUT,
+ rx, rx_len, RPMI_DEF_RX_TIMEOUT);
+ }
+ else {
+ args.type = RPMI_MSG_POSTED_REQUEST;
+ args.flags = RPMI_MSG_FLAGS_NO_RX;
+ args.service_id = srv->id;
+ mbox_xfer_init_tx(&xfer, &args,
+ tx, tx_len, RPMI_DEF_TX_TIMEOUT);
+ }
+
+ ret = mbox_chan_xfer(rmb->chan, &xfer);
+ if (ret)
+ return ret;
+
+ if (ack_len)
+ *ack_len = args.rx_data_len;
+
+ return SBI_OK;
+}
+
+static int mpxy_mbox_send_message_withresp(struct sbi_mpxy_channel *channel,
+ u32 message_id, void *tx, u32 tx_len,
+ void *rx, u32 rx_max_len,
+ unsigned long *ack_len)
+{
+ return __mpxy_mbox_send_message(channel, message_id, tx, tx_len,
+ rx, rx_max_len, ack_len);
+}
+
+static int mpxy_mbox_send_message_withoutresp(struct sbi_mpxy_channel *channel,
+ u32 message_id, void *tx, u32 tx_len)
+{
+ return __mpxy_mbox_send_message(channel, message_id, tx, tx_len,
+ NULL, 0, NULL);
+}
+
+static int mpxy_mbox_get_notifications(struct sbi_mpxy_channel *channel,
+ void *eventsbuf, u32 bufsize,
+ unsigned long *events_len)
+{
+ return SBI_ENOTSUPP;
+}
+
+static int mpxy_mbox_init(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ int rc, len;
+ const fdt32_t *val;
+ u32 channel_id;
+ struct mpxy_mbox *rmb;
+ struct mbox_chan *chan;
+ const struct mpxy_mbox_data *data = match->data;
+
+ /* Allocate context for RPXY mbox client */
+ rmb = sbi_zalloc(sizeof(*rmb));
+ if (!rmb)
+ return SBI_ENOMEM;
+
+ /*
+ * If channel request failed then other end does not support
+ * service group so do nothing.
+ */
+ rc = fdt_mailbox_request_chan(fdt, nodeoff, 0, &chan);
+ if (rc) {
+ sbi_free(rmb);
+ return SBI_ENODEV;
+ }
+
+ /* Match channel service group id */
+ if (data->servicegrp_id != chan->chan_args[0]) {
+ mbox_controller_free_chan(chan);
+ sbi_free(rmb);
+ return SBI_EINVAL;
+ }
+
+ /*
+ * The "riscv,sbi-mpxy-channel-id" DT property is mandatory
+ * for MPXY RPMI mailbox client driver so if this is not
+ * present then try other drivers.
+ */
+ val = fdt_getprop(fdt, nodeoff, "riscv,sbi-mpxy-channel-id", &len);
+ if (len > 0 && val)
+ channel_id = fdt32_to_cpu(*val);
+ else {
+ mbox_controller_free_chan(chan);
+ sbi_free(rmb);
+ return SBI_ENODEV;
+ }
+
+ /* Setup MPXY mbox client */
+ /* Channel ID*/
+ rmb->channel.channel_id = channel_id;
+ /* Callback for read RPMI attributes */
+ rmb->channel.read_attributes = mpxy_mbox_read_attributes;
+ /* Callback for write RPMI attributes */
+ rmb->channel.write_attributes = mpxy_mbox_write_attributes;
+ /* Callback for sending RPMI message */
+ rmb->channel.send_message_with_response =
+ mpxy_mbox_send_message_withresp;
+ rmb->channel.send_message_without_response =
+ mpxy_mbox_send_message_withoutresp;
+ /* Callback to get RPMI notifications */
+ rmb->channel.get_notification_events = mpxy_mbox_get_notifications;
+
+ /* No callback to switch events state data */
+ rmb->channel.switch_eventsstate = NULL;
+
+ /* RPMI Message Protocol ID */
+ rmb->channel.attrs.msg_proto_id = SBI_MPXY_MSGPROTO_RPMI_ID;
+ /* RPMI Message Protocol Version */
+ rmb->channel.attrs.msg_proto_version =
+ SBI_MPXY_MSGPROTO_VERSION(RPMI_MAJOR_VER, RPMI_MINOR_VER);
+
+ /* RPMI supported max message data length(bytes), same for
+ * all service groups */
+ rmb->channel.attrs.msg_data_maxlen =
+ RPMI_MSG_DATA_SIZE(RPMI_SLOT_SIZE_MIN);
+ /* RPMI message send timeout(milliseconds)
+ * same for all service groups */
+ rmb->channel.attrs.msg_send_timeout = RPMI_DEF_TX_TIMEOUT;
+ rmb->channel.attrs.msg_completion_timeout =
+ RPMI_DEF_TX_TIMEOUT + RPMI_DEF_RX_TIMEOUT;
+
+ /* RPMI message protocol attributes */
+ rmb->msgprot_attrs.servicegrp_id = data->servicegrp_id;
+ rmb->msgprot_attrs.servicegrp_ver =
+ SBI_MPXY_MSGPROTO_VERSION(RPMI_MAJOR_VER, RPMI_MINOR_VER);
+
+ rmb->mbox_data = (struct mpxy_mbox_data *)data;
+ rmb->chan = chan;
+
+ /* Register RPXY service group */
+ rc = sbi_mpxy_register_channel(&rmb->channel);
+ if (rc) {
+ mbox_controller_free_chan(chan);
+ sbi_free(rmb);
+ return rc;
+ }
+
+ return SBI_OK;
+}
+
+static struct rpmi_service_data clock_services[] = {
+{
+ .id = RPMI_CLOCK_SRV_ENABLE_NOTIFICATION,
+ .min_tx_len = sizeof(struct rpmi_enable_notification_req),
+ .max_tx_len = sizeof(struct rpmi_enable_notification_req),
+ .min_rx_len = sizeof(struct rpmi_enable_notification_resp),
+ .max_rx_len = sizeof(struct rpmi_enable_notification_resp),
+},
+{
+ .id = RPMI_CLOCK_SRV_GET_NUM_CLOCKS,
+ .min_tx_len = 0,
+ .max_tx_len = 0,
+ .min_rx_len = sizeof(struct rpmi_clock_get_num_clocks_resp),
+ .max_rx_len = sizeof(struct rpmi_clock_get_num_clocks_resp),
+},
+{
+ .id = RPMI_CLOCK_SRV_GET_ATTRIBUTES,
+ .min_tx_len = sizeof(struct rpmi_clock_get_attributes_req),
+ .max_tx_len = sizeof(struct rpmi_clock_get_attributes_req),
+ .min_rx_len = sizeof(struct rpmi_clock_get_attributes_resp),
+ .max_rx_len = sizeof(struct rpmi_clock_get_attributes_resp),
+},
+{
+ .id = RPMI_CLOCK_SRV_GET_SUPPORTED_RATES,
+ .min_tx_len = sizeof(struct rpmi_clock_get_supported_rates_req),
+ .max_tx_len = sizeof(struct rpmi_clock_get_supported_rates_req),
+ .min_rx_len = sizeof(struct rpmi_clock_get_supported_rates_resp),
+ .max_rx_len = -1U,
+},
+{
+ .id = RPMI_CLOCK_SRV_SET_CONFIG,
+ .min_tx_len = sizeof(struct rpmi_clock_set_config_req),
+ .max_tx_len = sizeof(struct rpmi_clock_set_config_req),
+ .min_rx_len = sizeof(struct rpmi_clock_set_config_resp),
+ .max_rx_len = sizeof(struct rpmi_clock_set_config_resp),
+},
+{
+ .id = RPMI_CLOCK_SRV_GET_CONFIG,
+ .min_tx_len = sizeof(struct rpmi_clock_get_config_req),
+ .max_tx_len = sizeof(struct rpmi_clock_get_config_req),
+ .min_rx_len = sizeof(struct rpmi_clock_get_config_resp),
+ .max_rx_len = sizeof(struct rpmi_clock_get_config_resp),
+},
+{
+ .id = RPMI_CLOCK_SRV_SET_RATE,
+ .min_tx_len = sizeof(struct rpmi_clock_set_rate_req),
+ .max_tx_len = sizeof(struct rpmi_clock_set_rate_req),
+ .min_rx_len = sizeof(struct rpmi_clock_set_rate_resp),
+ .max_rx_len = sizeof(struct rpmi_clock_set_rate_resp),
+},
+{
+ .id = RPMI_CLOCK_SRV_GET_RATE,
+ .min_tx_len = sizeof(struct rpmi_clock_get_rate_req),
+ .max_tx_len = sizeof(struct rpmi_clock_get_rate_req),
+ .min_rx_len = sizeof(struct rpmi_clock_get_rate_resp),
+ .max_rx_len = sizeof(struct rpmi_clock_get_rate_resp),
+},
+};
+
+static struct mpxy_mbox_data clock_data = {
+ .servicegrp_id = RPMI_SRVGRP_CLOCK,
+ .num_services = RPMI_CLOCK_SRV_MAX_COUNT,
+ .notifications_support = 1,
+ .priv_data = clock_services,
+};
+
+static const struct fdt_match mpxy_mbox_match[] = {
+ { .compatible = "riscv,rpmi-mpxy-clock", .data = &clock_data },
+ { },
+};
+
+struct fdt_driver fdt_mpxy_rpmi_mbox = {
+ .match_table = mpxy_mbox_match,
+ .init = mpxy_mbox_init,
+};
diff --git a/lib/utils/mpxy/objects.mk b/lib/utils/mpxy/objects.mk
index 43e73c94..ccb28b55 100644
--- a/lib/utils/mpxy/objects.mk
+++ b/lib/utils/mpxy/objects.mk
@@ -9,3 +9,6 @@
libsbiutils-objs-$(CONFIG_FDT_MPXY) += mpxy/fdt_mpxy.o
libsbiutils-objs-$(CONFIG_FDT_MPXY) += mpxy/fdt_mpxy_drivers.carray.o
+
+carray-fdt_mpxy_drivers-$(CONFIG_FDT_MPXY_RPMI_MBOX) += fdt_mpxy_rpmi_mbox
+libsbiutils-objs-$(CONFIG_FDT_MPXY_RPMI_MBOX) += mpxy/fdt_mpxy_rpmi_mbox.o
diff --git a/platform/generic/configs/defconfig b/platform/generic/configs/defconfig
index 1f0880ee..e23b38b2 100644
--- a/platform/generic/configs/defconfig
+++ b/platform/generic/configs/defconfig
@@ -54,3 +54,4 @@ CONFIG_FDT_TIMER=y
CONFIG_FDT_TIMER_MTIMER=y
CONFIG_FDT_TIMER_PLMT=y
CONFIG_FDT_MPXY=y
+CONFIG_FDT_MPXY_RPMI_MBOX=y
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
` (16 preceding siblings ...)
2024-11-29 15:50 ` [PATCH v2 17/17] lib: utils/mpxy: Add RPMI client driver for MPXY Anup Patel
@ 2024-12-06 3:55 ` Anup Patel
2024-12-06 5:08 ` Samuel Holland
17 siblings, 1 reply; 23+ messages in thread
From: Anup Patel @ 2024-12-06 3:55 UTC (permalink / raw)
To: opensbi
On Fri, Nov 29, 2024 at 9:21?PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> This series adds RPMI and SBI MPXY support for OpenSBI. The RPMI service
> groups supported include system reset, system suspend, HSM, CPPC, and
> clock. The RPMI clock serivice group is exposed to supervisor software
> as an MPXY channel.
>
> These patches can also be found in the rpmi_mpxy_v2 branch at:
> https://github.com/avpatel/opensbi.git
>
> To test these patches, use the dev-upstream branch of the following repos:
> * https://github.com/ventanamicro/qemu.git
> * https://github.com/ventanamicro/linux.git
>
> To enable QEMU RPMI emulation (using librpmi) for virt machine, use
> "virt,rpmi=on" as the QEMU machine name.
>
> Changes since v1:
> - Rebased on latest OpenSBI
> - Use the recently introduced helpers for generic driver initialization
> - Updated RPMI drivers to match the latest RPMI specification
> - Don't support fixed number of channels in RPMI shared memory mailbox driver
> - Added new patch9 for support RPMI HSM based FDT fixup
> - Improved arrangment of barrier in __smq_rx() and __smq_tx()
>
> Anup Patel (8):
> lib: utils/mailbox: Add generic mailbox library
> lib: utils/mailbox: Add simple FDT based mailbox framework
> lib: utils: Add simple FDT based system suspend driver framework
> lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
> lib: utils: Add simple FDT based HSM driver framework
> lib: utils: Add simple FDT based CPPC driver framework
> lib: sbi: Implement SBI MPXY extension
> lib: utils: Add simple FDT based MPXY driver framework
>
> Rahul Pathak (5):
> lib: Increase ROOT_REGION_MAX to accomodate more memregions
> lib/utils: Add RPMI messaging protocol and shared memory transport
> support
> lib/utils: reset: Add RPMI System Reset driver
> lib: sbi: Add SBI Message Proxy (MPXY) framework
> lib: utils/mpxy: Add RPMI client driver for MPXY
>
> Subrahmanya Lingappa (4):
> lib: utils/suspend: Add RPMI system suspend driver
> lib: sbi: Add optional resume address to hart suspend
> lib: utils/hsm: Add RPMI HSM driver
> lib: utils/cppc: Add RPMI CPPC driver
We plan to include the RPMI and MPXY drivers as experimental
for the upcoming OpenSBI v1.6 release at the end of this month.
There is still more work required in improving these drivers and
related frameworks but that can happen incrementally over time.
Applied this series to the riscv/opensi repo.
Thanks,
Anup
>
> include/sbi/sbi_ecall_interface.h | 12 +
> include/sbi/sbi_error.h | 15 +-
> include/sbi/sbi_hsm.h | 6 +-
> include/sbi/sbi_mpxy.h | 183 +++++
> include/sbi/sbi_platform.h | 17 +
> include/sbi_utils/cppc/fdt_cppc.h | 26 +
> include/sbi_utils/fdt/fdt_fixup.h | 15 +
> include/sbi_utils/hsm/fdt_hsm.h | 26 +
> include/sbi_utils/mailbox/fdt_mailbox.h | 35 +
> include/sbi_utils/mailbox/mailbox.h | 180 +++++
> include/sbi_utils/mailbox/rpmi_mailbox.h | 32 +
> include/sbi_utils/mailbox/rpmi_msgprot.h | 607 +++++++++++++++
> include/sbi_utils/mpxy/fdt_mpxy.h | 26 +
> include/sbi_utils/suspend/fdt_suspend.h | 26 +
> lib/sbi/Kconfig | 3 +
> lib/sbi/objects.mk | 4 +
> lib/sbi/sbi_domain.c | 2 +-
> lib/sbi/sbi_ecall_mpxy.c | 68 ++
> lib/sbi/sbi_hsm.c | 6 +-
> lib/sbi/sbi_init.c | 6 +
> lib/sbi/sbi_mpxy.c | 698 +++++++++++++++++
> lib/utils/Kconfig | 10 +
> lib/utils/cppc/Kconfig | 19 +
> lib/utils/cppc/fdt_cppc.c | 22 +
> lib/utils/cppc/fdt_cppc_drivers.carray | 3 +
> lib/utils/cppc/fdt_cppc_rpmi.c | 377 +++++++++
> lib/utils/cppc/objects.mk | 14 +
> lib/utils/fdt/fdt_fixup.c | 33 +
> lib/utils/hsm/Kconfig | 19 +
> lib/utils/hsm/fdt_hsm.c | 22 +
> lib/utils/hsm/fdt_hsm_drivers.carray | 3 +
> lib/utils/hsm/fdt_hsm_rpmi.c | 362 +++++++++
> lib/utils/hsm/objects.mk | 14 +
> lib/utils/mailbox/Kconfig | 29 +
> lib/utils/mailbox/fdt_mailbox.c | 96 +++
> lib/utils/mailbox/fdt_mailbox_drivers.carray | 5 +
> lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c | 773 +++++++++++++++++++
> lib/utils/mailbox/mailbox.c | 138 ++++
> lib/utils/mailbox/objects.mk | 18 +
> lib/utils/mailbox/rpmi_mailbox.c | 91 +++
> lib/utils/mpxy/Kconfig | 19 +
> lib/utils/mpxy/fdt_mpxy.c | 22 +
> lib/utils/mpxy/fdt_mpxy_drivers.carray | 3 +
> lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c | 442 +++++++++++
> lib/utils/mpxy/objects.mk | 14 +
> lib/utils/reset/Kconfig | 5 +
> lib/utils/reset/fdt_reset_rpmi.c | 141 ++++
> lib/utils/reset/objects.mk | 3 +
> lib/utils/suspend/Kconfig | 19 +
> lib/utils/suspend/fdt_suspend.c | 22 +
> lib/utils/suspend/fdt_suspend_drivers.carray | 3 +
> lib/utils/suspend/fdt_suspend_rpmi.c | 138 ++++
> lib/utils/suspend/objects.mk | 14 +
> platform/generic/allwinner/sun20i-d1.c | 2 +-
> platform/generic/configs/defconfig | 12 +
> platform/generic/platform.c | 16 +
> 56 files changed, 4903 insertions(+), 13 deletions(-)
> create mode 100644 include/sbi/sbi_mpxy.h
> create mode 100644 include/sbi_utils/cppc/fdt_cppc.h
> create mode 100644 include/sbi_utils/hsm/fdt_hsm.h
> create mode 100644 include/sbi_utils/mailbox/fdt_mailbox.h
> create mode 100644 include/sbi_utils/mailbox/mailbox.h
> create mode 100644 include/sbi_utils/mailbox/rpmi_mailbox.h
> create mode 100644 include/sbi_utils/mailbox/rpmi_msgprot.h
> create mode 100644 include/sbi_utils/mpxy/fdt_mpxy.h
> create mode 100644 include/sbi_utils/suspend/fdt_suspend.h
> create mode 100644 lib/sbi/sbi_ecall_mpxy.c
> create mode 100644 lib/sbi/sbi_mpxy.c
> create mode 100644 lib/utils/cppc/Kconfig
> create mode 100644 lib/utils/cppc/fdt_cppc.c
> create mode 100644 lib/utils/cppc/fdt_cppc_drivers.carray
> create mode 100644 lib/utils/cppc/fdt_cppc_rpmi.c
> create mode 100644 lib/utils/cppc/objects.mk
> create mode 100644 lib/utils/hsm/Kconfig
> create mode 100644 lib/utils/hsm/fdt_hsm.c
> create mode 100644 lib/utils/hsm/fdt_hsm_drivers.carray
> create mode 100644 lib/utils/hsm/fdt_hsm_rpmi.c
> create mode 100644 lib/utils/hsm/objects.mk
> create mode 100644 lib/utils/mailbox/Kconfig
> create mode 100644 lib/utils/mailbox/fdt_mailbox.c
> create mode 100644 lib/utils/mailbox/fdt_mailbox_drivers.carray
> create mode 100644 lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
> create mode 100644 lib/utils/mailbox/mailbox.c
> create mode 100644 lib/utils/mailbox/objects.mk
> create mode 100644 lib/utils/mailbox/rpmi_mailbox.c
> create mode 100644 lib/utils/mpxy/Kconfig
> create mode 100644 lib/utils/mpxy/fdt_mpxy.c
> create mode 100644 lib/utils/mpxy/fdt_mpxy_drivers.carray
> create mode 100644 lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c
> create mode 100644 lib/utils/mpxy/objects.mk
> create mode 100644 lib/utils/reset/fdt_reset_rpmi.c
> create mode 100644 lib/utils/suspend/Kconfig
> create mode 100644 lib/utils/suspend/fdt_suspend.c
> create mode 100644 lib/utils/suspend/fdt_suspend_drivers.carray
> create mode 100644 lib/utils/suspend/fdt_suspend_rpmi.c
> create mode 100644 lib/utils/suspend/objects.mk
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI
2024-12-06 3:55 ` [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
@ 2024-12-06 5:08 ` Samuel Holland
2024-12-06 11:32 ` Anup Patel
0 siblings, 1 reply; 23+ messages in thread
From: Samuel Holland @ 2024-12-06 5:08 UTC (permalink / raw)
To: opensbi
Hi Anup,
On 2024-12-05 9:55 PM, Anup Patel wrote:
> On Fri, Nov 29, 2024 at 9:21?PM Anup Patel <apatel@ventanamicro.com> wrote:
>>
>> This series adds RPMI and SBI MPXY support for OpenSBI. The RPMI service
>> groups supported include system reset, system suspend, HSM, CPPC, and
>> clock. The RPMI clock serivice group is exposed to supervisor software
>> as an MPXY channel.
>>
>> These patches can also be found in the rpmi_mpxy_v2 branch at:
>> https://github.com/avpatel/opensbi.git
>>
>> To test these patches, use the dev-upstream branch of the following repos:
>> * https://github.com/ventanamicro/qemu.git
>> * https://github.com/ventanamicro/linux.git
>>
>> To enable QEMU RPMI emulation (using librpmi) for virt machine, use
>> "virt,rpmi=on" as the QEMU machine name.
>>
>> Changes since v1:
>> - Rebased on latest OpenSBI
>> - Use the recently introduced helpers for generic driver initialization
>> - Updated RPMI drivers to match the latest RPMI specification
>> - Don't support fixed number of channels in RPMI shared memory mailbox driver
>> - Added new patch9 for support RPMI HSM based FDT fixup
>> - Improved arrangment of barrier in __smq_rx() and __smq_tx()
>>
>> Anup Patel (8):
>> lib: utils/mailbox: Add generic mailbox library
>> lib: utils/mailbox: Add simple FDT based mailbox framework
>> lib: utils: Add simple FDT based system suspend driver framework
>> lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
>> lib: utils: Add simple FDT based HSM driver framework
>> lib: utils: Add simple FDT based CPPC driver framework
>> lib: sbi: Implement SBI MPXY extension
>> lib: utils: Add simple FDT based MPXY driver framework
>>
>> Rahul Pathak (5):
>> lib: Increase ROOT_REGION_MAX to accomodate more memregions
>> lib/utils: Add RPMI messaging protocol and shared memory transport
>> support
>> lib/utils: reset: Add RPMI System Reset driver
>> lib: sbi: Add SBI Message Proxy (MPXY) framework
>> lib: utils/mpxy: Add RPMI client driver for MPXY
>>
>> Subrahmanya Lingappa (4):
>> lib: utils/suspend: Add RPMI system suspend driver
>> lib: sbi: Add optional resume address to hart suspend
>> lib: utils/hsm: Add RPMI HSM driver
>> lib: utils/cppc: Add RPMI CPPC driver
>
> We plan to include the RPMI and MPXY drivers as experimental
> for the upcoming OpenSBI v1.6 release at the end of this month.
> There is still more work required in improving these drivers and
> related frameworks but that can happen incrementally over time.
I haven't taken the time to fully review this series yet because it's 5000 lines
of new code and the RPMI spec isn't even frozen, but I have at least two major
concerns.
1) Where is the documentation for the devicetree compatible strings added by
this series? I don't see any attempt to get the bindings reviewed and accepted.
https://lore.kernel.org/linux-devicetree/?q=rpmi shows nothing. This isn't
something that can just be changed incrementally. It's not acceptable to break
DT ABI. It's not okay to unilaterally make up a devicetree interface without
documenting it and getting feedback through the appropriate process. This is
especially true since OpenSBI isn't the owner of the RPMI spec.
2) OpenSBI absolutely must not claim to implement MPXY MSG_PROT_ID 0 (RPMI)
version 1.0. That specification does not exist. RPMI is not frozen and is still
actively undergoing changes. If this is an experimental MPXY protocol, it should
use an experimental message protocol ID.
I have no problem with merging experimental code and iterating on it, but such
code must not create ABI surface that has stability guarantees.
Regards,
Samuel
> Applied this series to the riscv/opensi repo.
>
> Thanks,
> Anup
>
>>
>> include/sbi/sbi_ecall_interface.h | 12 +
>> include/sbi/sbi_error.h | 15 +-
>> include/sbi/sbi_hsm.h | 6 +-
>> include/sbi/sbi_mpxy.h | 183 +++++
>> include/sbi/sbi_platform.h | 17 +
>> include/sbi_utils/cppc/fdt_cppc.h | 26 +
>> include/sbi_utils/fdt/fdt_fixup.h | 15 +
>> include/sbi_utils/hsm/fdt_hsm.h | 26 +
>> include/sbi_utils/mailbox/fdt_mailbox.h | 35 +
>> include/sbi_utils/mailbox/mailbox.h | 180 +++++
>> include/sbi_utils/mailbox/rpmi_mailbox.h | 32 +
>> include/sbi_utils/mailbox/rpmi_msgprot.h | 607 +++++++++++++++
>> include/sbi_utils/mpxy/fdt_mpxy.h | 26 +
>> include/sbi_utils/suspend/fdt_suspend.h | 26 +
>> lib/sbi/Kconfig | 3 +
>> lib/sbi/objects.mk | 4 +
>> lib/sbi/sbi_domain.c | 2 +-
>> lib/sbi/sbi_ecall_mpxy.c | 68 ++
>> lib/sbi/sbi_hsm.c | 6 +-
>> lib/sbi/sbi_init.c | 6 +
>> lib/sbi/sbi_mpxy.c | 698 +++++++++++++++++
>> lib/utils/Kconfig | 10 +
>> lib/utils/cppc/Kconfig | 19 +
>> lib/utils/cppc/fdt_cppc.c | 22 +
>> lib/utils/cppc/fdt_cppc_drivers.carray | 3 +
>> lib/utils/cppc/fdt_cppc_rpmi.c | 377 +++++++++
>> lib/utils/cppc/objects.mk | 14 +
>> lib/utils/fdt/fdt_fixup.c | 33 +
>> lib/utils/hsm/Kconfig | 19 +
>> lib/utils/hsm/fdt_hsm.c | 22 +
>> lib/utils/hsm/fdt_hsm_drivers.carray | 3 +
>> lib/utils/hsm/fdt_hsm_rpmi.c | 362 +++++++++
>> lib/utils/hsm/objects.mk | 14 +
>> lib/utils/mailbox/Kconfig | 29 +
>> lib/utils/mailbox/fdt_mailbox.c | 96 +++
>> lib/utils/mailbox/fdt_mailbox_drivers.carray | 5 +
>> lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c | 773 +++++++++++++++++++
>> lib/utils/mailbox/mailbox.c | 138 ++++
>> lib/utils/mailbox/objects.mk | 18 +
>> lib/utils/mailbox/rpmi_mailbox.c | 91 +++
>> lib/utils/mpxy/Kconfig | 19 +
>> lib/utils/mpxy/fdt_mpxy.c | 22 +
>> lib/utils/mpxy/fdt_mpxy_drivers.carray | 3 +
>> lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c | 442 +++++++++++
>> lib/utils/mpxy/objects.mk | 14 +
>> lib/utils/reset/Kconfig | 5 +
>> lib/utils/reset/fdt_reset_rpmi.c | 141 ++++
>> lib/utils/reset/objects.mk | 3 +
>> lib/utils/suspend/Kconfig | 19 +
>> lib/utils/suspend/fdt_suspend.c | 22 +
>> lib/utils/suspend/fdt_suspend_drivers.carray | 3 +
>> lib/utils/suspend/fdt_suspend_rpmi.c | 138 ++++
>> lib/utils/suspend/objects.mk | 14 +
>> platform/generic/allwinner/sun20i-d1.c | 2 +-
>> platform/generic/configs/defconfig | 12 +
>> platform/generic/platform.c | 16 +
>> 56 files changed, 4903 insertions(+), 13 deletions(-)
>> create mode 100644 include/sbi/sbi_mpxy.h
>> create mode 100644 include/sbi_utils/cppc/fdt_cppc.h
>> create mode 100644 include/sbi_utils/hsm/fdt_hsm.h
>> create mode 100644 include/sbi_utils/mailbox/fdt_mailbox.h
>> create mode 100644 include/sbi_utils/mailbox/mailbox.h
>> create mode 100644 include/sbi_utils/mailbox/rpmi_mailbox.h
>> create mode 100644 include/sbi_utils/mailbox/rpmi_msgprot.h
>> create mode 100644 include/sbi_utils/mpxy/fdt_mpxy.h
>> create mode 100644 include/sbi_utils/suspend/fdt_suspend.h
>> create mode 100644 lib/sbi/sbi_ecall_mpxy.c
>> create mode 100644 lib/sbi/sbi_mpxy.c
>> create mode 100644 lib/utils/cppc/Kconfig
>> create mode 100644 lib/utils/cppc/fdt_cppc.c
>> create mode 100644 lib/utils/cppc/fdt_cppc_drivers.carray
>> create mode 100644 lib/utils/cppc/fdt_cppc_rpmi.c
>> create mode 100644 lib/utils/cppc/objects.mk
>> create mode 100644 lib/utils/hsm/Kconfig
>> create mode 100644 lib/utils/hsm/fdt_hsm.c
>> create mode 100644 lib/utils/hsm/fdt_hsm_drivers.carray
>> create mode 100644 lib/utils/hsm/fdt_hsm_rpmi.c
>> create mode 100644 lib/utils/hsm/objects.mk
>> create mode 100644 lib/utils/mailbox/Kconfig
>> create mode 100644 lib/utils/mailbox/fdt_mailbox.c
>> create mode 100644 lib/utils/mailbox/fdt_mailbox_drivers.carray
>> create mode 100644 lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
>> create mode 100644 lib/utils/mailbox/mailbox.c
>> create mode 100644 lib/utils/mailbox/objects.mk
>> create mode 100644 lib/utils/mailbox/rpmi_mailbox.c
>> create mode 100644 lib/utils/mpxy/Kconfig
>> create mode 100644 lib/utils/mpxy/fdt_mpxy.c
>> create mode 100644 lib/utils/mpxy/fdt_mpxy_drivers.carray
>> create mode 100644 lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c
>> create mode 100644 lib/utils/mpxy/objects.mk
>> create mode 100644 lib/utils/reset/fdt_reset_rpmi.c
>> create mode 100644 lib/utils/suspend/Kconfig
>> create mode 100644 lib/utils/suspend/fdt_suspend.c
>> create mode 100644 lib/utils/suspend/fdt_suspend_drivers.carray
>> create mode 100644 lib/utils/suspend/fdt_suspend_rpmi.c
>> create mode 100644 lib/utils/suspend/objects.mk
>>
>> --
>> 2.43.0
>>
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI
2024-12-06 5:08 ` Samuel Holland
@ 2024-12-06 11:32 ` Anup Patel
2024-12-15 21:49 ` Samuel Holland
0 siblings, 1 reply; 23+ messages in thread
From: Anup Patel @ 2024-12-06 11:32 UTC (permalink / raw)
To: opensbi
On Fri, Dec 6, 2024 at 10:38?AM Samuel Holland
<samuel.holland@sifive.com> wrote:
>
> Hi Anup,
>
> On 2024-12-05 9:55 PM, Anup Patel wrote:
> > On Fri, Nov 29, 2024 at 9:21?PM Anup Patel <apatel@ventanamicro.com> wrote:
> >>
> >> This series adds RPMI and SBI MPXY support for OpenSBI. The RPMI service
> >> groups supported include system reset, system suspend, HSM, CPPC, and
> >> clock. The RPMI clock serivice group is exposed to supervisor software
> >> as an MPXY channel.
> >>
> >> These patches can also be found in the rpmi_mpxy_v2 branch at:
> >> https://github.com/avpatel/opensbi.git
> >>
> >> To test these patches, use the dev-upstream branch of the following repos:
> >> * https://github.com/ventanamicro/qemu.git
> >> * https://github.com/ventanamicro/linux.git
> >>
> >> To enable QEMU RPMI emulation (using librpmi) for virt machine, use
> >> "virt,rpmi=on" as the QEMU machine name.
> >>
> >> Changes since v1:
> >> - Rebased on latest OpenSBI
> >> - Use the recently introduced helpers for generic driver initialization
> >> - Updated RPMI drivers to match the latest RPMI specification
> >> - Don't support fixed number of channels in RPMI shared memory mailbox driver
> >> - Added new patch9 for support RPMI HSM based FDT fixup
> >> - Improved arrangment of barrier in __smq_rx() and __smq_tx()
> >>
> >> Anup Patel (8):
> >> lib: utils/mailbox: Add generic mailbox library
> >> lib: utils/mailbox: Add simple FDT based mailbox framework
> >> lib: utils: Add simple FDT based system suspend driver framework
> >> lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
> >> lib: utils: Add simple FDT based HSM driver framework
> >> lib: utils: Add simple FDT based CPPC driver framework
> >> lib: sbi: Implement SBI MPXY extension
> >> lib: utils: Add simple FDT based MPXY driver framework
> >>
> >> Rahul Pathak (5):
> >> lib: Increase ROOT_REGION_MAX to accomodate more memregions
> >> lib/utils: Add RPMI messaging protocol and shared memory transport
> >> support
> >> lib/utils: reset: Add RPMI System Reset driver
> >> lib: sbi: Add SBI Message Proxy (MPXY) framework
> >> lib: utils/mpxy: Add RPMI client driver for MPXY
> >>
> >> Subrahmanya Lingappa (4):
> >> lib: utils/suspend: Add RPMI system suspend driver
> >> lib: sbi: Add optional resume address to hart suspend
> >> lib: utils/hsm: Add RPMI HSM driver
> >> lib: utils/cppc: Add RPMI CPPC driver
> >
> > We plan to include the RPMI and MPXY drivers as experimental
> > for the upcoming OpenSBI v1.6 release at the end of this month.
> > There is still more work required in improving these drivers and
> > related frameworks but that can happen incrementally over time.
>
> I haven't taken the time to fully review this series yet because it's 5000 lines
> of new code and the RPMI spec isn't even frozen, but I have at least two major
> concerns.
The v1 of this series is available on the OpenSBI mailing list since
6th August 2024. Also, unlike kernel, OpenSBI only requires the
specs to be in a stable state for accepting patches as experimental.
This has been the policy for many years now.
>
> 1) Where is the documentation for the devicetree compatible strings added by
> this series? I don't see any attempt to get the bindings reviewed and accepted.
> https://lore.kernel.org/linux-devicetree/?q=rpmi shows nothing. This isn't
> something that can just be changed incrementally. It's not acceptable to break
> DT ABI. It's not okay to unilaterally make up a devicetree interface without
> documenting it and getting feedback through the appropriate process. This is
> especially true since OpenSBI isn't the owner of the RPMI spec.
OpenSBI has accepted experimental drivers in the past and the
expectation is that people will update the bindings in OpenSBI
once finalized on LKML. The drivers being "experimental" means
users should assume that everything (including DT bindings) can
change.
We do have kernel RFC series in-development for getting early
feedback on device tree bindings and kernel drivers. I plan to
send it out this week or early next week.
>
> 2) OpenSBI absolutely must not claim to implement MPXY MSG_PROT_ID 0 (RPMI)
> version 1.0. That specification does not exist. RPMI is not frozen and is still
> actively undergoing changes. If this is an experimental MPXY protocol, it should
> use an experimental message protocol ID.
The whole SBI MPXY extension is experimental until the SBI v3.0
spec is frozen so RPMI v1.0 being accessed via SBI MPXY channel
is also experimental.
>
> I have no problem with merging experimental code and iterating on it, but such
> code must not create ABI surface that has stability guarantees.
Historically, we have always accepted new SBI extensions as
experimental ABI once the corresponding SBI spec is stable
enough. We only change the advertised SBI spec version in
OpenSBI only after the SBI spec is frozen.
Regards,
Anup
>
> Regards,
> Samuel
>
> > Applied this series to the riscv/opensi repo.
> >
> > Thanks,
> > Anup
> >
> >>
> >> include/sbi/sbi_ecall_interface.h | 12 +
> >> include/sbi/sbi_error.h | 15 +-
> >> include/sbi/sbi_hsm.h | 6 +-
> >> include/sbi/sbi_mpxy.h | 183 +++++
> >> include/sbi/sbi_platform.h | 17 +
> >> include/sbi_utils/cppc/fdt_cppc.h | 26 +
> >> include/sbi_utils/fdt/fdt_fixup.h | 15 +
> >> include/sbi_utils/hsm/fdt_hsm.h | 26 +
> >> include/sbi_utils/mailbox/fdt_mailbox.h | 35 +
> >> include/sbi_utils/mailbox/mailbox.h | 180 +++++
> >> include/sbi_utils/mailbox/rpmi_mailbox.h | 32 +
> >> include/sbi_utils/mailbox/rpmi_msgprot.h | 607 +++++++++++++++
> >> include/sbi_utils/mpxy/fdt_mpxy.h | 26 +
> >> include/sbi_utils/suspend/fdt_suspend.h | 26 +
> >> lib/sbi/Kconfig | 3 +
> >> lib/sbi/objects.mk | 4 +
> >> lib/sbi/sbi_domain.c | 2 +-
> >> lib/sbi/sbi_ecall_mpxy.c | 68 ++
> >> lib/sbi/sbi_hsm.c | 6 +-
> >> lib/sbi/sbi_init.c | 6 +
> >> lib/sbi/sbi_mpxy.c | 698 +++++++++++++++++
> >> lib/utils/Kconfig | 10 +
> >> lib/utils/cppc/Kconfig | 19 +
> >> lib/utils/cppc/fdt_cppc.c | 22 +
> >> lib/utils/cppc/fdt_cppc_drivers.carray | 3 +
> >> lib/utils/cppc/fdt_cppc_rpmi.c | 377 +++++++++
> >> lib/utils/cppc/objects.mk | 14 +
> >> lib/utils/fdt/fdt_fixup.c | 33 +
> >> lib/utils/hsm/Kconfig | 19 +
> >> lib/utils/hsm/fdt_hsm.c | 22 +
> >> lib/utils/hsm/fdt_hsm_drivers.carray | 3 +
> >> lib/utils/hsm/fdt_hsm_rpmi.c | 362 +++++++++
> >> lib/utils/hsm/objects.mk | 14 +
> >> lib/utils/mailbox/Kconfig | 29 +
> >> lib/utils/mailbox/fdt_mailbox.c | 96 +++
> >> lib/utils/mailbox/fdt_mailbox_drivers.carray | 5 +
> >> lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c | 773 +++++++++++++++++++
> >> lib/utils/mailbox/mailbox.c | 138 ++++
> >> lib/utils/mailbox/objects.mk | 18 +
> >> lib/utils/mailbox/rpmi_mailbox.c | 91 +++
> >> lib/utils/mpxy/Kconfig | 19 +
> >> lib/utils/mpxy/fdt_mpxy.c | 22 +
> >> lib/utils/mpxy/fdt_mpxy_drivers.carray | 3 +
> >> lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c | 442 +++++++++++
> >> lib/utils/mpxy/objects.mk | 14 +
> >> lib/utils/reset/Kconfig | 5 +
> >> lib/utils/reset/fdt_reset_rpmi.c | 141 ++++
> >> lib/utils/reset/objects.mk | 3 +
> >> lib/utils/suspend/Kconfig | 19 +
> >> lib/utils/suspend/fdt_suspend.c | 22 +
> >> lib/utils/suspend/fdt_suspend_drivers.carray | 3 +
> >> lib/utils/suspend/fdt_suspend_rpmi.c | 138 ++++
> >> lib/utils/suspend/objects.mk | 14 +
> >> platform/generic/allwinner/sun20i-d1.c | 2 +-
> >> platform/generic/configs/defconfig | 12 +
> >> platform/generic/platform.c | 16 +
> >> 56 files changed, 4903 insertions(+), 13 deletions(-)
> >> create mode 100644 include/sbi/sbi_mpxy.h
> >> create mode 100644 include/sbi_utils/cppc/fdt_cppc.h
> >> create mode 100644 include/sbi_utils/hsm/fdt_hsm.h
> >> create mode 100644 include/sbi_utils/mailbox/fdt_mailbox.h
> >> create mode 100644 include/sbi_utils/mailbox/mailbox.h
> >> create mode 100644 include/sbi_utils/mailbox/rpmi_mailbox.h
> >> create mode 100644 include/sbi_utils/mailbox/rpmi_msgprot.h
> >> create mode 100644 include/sbi_utils/mpxy/fdt_mpxy.h
> >> create mode 100644 include/sbi_utils/suspend/fdt_suspend.h
> >> create mode 100644 lib/sbi/sbi_ecall_mpxy.c
> >> create mode 100644 lib/sbi/sbi_mpxy.c
> >> create mode 100644 lib/utils/cppc/Kconfig
> >> create mode 100644 lib/utils/cppc/fdt_cppc.c
> >> create mode 100644 lib/utils/cppc/fdt_cppc_drivers.carray
> >> create mode 100644 lib/utils/cppc/fdt_cppc_rpmi.c
> >> create mode 100644 lib/utils/cppc/objects.mk
> >> create mode 100644 lib/utils/hsm/Kconfig
> >> create mode 100644 lib/utils/hsm/fdt_hsm.c
> >> create mode 100644 lib/utils/hsm/fdt_hsm_drivers.carray
> >> create mode 100644 lib/utils/hsm/fdt_hsm_rpmi.c
> >> create mode 100644 lib/utils/hsm/objects.mk
> >> create mode 100644 lib/utils/mailbox/Kconfig
> >> create mode 100644 lib/utils/mailbox/fdt_mailbox.c
> >> create mode 100644 lib/utils/mailbox/fdt_mailbox_drivers.carray
> >> create mode 100644 lib/utils/mailbox/fdt_mailbox_rpmi_shmem.c
> >> create mode 100644 lib/utils/mailbox/mailbox.c
> >> create mode 100644 lib/utils/mailbox/objects.mk
> >> create mode 100644 lib/utils/mailbox/rpmi_mailbox.c
> >> create mode 100644 lib/utils/mpxy/Kconfig
> >> create mode 100644 lib/utils/mpxy/fdt_mpxy.c
> >> create mode 100644 lib/utils/mpxy/fdt_mpxy_drivers.carray
> >> create mode 100644 lib/utils/mpxy/fdt_mpxy_rpmi_mbox.c
> >> create mode 100644 lib/utils/mpxy/objects.mk
> >> create mode 100644 lib/utils/reset/fdt_reset_rpmi.c
> >> create mode 100644 lib/utils/suspend/Kconfig
> >> create mode 100644 lib/utils/suspend/fdt_suspend.c
> >> create mode 100644 lib/utils/suspend/fdt_suspend_drivers.carray
> >> create mode 100644 lib/utils/suspend/fdt_suspend_rpmi.c
> >> create mode 100644 lib/utils/suspend/objects.mk
> >>
> >> --
> >> 2.43.0
> >>
> >
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI
2024-12-06 11:32 ` Anup Patel
@ 2024-12-15 21:49 ` Samuel Holland
2024-12-16 8:57 ` Anup Patel
0 siblings, 1 reply; 23+ messages in thread
From: Samuel Holland @ 2024-12-15 21:49 UTC (permalink / raw)
To: opensbi
Hi Anup,
On 2024-12-06 5:32 AM, Anup Patel wrote:
> On Fri, Dec 6, 2024 at 10:38?AM Samuel Holland
> <samuel.holland@sifive.com> wrote:
>> On 2024-12-05 9:55 PM, Anup Patel wrote:
>>> On Fri, Nov 29, 2024 at 9:21?PM Anup Patel <apatel@ventanamicro.com> wrote:
>>>>
>>>> This series adds RPMI and SBI MPXY support for OpenSBI. The RPMI service
>>>> groups supported include system reset, system suspend, HSM, CPPC, and
>>>> clock. The RPMI clock serivice group is exposed to supervisor software
>>>> as an MPXY channel.
>>>>
>>>> These patches can also be found in the rpmi_mpxy_v2 branch at:
>>>> https://github.com/avpatel/opensbi.git
>>>>
>>>> To test these patches, use the dev-upstream branch of the following repos:
>>>> * https://github.com/ventanamicro/qemu.git
>>>> * https://github.com/ventanamicro/linux.git
>>>>
>>>> To enable QEMU RPMI emulation (using librpmi) for virt machine, use
>>>> "virt,rpmi=on" as the QEMU machine name.
>>>>
>>>> Changes since v1:
>>>> - Rebased on latest OpenSBI
>>>> - Use the recently introduced helpers for generic driver initialization
>>>> - Updated RPMI drivers to match the latest RPMI specification
>>>> - Don't support fixed number of channels in RPMI shared memory mailbox driver
>>>> - Added new patch9 for support RPMI HSM based FDT fixup
>>>> - Improved arrangment of barrier in __smq_rx() and __smq_tx()
>>>>
>>>> Anup Patel (8):
>>>> lib: utils/mailbox: Add generic mailbox library
>>>> lib: utils/mailbox: Add simple FDT based mailbox framework
>>>> lib: utils: Add simple FDT based system suspend driver framework
>>>> lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
>>>> lib: utils: Add simple FDT based HSM driver framework
>>>> lib: utils: Add simple FDT based CPPC driver framework
>>>> lib: sbi: Implement SBI MPXY extension
>>>> lib: utils: Add simple FDT based MPXY driver framework
>>>>
>>>> Rahul Pathak (5):
>>>> lib: Increase ROOT_REGION_MAX to accomodate more memregions
>>>> lib/utils: Add RPMI messaging protocol and shared memory transport
>>>> support
>>>> lib/utils: reset: Add RPMI System Reset driver
>>>> lib: sbi: Add SBI Message Proxy (MPXY) framework
>>>> lib: utils/mpxy: Add RPMI client driver for MPXY
>>>>
>>>> Subrahmanya Lingappa (4):
>>>> lib: utils/suspend: Add RPMI system suspend driver
>>>> lib: sbi: Add optional resume address to hart suspend
>>>> lib: utils/hsm: Add RPMI HSM driver
>>>> lib: utils/cppc: Add RPMI CPPC driver
>>>
>>> We plan to include the RPMI and MPXY drivers as experimental
>>> for the upcoming OpenSBI v1.6 release at the end of this month.
>>> There is still more work required in improving these drivers and
>>> related frameworks but that can happen incrementally over time.
>>
>> I haven't taken the time to fully review this series yet because it's 5000 lines
>> of new code and the RPMI spec isn't even frozen, but I have at least two major
>> concerns.
>
> The v1 of this series is available on the OpenSBI mailing list since
> 6th August 2024. Also, unlike kernel, OpenSBI only requires the
> specs to be in a stable state for accepting patches as experimental.
> This has been the policy for many years now.
Alright, then this is my mistake for waiting too long to review the driver code.
I generally assume that DT bindings will go through several iterations before
being accepted, and binding changes will require updates to the driver code, so
there's not much point in reviewing drivers until the bindings have stabilized.
>> 1) Where is the documentation for the devicetree compatible strings added by
>> this series? I don't see any attempt to get the bindings reviewed and accepted.
>> https://lore.kernel.org/linux-devicetree/?q=rpmi shows nothing. This isn't
>> something that can just be changed incrementally. It's not acceptable to break
>> DT ABI. It's not okay to unilaterally make up a devicetree interface without
>> documenting it and getting feedback through the appropriate process. This is
>> especially true since OpenSBI isn't the owner of the RPMI spec.
>
> OpenSBI has accepted experimental drivers in the past and the
> expectation is that people will update the bindings in OpenSBI
> once finalized on LKML. The drivers being "experimental" means
> users should assume that everything (including DT bindings) can
> change.
OK, if that is the policy, then we need to make it obvious which drivers are
experimental, and which ones have stability guarantees. I sent a patch doing
this, that I hope can be merged for v1.6:
https://lists.infradead.org/pipermail/opensbi/2024-December/007830.html
> We do have kernel RFC series in-development for getting early
> feedback on device tree bindings and kernel drivers. I plan to
> send it out this week or early next week.
Thanks! That will be helpful. I don't think I've seen this series yet. Did I
miss it?
>> 2) OpenSBI absolutely must not claim to implement MPXY MSG_PROT_ID 0 (RPMI)
>> version 1.0. That specification does not exist. RPMI is not frozen and is still
>> actively undergoing changes. If this is an experimental MPXY protocol, it should
>> use an experimental message protocol ID.
>
> The whole SBI MPXY extension is experimental until the SBI v3.0
> spec is frozen so RPMI v1.0 being accessed via SBI MPXY channel
> is also experimental.
OK, I can accept that the RPMI protocol version number is currently hidden
behind other experimental functionality (SBI v3.0).
>> I have no problem with merging experimental code and iterating on it, but such
>> code must not create ABI surface that has stability guarantees.
>
> Historically, we have always accepted new SBI extensions as
> experimental ABI once the corresponding SBI spec is stable
> enough. We only change the advertised SBI spec version in
> OpenSBI only after the SBI spec is frozen.
Right, though now there is another dependency: because of the protocol version
issue above, we must also wait until the RPMI spec is frozen and the
implementation is no longer experimental before stabilizing SBI v3.0.
Regards,
Samuel
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI
2024-12-15 21:49 ` Samuel Holland
@ 2024-12-16 8:57 ` Anup Patel
0 siblings, 0 replies; 23+ messages in thread
From: Anup Patel @ 2024-12-16 8:57 UTC (permalink / raw)
To: opensbi
On Mon, Dec 16, 2024 at 3:19?AM Samuel Holland
<samuel.holland@sifive.com> wrote:
>
> Hi Anup,
>
> On 2024-12-06 5:32 AM, Anup Patel wrote:
> > On Fri, Dec 6, 2024 at 10:38?AM Samuel Holland
> > <samuel.holland@sifive.com> wrote:
> >> On 2024-12-05 9:55 PM, Anup Patel wrote:
> >>> On Fri, Nov 29, 2024 at 9:21?PM Anup Patel <apatel@ventanamicro.com> wrote:
> >>>>
> >>>> This series adds RPMI and SBI MPXY support for OpenSBI. The RPMI service
> >>>> groups supported include system reset, system suspend, HSM, CPPC, and
> >>>> clock. The RPMI clock serivice group is exposed to supervisor software
> >>>> as an MPXY channel.
> >>>>
> >>>> These patches can also be found in the rpmi_mpxy_v2 branch at:
> >>>> https://github.com/avpatel/opensbi.git
> >>>>
> >>>> To test these patches, use the dev-upstream branch of the following repos:
> >>>> * https://github.com/ventanamicro/qemu.git
> >>>> * https://github.com/ventanamicro/linux.git
> >>>>
> >>>> To enable QEMU RPMI emulation (using librpmi) for virt machine, use
> >>>> "virt,rpmi=on" as the QEMU machine name.
> >>>>
> >>>> Changes since v1:
> >>>> - Rebased on latest OpenSBI
> >>>> - Use the recently introduced helpers for generic driver initialization
> >>>> - Updated RPMI drivers to match the latest RPMI specification
> >>>> - Don't support fixed number of channels in RPMI shared memory mailbox driver
> >>>> - Added new patch9 for support RPMI HSM based FDT fixup
> >>>> - Improved arrangment of barrier in __smq_rx() and __smq_tx()
> >>>>
> >>>> Anup Patel (8):
> >>>> lib: utils/mailbox: Add generic mailbox library
> >>>> lib: utils/mailbox: Add simple FDT based mailbox framework
> >>>> lib: utils: Add simple FDT based system suspend driver framework
> >>>> lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks
> >>>> lib: utils: Add simple FDT based HSM driver framework
> >>>> lib: utils: Add simple FDT based CPPC driver framework
> >>>> lib: sbi: Implement SBI MPXY extension
> >>>> lib: utils: Add simple FDT based MPXY driver framework
> >>>>
> >>>> Rahul Pathak (5):
> >>>> lib: Increase ROOT_REGION_MAX to accomodate more memregions
> >>>> lib/utils: Add RPMI messaging protocol and shared memory transport
> >>>> support
> >>>> lib/utils: reset: Add RPMI System Reset driver
> >>>> lib: sbi: Add SBI Message Proxy (MPXY) framework
> >>>> lib: utils/mpxy: Add RPMI client driver for MPXY
> >>>>
> >>>> Subrahmanya Lingappa (4):
> >>>> lib: utils/suspend: Add RPMI system suspend driver
> >>>> lib: sbi: Add optional resume address to hart suspend
> >>>> lib: utils/hsm: Add RPMI HSM driver
> >>>> lib: utils/cppc: Add RPMI CPPC driver
> >>>
> >>> We plan to include the RPMI and MPXY drivers as experimental
> >>> for the upcoming OpenSBI v1.6 release at the end of this month.
> >>> There is still more work required in improving these drivers and
> >>> related frameworks but that can happen incrementally over time.
> >>
> >> I haven't taken the time to fully review this series yet because it's 5000 lines
> >> of new code and the RPMI spec isn't even frozen, but I have at least two major
> >> concerns.
> >
> > The v1 of this series is available on the OpenSBI mailing list since
> > 6th August 2024. Also, unlike kernel, OpenSBI only requires the
> > specs to be in a stable state for accepting patches as experimental.
> > This has been the policy for many years now.
>
> Alright, then this is my mistake for waiting too long to review the driver code.
> I generally assume that DT bindings will go through several iterations before
> being accepted, and binding changes will require updates to the driver code, so
> there's not much point in reviewing drivers until the bindings have stabilized.
>
> >> 1) Where is the documentation for the devicetree compatible strings added by
> >> this series? I don't see any attempt to get the bindings reviewed and accepted.
> >> https://lore.kernel.org/linux-devicetree/?q=rpmi shows nothing. This isn't
> >> something that can just be changed incrementally. It's not acceptable to break
> >> DT ABI. It's not okay to unilaterally make up a devicetree interface without
> >> documenting it and getting feedback through the appropriate process. This is
> >> especially true since OpenSBI isn't the owner of the RPMI spec.
> >
> > OpenSBI has accepted experimental drivers in the past and the
> > expectation is that people will update the bindings in OpenSBI
> > once finalized on LKML. The drivers being "experimental" means
> > users should assume that everything (including DT bindings) can
> > change.
>
> OK, if that is the policy, then we need to make it obvious which drivers are
> experimental, and which ones have stability guarantees. I sent a patch doing
> this, that I hope can be merged for v1.6:
>
> https://lists.infradead.org/pipermail/opensbi/2024-December/007830.html
Sure, I will look at this patch today.
>
> > We do have kernel RFC series in-development for getting early
> > feedback on device tree bindings and kernel drivers. I plan to
> > send it out this week or early next week.
>
> Thanks! That will be helpful. I don't think I've seen this series yet. Did I
> miss it?
My bad. I got derailed by the Linux IMSIC driver improvements. I have
send-out RFC series to LKML
>
> >> 2) OpenSBI absolutely must not claim to implement MPXY MSG_PROT_ID 0 (RPMI)
> >> version 1.0. That specification does not exist. RPMI is not frozen and is still
> >> actively undergoing changes. If this is an experimental MPXY protocol, it should
> >> use an experimental message protocol ID.
> >
> > The whole SBI MPXY extension is experimental until the SBI v3.0
> > spec is frozen so RPMI v1.0 being accessed via SBI MPXY channel
> > is also experimental.
>
> OK, I can accept that the RPMI protocol version number is currently hidden
> behind other experimental functionality (SBI v3.0).
>
> >> I have no problem with merging experimental code and iterating on it, but such
> >> code must not create ABI surface that has stability guarantees.
> >
> > Historically, we have always accepted new SBI extensions as
> > experimental ABI once the corresponding SBI spec is stable
> > enough. We only change the advertised SBI spec version in
> > OpenSBI only after the SBI spec is frozen.
>
> Right, though now there is another dependency: because of the protocol version
> issue above, we must also wait until the RPMI spec is frozen and the
> implementation is no longer experimental before stabilizing SBI v3.0.
You are correct. Due to this reason, we have aligned the ratification
plan milestone dates for both SBI v3.0 and RPMI v1.0. Both these
specifications are currently under ARC review and hopefully both
will be frozen in the same time frame. We had done such alignment
in the past for SBI v2.0 and RISC-V ACPI FFH.
Regards,
Anup
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2024-12-16 8:57 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-29 15:50 [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
2024-11-29 15:50 ` [PATCH v2 01/17] lib: Increase ROOT_REGION_MAX to accomodate more memregions Anup Patel
2024-11-29 15:50 ` [PATCH v2 02/17] lib: utils/mailbox: Add generic mailbox library Anup Patel
2024-11-29 15:50 ` [PATCH v2 03/17] lib: utils/mailbox: Add simple FDT based mailbox framework Anup Patel
2024-11-29 15:50 ` [PATCH v2 04/17] lib/utils: Add RPMI messaging protocol and shared memory transport support Anup Patel
2024-11-29 15:50 ` [PATCH v2 05/17] lib/utils: reset: Add RPMI System Reset driver Anup Patel
2024-11-29 15:50 ` [PATCH v2 06/17] lib: utils: Add simple FDT based system suspend driver framework Anup Patel
2024-11-29 15:50 ` [PATCH v2 07/17] lib: utils/suspend: Add RPMI system suspend driver Anup Patel
2024-11-29 15:50 ` [PATCH v2 08/17] lib: sbi: Add optional resume address to hart suspend Anup Patel
2024-11-29 15:50 ` [PATCH v2 09/17] lib: utils/fdt: Allow dynamic registration of FDT fixup callbacks Anup Patel
2024-11-29 15:50 ` [PATCH v2 10/17] lib: utils: Add simple FDT based HSM driver framework Anup Patel
2024-11-29 15:50 ` [PATCH v2 11/17] lib: utils/hsm: Add RPMI HSM driver Anup Patel
2024-11-29 15:50 ` [PATCH v2 12/17] lib: utils: Add simple FDT based CPPC driver framework Anup Patel
2024-11-29 15:50 ` [PATCH v2 13/17] lib: utils/cppc: Add RPMI CPPC driver Anup Patel
2024-11-29 15:50 ` [PATCH v2 14/17] lib: sbi: Add SBI Message Proxy (MPXY) framework Anup Patel
2024-11-29 15:50 ` [PATCH v2 15/17] lib: sbi: Implement SBI MPXY extension Anup Patel
2024-11-29 15:50 ` [PATCH v2 16/17] lib: utils: Add simple FDT based MPXY driver framework Anup Patel
2024-11-29 15:50 ` [PATCH v2 17/17] lib: utils/mpxy: Add RPMI client driver for MPXY Anup Patel
2024-12-06 3:55 ` [PATCH v2 00/17] RPMI and SBI MPXY support for OpenSBI Anup Patel
2024-12-06 5:08 ` Samuel Holland
2024-12-06 11:32 ` Anup Patel
2024-12-15 21:49 ` Samuel Holland
2024-12-16 8:57 ` Anup Patel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox