This change implements a mailbox transport using SMT format for SCMI
exchanges. This implementation follows the Linux kernel and
SCP-firmware [1] as references implementation for SCMI message
processing using SMT format for communication channel meta-data.
Use of mailboxes in SCMI FDT bindings are defined in the Linux kernel
DT bindings since v4.17.
Links: [1] https://github.com/ARM-software/SCP-firmware
Signed-off-by: Etienne Carriere
Cc: Simon Glass
Cc: Peng Fan
Cc: Sudeep Holla
---
Changes in v4:
- Replace __arm__ with CONFIG_ARM.
- Remove cast for priv reference hence remove helper scmi_mbox_get_priv().
Changes in v3:
- This is a followup of the SCMI agent patches posted in
https://patchwork.ozlabs.org/project/uboot/list/?series=196253
The v3 splits commits and introduces a new uclass as requested.
- This patch implements the same mailbox SCMI agent proposed in v2
but split over few source files.
---
drivers/firmware/scmi/Kconfig | 6 +-
drivers/firmware/scmi/Makefile| 2 +
drivers/firmware/scmi/mailbox_agent.c | 102 +++
drivers/firmware/scmi/smt.c | 139 ++
drivers/firmware/scmi/smt.h | 86
5 files changed, 333 insertions(+), 2 deletions(-)
create mode 100644 drivers/firmware/scmi/mailbox_agent.c
create mode 100644 drivers/firmware/scmi/smt.c
create mode 100644 drivers/firmware/scmi/smt.h
diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig
index 57e2ebbe42..c501bf4943 100644
--- a/drivers/firmware/scmi/Kconfig
+++ b/drivers/firmware/scmi/Kconfig
@@ -2,7 +2,7 @@ config SCMI_FIRMWARE
bool "Enable SCMI support"
select FIRMWARE
select OF_TRANSLATE
- depends on SANDBOX
+ depends on SANDBOX || DM_MAILBOX
help
System Control and Management Interface (SCMI) is a communication
protocol that defines standard interfaces for power, performance
@@ -14,4 +14,6 @@ config SCMI_FIRMWARE
or a companion host in the CPU system.
Communications between agent (client) and the SCMI server are
- based on message exchange.
+ based on message exchange. Messages can be exchange over tranport
+ channels as a mailbox device with some piece of identified shared
+ memory.
diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile
index 336ea1f2a3..d22f53efe7 100644
--- a/drivers/firmware/scmi/Makefile
+++ b/drivers/firmware/scmi/Makefile
@@ -1,2 +1,4 @@
obj-y += scmi_agent-uclass.o
+obj-y += smt.o
+obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o
obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o
diff --git a/drivers/firmware/scmi/mailbox_agent.c
b/drivers/firmware/scmi/mailbox_agent.c
new file mode 100644
index 00..7d9fb3622e
--- /dev/null
+++ b/drivers/firmware/scmi/mailbox_agent.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Linaro Limited.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "smt.h"
+
+#define TIMEOUT_US_10MS1
+
+/**
+ * struct scmi_mbox_channel - Description of an SCMI mailbox transport
+ * @smt: Shared memory buffer
+ * @mbox: Mailbox channel description
+ * @timeout_us:Timeout in microseconds for the mailbox transfer
+ */
+struct scmi_mbox_channel {
+ struct scmi_smt smt;
+ struct mbox_chan mbox;
+ ulong timeout_us;
+};
+
+static int scmi_mbox_process_msg(struct udevice *dev, struct scmi_msg *msg)
+{
+ struct scmi_mbox_channel *chan = dev_get_priv(dev);
+ int ret;
+
+ ret = scmi_write_msg_to_smt(dev, >smt, msg);
+ if (ret)
+ return ret;
+
+ /* Give shm addr to mbox in case it is meaningful */
+ ret = mbox_send(>mbox, chan->smt.buf);
+ if (ret) {
+ dev_err(dev, "Message send failed: %d\n", ret);
+ goto out;
+ }
+
+ /* Receive the response */
+ ret = mbox_recv(>mbox, chan->smt.buf, chan->timeout_us);
+ if (ret) {
+ dev_err(dev, "Response failed: %d, abort\n", ret);
+ goto out;
+ }
+
+ ret = scmi_read_resp_from_smt(dev, >smt, msg);
+
+out:
+ scmi_clear_smt_channel(>smt);
+
+ return ret;
+}
+
+int scmi_mbox_probe(struct udevice *dev)
+{
+ struct scmi_mbox_channel *chan = dev_get_priv(dev);
+ int ret;
+
+ chan->timeout_us = TIMEOUT_US_10MS;
+
+ ret = mbox_get_by_index(dev, 0, >mbox);
+ if (ret) {
+ dev_err(dev, "Failed to find mailbox: %d\n", ret);
+ goto out;
+ }
+
+ ret = scmi_dt_get_smt_buffer(dev, >smt);
+ if (ret)
+ dev_err(dev, "Failed to get shm resources: %d\n", ret);
+
+out:
+ if (ret)
+ devm_kfree(dev, chan);
+
+ return ret;
+}
+
+static const struct udevice_id scmi_mbox_ids[] = {
+