[PATCH RFC 1/5] optee: riscv: add RPMI TEE service group transport

Amirreza Zarrabi amirreza.zarrabi at oss.qualcomm.com
Sat Sep 12 03:15:12 PDT 2026


Add an OP-TEE transport for RISC-V using the RPMI TEE service group over
the SBI MPXY mailbox framework.

Request one mailbox channel per hart and use the channel corresponding to
the current CPU when issuing a TEE request. Probe the RPMI TEE service
group and required memory-sharing capabilities before registering the
transport.

This provides the basic transport and discovery support needed by the
following patches.

Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi at oss.qualcomm.com>
---
 drivers/tee/optee/Makefile                 |   1 +
 drivers/tee/optee/core.c                   |   8 +-
 drivers/tee/optee/optee_private.h          |  34 ++++
 drivers/tee/optee/optee_riscv.c            | 312 +++++++++++++++++++++++++++++
 drivers/tee/optee/optee_riscv.h            | 141 +++++++++++++
 include/linux/mailbox/riscv-rpmi-message.h |   1 +
 6 files changed, 495 insertions(+), 2 deletions(-)

diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index ad7049c1c107..925b8ec7ef68 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -9,6 +9,7 @@ optee-objs += supp.o
 optee-objs += device.o
 optee-objs += smc_abi.o
 optee-objs += ffa_abi.o
+optee-$(CONFIG_RISCV_SBI_MPXY_MBOX) += optee_riscv.o
 
 # for tracing framework to find optee_trace.h
 CFLAGS_smc_abi.o := -I$(src)
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index a52c1f498b99..63f1725e646e 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -220,6 +220,7 @@ void optee_remove_common(struct optee *optee)
 
 static int smc_abi_rc;
 static int ffa_abi_rc;
+static int riscv_abi_rc;
 static bool intf_is_regged;
 
 static int __init optee_core_init(void)
@@ -245,9 +246,10 @@ static int __init optee_core_init(void)
 
 	smc_abi_rc = optee_smc_abi_register();
 	ffa_abi_rc = optee_ffa_abi_register();
+	riscv_abi_rc = optee_riscv_abi_register();
 
