]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mailbox: Add common header for RPMI messages sent via mailbox
authorAnup Patel <apatel@ventanamicro.com>
Mon, 18 Aug 2025 04:09:00 +0000 (09:39 +0530)
committerPaul Walmsley <pjw@kernel.org>
Wed, 24 Sep 2025 22:58:00 +0000 (16:58 -0600)
The RPMI based mailbox controller drivers and mailbox clients need to
share defines related to RPMI messages over mailbox interface so add
a common header for this purpose.

Acked-by: Jassi Brar <jassisinghbrar@gmail.com>
Co-developed-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Rahul Pathak <rpathak@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Link: https://lore.kernel.org/r/20250818040920.272664-5-apatel@ventanamicro.com
Signed-off-by: Paul Walmsley <pjw@kernel.org>
include/linux/mailbox/riscv-rpmi-message.h [new file with mode: 0644]

diff --git a/include/linux/mailbox/riscv-rpmi-message.h b/include/linux/mailbox/riscv-rpmi-message.h
new file mode 100644 (file)
index 0000000..c3a98fc
--- /dev/null
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (C) 2025 Ventana Micro Systems Inc. */
+
+#ifndef _LINUX_RISCV_RPMI_MESSAGE_H_
+#define _LINUX_RISCV_RPMI_MESSAGE_H_
+
+#include <linux/errno.h>
+#include <linux/mailbox_client.h>
+#include <linux/types.h>
+#include <linux/wordpart.h>
+
+/* RPMI version encode/decode macros */
+#define RPMI_VER_MAJOR(__ver)          upper_16_bits(__ver)
+#define RPMI_VER_MINOR(__ver)          lower_16_bits(__ver)
+#define RPMI_MKVER(__maj, __min)       (((u32)(__maj) << 16) | (u16)(__min))
+
+/* RPMI message header */
+struct rpmi_message_header {
+       __le16 servicegroup_id;
+       u8 service_id;
+       u8 flags;
+       __le16 datalen;
+       __le16 token;
+};
+
+/* RPMI message */
+struct rpmi_message {
+       struct rpmi_message_header header;
+       u8 data[];
+};
+
+/* RPMI notification event */
+struct rpmi_notification_event {
+       __le16 event_datalen;
+       u8 event_id;
+       u8 reserved;
+       u8 event_data[];
+};
+
+/* RPMI error codes */
+enum rpmi_error_codes {
+       RPMI_SUCCESS                    = 0,
+       RPMI_ERR_FAILED                 = -1,
+       RPMI_ERR_NOTSUPP                = -2,
+       RPMI_ERR_INVALID_PARAM          = -3,
+       RPMI_ERR_DENIED                 = -4,
+       RPMI_ERR_INVALID_ADDR           = -5,
+       RPMI_ERR_ALREADY                = -6,
+       RPMI_ERR_EXTENSION              = -7,
+       RPMI_ERR_HW_FAULT               = -8,
+       RPMI_ERR_BUSY                   = -9,
+       RPMI_ERR_INVALID_STATE          = -10,
+       RPMI_ERR_BAD_RANGE              = -11,
+       RPMI_ERR_TIMEOUT                = -12,
+       RPMI_ERR_IO                     = -13,
+       RPMI_ERR_NO_DATA                = -14,
+       RPMI_ERR_RESERVED_START         = -15,
+       RPMI_ERR_RESERVED_END           = -127,
+       RPMI_ERR_VENDOR_START           = -128,
+};
+
+static inline int rpmi_to_linux_error(int rpmi_error)
+{
+       switch (rpmi_error) {
+       case RPMI_SUCCESS:
+               return 0;
+       case RPMI_ERR_INVALID_PARAM:
+       case RPMI_ERR_BAD_RANGE:
+       case RPMI_ERR_INVALID_STATE:
+               return -EINVAL;
+       case RPMI_ERR_DENIED:
+               return -EPERM;
+       case RPMI_ERR_INVALID_ADDR:
+       case RPMI_ERR_HW_FAULT:
+               return -EFAULT;
+       case RPMI_ERR_ALREADY:
+               return -EALREADY;
+       case RPMI_ERR_BUSY:
+               return -EBUSY;
+       case RPMI_ERR_TIMEOUT:
+               return -ETIMEDOUT;
+       case RPMI_ERR_IO:
+               return -ECOMM;
+       case RPMI_ERR_FAILED:
+       case RPMI_ERR_NOTSUPP:
+       case RPMI_ERR_NO_DATA:
+       case RPMI_ERR_EXTENSION:
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+/* RPMI Linux mailbox attribute IDs */
+enum rpmi_mbox_attribute_id {
+       RPMI_MBOX_ATTR_SPEC_VERSION,
+       RPMI_MBOX_ATTR_MAX_MSG_DATA_SIZE,
+       RPMI_MBOX_ATTR_SERVICEGROUP_ID,
+       RPMI_MBOX_ATTR_SERVICEGROUP_VERSION,
+       RPMI_MBOX_ATTR_IMPL_ID,
+       RPMI_MBOX_ATTR_IMPL_VERSION,
+       RPMI_MBOX_ATTR_MAX_ID
+};
+
+/* RPMI Linux mailbox message types */
+enum rpmi_mbox_message_type {
+       RPMI_MBOX_MSG_TYPE_GET_ATTRIBUTE,
+       RPMI_MBOX_MSG_TYPE_SET_ATTRIBUTE,
+       RPMI_MBOX_MSG_TYPE_SEND_WITH_RESPONSE,
+       RPMI_MBOX_MSG_TYPE_SEND_WITHOUT_RESPONSE,
+       RPMI_MBOX_MSG_TYPE_NOTIFICATION_EVENT,
+       RPMI_MBOX_MSG_MAX_TYPE
+};
+
+/* RPMI Linux mailbox message instance */
+struct rpmi_mbox_message {
+       enum rpmi_mbox_message_type type;
+       union {
+               struct {
+                       enum rpmi_mbox_attribute_id id;
+                       u32 value;
+               } attr;
+
+               struct {
+                       u32 service_id;
+                       void *request;
+                       unsigned long request_len;
+                       void *response;
+                       unsigned long max_response_len;
+                       unsigned long out_response_len;
+               } data;
+
+               struct {
+                       u16 event_datalen;
+                       u8 event_id;
+                       u8 *event_data;
+               } notif;
+       };
+       int error;
+};
+
+/* RPMI Linux mailbox message helper routines */
+static inline void rpmi_mbox_init_get_attribute(struct rpmi_mbox_message *msg,
+                                               enum rpmi_mbox_attribute_id id)
+{
+       msg->type = RPMI_MBOX_MSG_TYPE_GET_ATTRIBUTE;
+       msg->attr.id = id;
+       msg->attr.value = 0;
+       msg->error = 0;
+}
+
+static inline void rpmi_mbox_init_set_attribute(struct rpmi_mbox_message *msg,
+                                               enum rpmi_mbox_attribute_id id,
+                                               u32 value)
+{
+       msg->type = RPMI_MBOX_MSG_TYPE_SET_ATTRIBUTE;
+       msg->attr.id = id;
+       msg->attr.value = value;
+       msg->error = 0;
+}
+
+static inline void rpmi_mbox_init_send_with_response(struct rpmi_mbox_message *msg,
+                                                    u32 service_id,
+                                                    void *request,
+                                                    unsigned long request_len,
+                                                    void *response,
+                                                    unsigned long max_response_len)
+{
+       msg->type = RPMI_MBOX_MSG_TYPE_SEND_WITH_RESPONSE;
+       msg->data.service_id = service_id;
+       msg->data.request = request;
+       msg->data.request_len = request_len;
+       msg->data.response = response;
+       msg->data.max_response_len = max_response_len;
+       msg->data.out_response_len = 0;
+       msg->error = 0;
+}
+
+static inline void rpmi_mbox_init_send_without_response(struct rpmi_mbox_message *msg,
+                                                       u32 service_id,
+                                                       void *request,
+                                                       unsigned long request_len)
+{
+       msg->type = RPMI_MBOX_MSG_TYPE_SEND_WITHOUT_RESPONSE;
+       msg->data.service_id = service_id;
+       msg->data.request = request;
+       msg->data.request_len = request_len;
+       msg->data.response = NULL;
+       msg->data.max_response_len = 0;
+       msg->data.out_response_len = 0;
+       msg->error = 0;
+}
+
+static inline void *rpmi_mbox_get_msg_response(struct rpmi_mbox_message *msg)
+{
+       return msg ? msg->data.response : NULL;
+}
+
+static inline int rpmi_mbox_send_message(struct mbox_chan *chan,
+                                        struct rpmi_mbox_message *msg)
+{
+       int ret;
+
+       /* Send message for the underlying mailbox channel */
+       ret = mbox_send_message(chan, msg);
+       if (ret < 0)
+               return ret;
+
+       /* Explicitly signal txdone for mailbox channel */
+       ret = msg->error;
+       mbox_client_txdone(chan, ret);
+       return ret;
+}
+
+#endif /* _LINUX_RISCV_RPMI_MESSAGE_H_ */