[PATCH RFC 1/5] optee: riscv: add RPMI TEE service group transport
From: Amirreza Zarrabi
Date: Sat Sep 12 2026 - 06:15:59 EST
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@xxxxxxxxxxxxxxxx>
---
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