-	/* If both failed there's no point with this module */
-	if (smc_abi_rc && ffa_abi_rc) {
+	/* If all failed there's no point with this module */
+	if (smc_abi_rc && ffa_abi_rc && riscv_abi_rc) {
 		if (IS_REACHABLE(CONFIG_RPMB)) {
 			rpmb_interface_unregister(&rpmb_class_intf);
 			intf_is_regged = false;
@@ -270,6 +272,8 @@ static void __exit optee_core_exit(void)
 		optee_smc_abi_unregister();
 	if (!ffa_abi_rc)
 		optee_ffa_abi_unregister();
+	if (!riscv_abi_rc)
+		optee_riscv_abi_unregister();
 }
 module_exit(optee_core_exit);
 
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index aefe1e6f5689..8d22d65e087b 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -171,6 +171,31 @@ struct optee_ffa {
 	struct work_struct notif_work;
 };
 
+/**
+ * struct optee_riscv - RPMI TEE communication struct
+ * @chan:		per-hart RPMI TEE service group mailbox channels
+ * @client:		RPMI mailbox client used to request @chan
+ * @dev:		device backing the RPMI TEE mailbox client
+ * @nr_chan:		number of entries in @chan
+ * @max_msg_data_size:	maximum RPMI message data size of the TEE channel
+ * @mutex:		serializes access to @global_ids
+ * @global_ids:		memory parcel id to tee_shm translation table
+ *
+ * This is the RISC-V analog of struct optee_ffa: communication with secure
+ * world OP-TEE OS rides the RPMI TEE service group (RPMI spec section 4.16)
+ * over the SBI MPXY mailbox instead of Arm FF-A.
+ */
+struct optee_riscv {
+	struct mbox_chan **chan;
+	struct mbox_client *client;
+	struct device *dev;
+	unsigned int nr_chan;
+	u32 max_msg_data_size;
+	/* Serializes access to @global_ids */
+	struct mutex mutex;
+	struct rhashtable global_ids;
+};
+
 struct optee;
 
 /**
@@ -231,6 +256,7 @@ struct optee_ops {
  * @ctx:			driver internal TEE context
  * @smc:			specific to SMC ABI
  * @ffa:			specific to FF-A ABI
+ * @riscv:			specific to RPMI TEE ABI
  * @shm_arg_cache:		shared memory cache argument
  * @call_queue:			queue of threads waiting to call @invoke_fn
  * @notif:			notification synchronization struct
@@ -259,6 +285,7 @@ struct optee {
 	union {
 		struct optee_smc smc;
 		struct optee_ffa ffa;
+		struct optee_riscv riscv;
 	};
 	struct optee_shm_arg_cache shm_arg_cache;
 	struct optee_call_queue call_queue;
@@ -426,5 +453,12 @@ int optee_smc_abi_register(void);
 void optee_smc_abi_unregister(void);
 int optee_ffa_abi_register(void);
 void optee_ffa_abi_unregister(void);
+#ifdef CONFIG_RISCV_SBI_MPXY_MBOX
+int optee_riscv_abi_register(void);
+void optee_riscv_abi_unregister(void);
+#else
+static inline int optee_riscv_abi_register(void) { return -EOPNOTSUPP; }
+static inline void optee_riscv_abi_unregister(void) { }
+#endif
 
 #endif /*OPTEE_PRIVATE_H*/
diff --git a/drivers/tee/optee/optee_riscv.c b/drivers/tee/optee/optee_riscv.c
new file mode 100644
index 000000000000..0fe4edf92fc9
--- /dev/null
+++ b/drivers/tee/optee/optee_riscv.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * This file implements the ABI used when communicating with secure world
+ * OP-TEE OS over the RPMI TEE service group (RPMI spec section 4.16). It is
+ * the RISC-V analog of ffa_abi.c: OP-TEE and Linux are peer endpoints of the
+ * RPMI framework (OpenSBI), and shared memory follows the FF-A memory-donation
+ * model through the RPMI memory parcel services.
+ *
+ * This file is divided into the following sections:
+ * 1. Low level RPMI TEE service group transport over the SBI MPXY mailbox
+ * 2. Feature discovery and notification handshake
+ * 3. Driver initialization
+ *
+ * The remaining FF-A-equivalent sections (parcel id hash table, tee_param
+ * marshalling, dynamic shared memory pool and the scheduled call into secure
+ * world) are added on top of this transport layer.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/errno.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/riscv-rpmi-message.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/tee_core.h>
+#include <linux/types.h>
+
+#include "optee_private.h"
+#include "optee_riscv.h"
+
+/*
+ * 1. Low level RPMI TEE service group transport over the SBI MPXY mailbox
+ *
+ * The RPMI TEE service group is reached through the SBI MPXY mailbox. Each
+ * hart owns a dedicated MPXY channel so that a call issued on a given hart is
+ * serviced by the OP-TEE context bound to it; optee_riscv_send() therefore
+ * selects the channel of the running hart. All RPMI messages are exchanged
+ * synchronously with rpmi_mbox_send_message().
+ */
+
+static int optee_riscv_send(struct optee *optee, struct rpmi_mbox_message *msg)
+{
+	int cpu, ret;
+
+	cpu = get_cpu();
+	if (cpu >= optee->riscv.nr_chan || !optee->riscv.chan[cpu]) {
+		put_cpu();
+		return -ENODEV;
+	}
+	ret = rpmi_mbox_send_message(optee->riscv.chan[cpu], msg);
+	put_cpu();
+
+	return ret;
+}
+
+/*
+ * 2. Feature discovery and notification handshake
+ *
+ * TEE_PROBE_FEATURES (0x02) reports which framework features are available;
+ * TEE_ENABLE_NOTIFICATION (0x01) subscribes to TEE service group events. Both
+ * are mandatory services (RPMI spec section 4.16), so probing them also
+ * confirms that the framework speaks the TEE service group on this channel.
+ */
+
+static int optee_riscv_probe_feature(struct optee *optee, u32 feature_id,
+				     u32 *value)
+{
+	struct rpmi_tee_probe_features_req tx = {
+		.feature_id = cpu_to_le32(feature_id),
+	};
+	struct rpmi_tee_probe_features_resp rx = { };
+	struct rpmi_mbox_message msg;
+	int ret;
+
+	rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_PROBE_FEATURES,
+					  &tx, sizeof(tx), &rx, sizeof(rx));
+	ret = optee_riscv_send(optee, &msg);
+	if (ret)
+		return ret;
+	if (rx.status)
+		return rpmi_to_linux_error(le32_to_cpu(rx.status));
+
+	if (value)
+		*value = le32_to_cpu(rx.value);
+
+	return 0;
+}
+
+static int optee_riscv_features(struct optee *optee)
+{
+	u32 share = RPMI_TEE_MEMORY_SHARE_NONE;
+	int ret;
+
+	/*
+	 * Memory parcels carry normal-world shared memory to OP-TEE, so the
+	 * framework must support sharing memory between the REE and a TEE.
+	 */
+	ret = optee_riscv_probe_feature(optee, RPMI_TEE_FEAT_MEMORY_SHARE,
+					&share);
+	if (ret) {
+		pr_err("Failed to probe MEMORY_SHARE feature: %d\n", ret);
+		return ret;
+	}
+	if (share != RPMI_TEE_MEMORY_SHARE_FULL) {
+		pr_err("Framework cannot share memory between REE and TEE (%u)\n",
+		       share);
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int optee_riscv_enable_notif(struct optee *optee)
+{
+	struct rpmi_tee_probe_features_resp rx = { };
+	struct rpmi_mbox_message msg;
+	int ret;
+
+	rpmi_mbox_init_send_with_response(&msg, RPMI_TEE_SRV_ENABLE_NOTIFICATION,
+					  NULL, 0, &rx, sizeof(rx));
+	ret = optee_riscv_send(optee, &msg);
+	if (ret)
+		return ret;
+
+	/*
+	 * The TEE service group defines no notification events on this
+	 * platform, so RPMI_ERR_NOTSUPP is expected and not fatal.
+	 */
+	if (rx.status && le32_to_cpu(rx.status) != (u32)RPMI_ERR_NOTSUPP)
+		return rpmi_to_linux_error(le32_to_cpu(rx.status));
+
+	return 0;
+}
+
+/*
+ * 3. Driver initialization
+ *
+ * The RPMI TEE service group is described in the device tree by a single
+ * node whose "mboxes" property lists one SBI MPXY channel per hart, in hart
+ * order. The driver requests each list entry by index and validates the
+ * transport before building the OP-TEE device.
+ */
+
+static int optee_riscv_request_channels(struct optee *optee)
+{
+	struct device *dev = optee->riscv.dev;
+	int nr_mboxes;
+	unsigned int cpuid;
+
+	nr_mboxes = of_count_phandle_with_args(dev->of_node, "mboxes",
+					       "#mbox-cells");
+	if (nr_mboxes != optee->riscv.nr_chan)
+		return dev_err_probe(dev, -EINVAL,
+				     "Expected %u mailbox channels, got %d\n",
+				     optee->riscv.nr_chan, nr_mboxes);
+
+	for (cpuid = 0; cpuid < optee->riscv.nr_chan; cpuid++) {
+		optee->riscv.chan[cpuid] =
+			mbox_request_channel(optee->riscv.client, cpuid);
+		if (IS_ERR(optee->riscv.chan[cpuid])) {
+			int ret = PTR_ERR(optee->riscv.chan[cpuid]);
+
+			optee->riscv.chan[cpuid] = NULL;
+			return dev_err_probe(dev, ret,
+					     "Failed to request channel %u\n",
+					     cpuid);
+		}
+	}
+
+	return 0;
+}
+
+static void optee_riscv_free_channels(struct optee *optee)
+{
+	unsigned int i;
+
+	for (i = 0; i < optee->riscv.nr_chan; i++) {
+		if (optee->riscv.chan[i])
+			mbox_free_channel(optee->riscv.chan[i]);
+	}
+}
+
+static int optee_riscv_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rpmi_mbox_message msg;
+	struct mbox_client *client;
+	struct optee *optee;
+	u32 servicegroup_id;
+	unsigned int nr_cpus;
+	int ret;
+
+	nr_cpus = num_possible_cpus();
+	if (!nr_cpus)
+		return dev_err_probe(dev, -ENODEV, "No harts found\n");
+
+	optee = kzalloc_obj(*optee);
+	if (!optee)
+		return -ENOMEM;
+
+	client = devm_kzalloc(dev, sizeof(*client), GFP_KERNEL);
+	if (!client) {
+		ret = -ENOMEM;
+		goto err_free_optee;
+	}
+	client->dev		= dev;
+	client->rx_callback	= NULL;
+	client->tx_block	= false;
+	client->knows_txdone	= true;
+	client->tx_tout		= 0;
+
+	optee->riscv.dev = dev;
+	optee->riscv.client = client;
+	optee->riscv.nr_chan = nr_cpus;
+	optee->riscv.chan = kcalloc(nr_cpus, sizeof(*optee->riscv.chan),
+				    GFP_KERNEL);
+	if (!optee->riscv.chan) {
+		ret = -ENOMEM;
+		goto err_free_optee;
+	}
+
+	ret = optee_riscv_request_channels(optee);
+	if (ret)
+		goto err_free_channels;
+
+	/* Confirm the channel really speaks the TEE service group. */
+	rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_SERVICEGROUP_ID);
+	ret = optee_riscv_send(optee, &msg);
+	if (ret) {
+		dev_err_probe(dev, ret, "Failed to get service group id\n");
+		goto err_free_channels;
+	}
+	servicegroup_id = msg.attr.value;
+	if (servicegroup_id != RPMI_SRVGRP_TEE) {
+		ret = -ENODEV;
+		dev_err_probe(dev, ret, "Not a TEE service group channel (0x%x)\n",
+			      servicegroup_id);
+		goto err_free_channels;
+	}
+
+	rpmi_mbox_init_get_attribute(&msg, RPMI_MBOX_ATTR_MAX_MSG_DATA_SIZE);
+	ret = optee_riscv_send(optee, &msg);
+	if (ret) {
+		dev_err_probe(dev, ret, "Failed to get max msg data size\n");
+		goto err_free_channels;
+	}
+	optee->riscv.max_msg_data_size = msg.attr.value;
+
+	ret = optee_riscv_features(optee);
+	if (ret) {
+		dev_err_probe(dev, ret, "Missing required TEE features\n");
+		goto err_free_channels;
+	}
+
+	ret = optee_riscv_enable_notif(optee);
+	if (ret) {
+		dev_err_probe(dev, ret, "Failed to enable notifications\n");
+		goto err_free_channels;
+	}
+
+	platform_set_drvdata(pdev, optee);
+	dev_info(dev, "initialized driver\n");
+
+	return 0;
+
+err_free_channels:
+	optee_riscv_free_channels(optee);
+	kfree(optee->riscv.chan);
+err_free_optee:
+	kfree(optee);
+	return ret;
+}
+
+static void optee_riscv_remove(struct platform_device *pdev)
+{
+	struct optee *optee = platform_get_drvdata(pdev);
+
+	optee_riscv_free_channels(optee);
+	kfree(optee->riscv.chan);
+	kfree(optee);
+}
+
+static const struct of_device_id optee_riscv_match[] = {
+	{ .compatible = "riscv,rpmi-mpxy-tee" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, optee_riscv_match);
+
+static struct platform_driver optee_riscv_driver = {
+	.driver = {
+		.name = DRIVER_NAME "-riscv",
+		.of_match_table = optee_riscv_match,
+	},
+	.probe = optee_riscv_probe,
+	.remove = optee_riscv_remove,
+};
+
+int optee_riscv_abi_register(void)
+{
+	return platform_driver_register(&optee_riscv_driver);
+}
+
+void optee_riscv_abi_unregister(void)
+{
+	platform_driver_unregister(&optee_riscv_driver);
+}
diff --git a/drivers/tee/optee/optee_riscv.h b/drivers/tee/optee/optee_riscv.h
new file mode 100644
index 000000000000..d87298faa6a2
--- /dev/null
+++ b/drivers/tee/optee/optee_riscv.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+/*
+ * This file is exported by OP-TEE and is kept in sync between secure world
+ * and normal world drivers. It describes the wire contract used when
+ * communicating with secure world OP-TEE OS over the RPMI TEE service group
+ * (RPMI specification section 4.16, SERVICEGROUP_ID 0x0010).
+ *
+ * The RPMI TEE service group is the RISC-V analog of Arm FF-A: OP-TEE and the
+ * rich execution environment (REE, i.e. Linux) are peer endpoints, and the
+ * RPMI framework (OpenSBI in M-mode) mediates every message. Memory sharing
+ * follows the FF-A memory-donation model through the memory parcel services:
+ * the REE creates a parcel describing its pages, OP-TEE accepts it lazily by
+ * parcel id, and teardown is two phased (OP-TEE releases, the REE reclaims).
+ *
+ * All request and response payloads are little-endian uint32 words as defined
+ * by the RPMI specification. These definitions MUST byte-match the OpenSBI
+ * framework definitions in <sbi_utils/mailbox/rpmi_msgprot.h>.
+ */
+
+#ifndef __OPTEE_RISCV_H
+#define __OPTEE_RISCV_H
+
+#include <linux/mailbox/riscv-rpmi-message.h>
+#include <linux/types.h>
+
+/*
+ * RPMI TEE service ids (RPMI spec section 4.16, Table 181).
+ *
+ * Only TEE_ENABLE_NOTIFICATION, TEE_PROBE_FEATURES and TEE_CALL are mandated;
+ * the remaining services are optional and may return RPMI_ERR_NOTSUPP.
+ */
+enum rpmi_tee_service_id {
+	RPMI_TEE_SRV_ENABLE_NOTIFICATION	= 0x01,
+	RPMI_TEE_SRV_PROBE_FEATURES		= 0x02,
+	RPMI_TEE_SRV_PROBE_SYSTEM		= 0x03,
+	RPMI_TEE_SRV_EXIT			= 0x04,
+	RPMI_TEE_SRV_SIGNAL_BUS_SETUP		= 0x05,
+	RPMI_TEE_SRV_SIGNAL_BUS_TEARDOWN	= 0x06,
+	RPMI_TEE_SRV_SIGNAL_RAISE		= 0x07,
+	RPMI_TEE_SRV_SIGNAL_RETRIEVE		= 0x08,
+	RPMI_TEE_SRV_MEM_PARCEL_CREATE		= 0x09,
+	RPMI_TEE_SRV_MEM_PARCEL_ACCEPT		= 0x0a,
+	RPMI_TEE_SRV_MEM_PARCEL_RELEASE		= 0x0b,
+	RPMI_TEE_SRV_MEM_PARCEL_RECLAIM		= 0x0c,
+	RPMI_TEE_SRV_MEM_PARCEL_SEGMENT_SEND	= 0x0d,
+	RPMI_TEE_SRV_MEM_PARCEL_SEGMENT_RECEIVE	= 0x0e,
+	RPMI_TEE_SRV_CALL			= 0x13,
+	RPMI_TEE_SRV_MAX_COUNT,
+};
+
+/*
+ * RPMI TEE endpoint identities.
+ *
+ * The RPMI specification does not fix numeric endpoint ids; they are assigned
+ * by the framework at runtime. These values match the OpenSBI framework
+ * assignment used on this platform: the REE is endpoint 0 and OP-TEE is
+ * endpoint 1.
+ */
+#define RPMI_TEE_ENDPOINT_REE		0
+#define RPMI_TEE_ENDPOINT_OPTEE		1
+
+/*
+ * RPMI TEE feature ids for TEE_PROBE_FEATURES (RPMI spec section 4.16.4,
+ * Table 182).
+ */
+enum rpmi_tee_feature_id {
+	RPMI_TEE_FEAT_MEMORY_DONATE	= 1,
+	RPMI_TEE_FEAT_MEMORY_LEND	= 2,
+	RPMI_TEE_FEAT_MEMORY_SHARE	= 3,
+	RPMI_TEE_FEAT_SIGNAL_BUS	= 4,
+	RPMI_TEE_FEAT_MULTISEGMENT_OPS	= 5,
+	RPMI_TEE_FEAT_SYSINFO_FORMAT	= 6,
+};
+
+/* MEMORY_SHARE feature values (RPMI spec Table 182). */
+#define RPMI_TEE_MEMORY_SHARE_NONE		0
+#define RPMI_TEE_MEMORY_SHARE_TEE_ONLY		1
+#define RPMI_TEE_MEMORY_SHARE_FULL		2
+
+/* TEE_PROBE_FEATURES request (Table 183) / response (Table 184). */
+struct rpmi_tee_probe_features_req {
+	__le32 feature_id;
+};
+
+struct rpmi_tee_probe_features_resp {
+	__le32 status;
+	__le32 value;
+};
+
+/*
+ * TEE_CALL wire encoding (RPMI spec section 4.16.21, Tables 218 and 219).
+ *
+ * TEE_CALL is the mandatory doorbell service used to enter OP-TEE. The
+ * request carries a fixed REE->OP-TEE identity, the well-known OP-TEE service
+ * UUID and a SERVICE_DATA payload; the response carries a STATUS word, a
+ * SERVICE_RSP_LEN word and the SERVICE_RSP payload.
+ *
+ * The SERVICE_DATA/SERVICE_RSP registers are XLEN-sized little-endian values.
+ * The structures are __packed so the 16-byte UUID does not force padding
+ * before the length word.
+ */
+#define RPMI_TEE_UUID_LEN		16
+
+/* OP-TEE communicate service UUID: 5be1b1a0-7e11-4e7a-9b10-0010c0ffee00 */
+#define RPMI_TEE_OPTEE_UUID						\
+	{ 0x5b, 0xe1, 0xb1, 0xa0, 0x7e, 0x11, 0x4e, 0x7a,		\
+	  0x9b, 0x10, 0x00, 0x10, 0xc0, 0xff, 0xee, 0x00 }
+
+/* OP-TEE SMC-style call convention carried inside SERVICE_DATA. */
+#define RPMI_TEE_OPTEE_CALL_REGS	8	/* a0-a7 */
+#define RPMI_TEE_OPTEE_RESP_REGS	4	/* a0-a3 */
+
+#if __riscv_xlen == 64
+typedef __le64 rpmi_xlen_t;
+#define cpu_to_rpmi_xlen(x)	cpu_to_le64(x)
+#define rpmi_xlen_to_cpu(x)	le64_to_cpu(x)
+#else
+typedef __le32 rpmi_xlen_t;
+#define cpu_to_rpmi_xlen(x)	cpu_to_le32(x)
+#define rpmi_xlen_to_cpu(x)	le32_to_cpu(x)
+#endif
+
+struct rpmi_tee_call_req {
+	__le32 sender_id;
+	__le32 target_id;
+	u8 service[RPMI_TEE_UUID_LEN];
+	__le32 service_data_len;
+	rpmi_xlen_t reg[RPMI_TEE_OPTEE_CALL_REGS];
+} __packed;
+
+struct rpmi_tee_call_resp {
+	__le32 status;
+	__le32 service_rsp_len;
+	rpmi_xlen_t reg[RPMI_TEE_OPTEE_RESP_REGS];
+} __packed;
+
+#endif /* __OPTEE_RISCV_H */
diff --git a/include/linux/mailbox/riscv-rpmi-message.h b/include/linux/mailbox/riscv-rpmi-message.h
index e135c6564d0c..47a540bd81c9 100644
--- a/include/linux/mailbox/riscv-rpmi-message.h
+++ b/include/linux/mailbox/riscv-rpmi-message.h
@@ -93,6 +93,7 @@ static inline int rpmi_to_linux_error(int rpmi_error)
 /* RPMI service group IDs */
 #define RPMI_SRVGRP_SYSTEM_MSI		0x00002
 #define RPMI_SRVGRP_CLOCK		0x00008
+#define RPMI_SRVGRP_TEE			0x00010
 
 /* RPMI clock service IDs */
 enum rpmi_clock_service_id {

-- 
2.34.1




More information about the linux-riscv mailing list