diff mbox series

[12/14,HACK] mailbox: add new arm smc/hvc mailbox

Message ID 20211104142324.2879-12-etienne.carriere@linaro.org
State New
Headers show
Series [01/14] firmware: scmi: fix description of an API function | expand

Commit Message

Etienne Carriere Nov. 4, 2021, 2:23 p.m. UTC
From: Etienne Carriere <etienne.carriere@st.com>


Basic mailbox inspired from https://patchwork.kernel.org/patch/11166071/.

When sending a message, the mailbox invokes the Cortex-A Arm Trustzone
secure monitor with an SMC or HVC instruction providing a function
identifier in register R0/X0 defined by the DTB.

Signed-off-by: Etienne Carriere <etienne.carriere@st.com>

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>

---
 drivers/mailbox/Kconfig        |   8 +++
 drivers/mailbox/Makefile       |   1 +
 drivers/mailbox/arm-smc-mbox.c | 123 +++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 drivers/mailbox/arm-smc-mbox.c

-- 
2.17.1
diff mbox series

Patch

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index dd4b0ac0c3..599d1df1ae 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -47,4 +47,12 @@  config ZYNQMP_IPI
 	help
 	  This enables support for the Xilinx ZynqMP Inter Processor Interrupt
 	  communication controller.
+
+config ARM_SMC_MAILBOX
+	bool "Enable Arm SMC mailbox support"
+        depends on DM_MAILBOX && ARM_SMCCC
+	default y
+	help
+	  Mailbox notification through an Arm SMC or HVC calls.
+
 endmenu
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index d2ace8cd21..7a56a454b8 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -3,6 +3,7 @@ 
 # Copyright (c) 2016, NVIDIA CORPORATION.
 #
 
+obj-$(CONFIG_ARM_SMC_MAILBOX) += arm-smc-mbox.o
 obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox-uclass.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o
 obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o
diff --git a/drivers/mailbox/arm-smc-mbox.c b/drivers/mailbox/arm-smc-mbox.c
new file mode 100644
index 0000000000..d379da490a
--- /dev/null
+++ b/drivers/mailbox/arm-smc-mbox.c
@@ -0,0 +1,123 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019, Linaro Limited
+ */
+
+#define LOG_CATEGORY UCLASS_MAILBOX
+
+#include <common.h>
+#include <dm.h>
+#include <mailbox-uclass.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <linux/arm-smccc.h>
+#include <linux/compat.h>
+
+#define ARM_SMC_METHOD		0
+#define ARM_HVC_METHOD		1
+
+typedef void (invoke_fn_t)(unsigned long);
+
+struct smc_pdata {
+	unsigned long func_id;
+	invoke_fn_t *invoke_fn;
+};
+
+/* Simple wrapper functions to be able to use a function pointer */
+static void smccc_smc(unsigned long a0)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(a0, 0, 0, 0, 0, 0, 0, 0, &res);
+}
+
+static void smccc_hvc(unsigned long a0)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_hvc(a0, 0, 0, 0, 0, 0, 0, 0, &res);
+}
+
+static int smc_mbox_send(struct mbox_chan *chan, const void *data)
+{
+	struct smc_pdata *pdata = dev_get_plat(chan->dev);
+
+	/*
+	 * This mailbox invokes secure world for a channel event.
+	 * Message is already in the channel's shared memory.
+	 */
+	pdata->invoke_fn(pdata->func_id);
+
+	return 0;
+}
+
+static int smc_mbox_recv(struct mbox_chan *chan, void *data)
+{
+	/* Mbox owner already got the return message from shared memory */
+	return 0;
+}
+
+static int smc_mbox_request(struct mbox_chan *chan)
+{
+	return 0;
+}
+
+static int smc_mbox_rfree(struct mbox_chan *chan)
+{
+	return 0;
+}
+
+static int smc_mbox_of_xlate(struct mbox_chan *chan,
+			     struct ofnode_phandle_args *args)
+{
+	if (args->args_count)
+		dev_warn(chan->dev, "Expect no argument to smc-mbox cells\n");
+
+	chan->id = 0;
+
+	return 0;
+}
+
+static int smc_mbox_ofdata_to_platdata(struct udevice *dev)
+{
+	ulong compat_data = dev_get_driver_data(dev);
+	struct smc_pdata *pdata = dev_get_plat(dev);
+	u32 func_id;
+
+	if (dev_read_u32(dev, "arm,func-id", &func_id)) {
+		dev_err(dev, "Missing property arm,func-id\n");
+		return -EINVAL;
+	}
+
+	pdata->func_id = func_id;
+
+	if (compat_data == ARM_SMC_METHOD)
+		pdata->invoke_fn = smccc_smc;
+	else
+		pdata->invoke_fn = smccc_hvc;
+
+	return 0;
+}
+
+static const struct udevice_id smc_mbox_ids[] = {
+	{ .compatible = "arm,smc-mbox", .data = ARM_SMC_METHOD, },
+	{ .compatible = "arm,hvc-mbox", .data = ARM_HVC_METHOD, },
+	{ }
+};
+
+struct mbox_ops smc_mbox_ops = {
+	.of_xlate = smc_mbox_of_xlate,
+	.request = smc_mbox_request,
+	.rfree = smc_mbox_rfree,
+	.send = smc_mbox_send,
+	.recv = smc_mbox_recv,
+};
+
+U_BOOT_DRIVER(smc_mbox) = {
+	.name = "arm_smc_mbox",
+	.id = UCLASS_MAILBOX,
+	.of_match = smc_mbox_ids,
+	.of_to_plat = smc_mbox_ofdata_to_platdata,
+	.plat_auto = sizeof(struct smc_pdata),
+	.ops = &smc_mbox_ops,
+};