Mailing List Archive

[xen staging] xen/arm: Add imx8q{m,x} platform glue
commit 71d4356544ee49eeb6b58383f15eef330c7e8452
Author: John Ernberg <john.ernberg@actia.se>
AuthorDate: Mon Apr 8 16:11:35 2024 +0000
Commit: Stefano Stabellini <stefano.stabellini@amd.com>
CommitDate: Tue Apr 9 14:27:35 2024 -0700

xen/arm: Add imx8q{m,x} platform glue

When using Linux for dom0 there are a bunch of drivers that need to do SMC
SIP calls into the firmware to enable certain hardware bits like the
watchdog.

Provide a basic platform glue that implements the needed SMC forwarding.

The format of these calls are as follows:
- reg 0: function ID
- reg 1: subfunction ID (when there's a subfunction)
remaining regs: args

For now we only allow Dom0 to make these calls as they are all managing
hardware. There is no specification for these SIP calls, the IDs and names
have been extracted from the upstream linux kernel and the vendor kernel.

We can reject CPUFREQ because Dom0 cannot make an informed decision
regarding CPU frequency scaling, WAKEUP_SRC is to wake up from suspend,
which Xen doesn't support at this time.

This leaves the TIME SIP, OTP SIPs which for now are allowed to Dom0.

NOTE: This code is based on code found in NXP Xen tree located here:
https://github.com/nxp-imx/imx-xen/blob/lf-5.10.y_4.13/xen/arch/arm/platforms/imx8qm.c

Signed-off-by: Peng Fan <peng.fan@nxp.com>
[jernberg: Add SIP call filtering]
Signed-off-by: John Ernberg <john.ernberg@actia.se>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
[stefano: commit message improvement]
Signed-off-by: Stefano Stabellini <stefano.stabellini@amd.com>
---
xen/arch/arm/platforms/Makefile | 1 +
xen/arch/arm/platforms/imx8qm.c | 139 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+)

diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 8632f4115f..bec6e55d1f 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -9,5 +9,6 @@ obj-$(CONFIG_ALL_PLAT) += sunxi.o
obj-$(CONFIG_ALL64_PLAT) += thunderx.o
obj-$(CONFIG_ALL64_PLAT) += xgene-storm.o
obj-$(CONFIG_ALL64_PLAT) += brcm-raspberry-pi.o
+obj-$(CONFIG_ALL64_PLAT) += imx8qm.o
obj-$(CONFIG_MPSOC_PLATFORM) += xilinx-zynqmp.o
obj-$(CONFIG_MPSOC_PLATFORM) += xilinx-zynqmp-eemi.o
diff --git a/xen/arch/arm/platforms/imx8qm.c b/xen/arch/arm/platforms/imx8qm.c
new file mode 100644
index 0000000000..3600a073e8
--- /dev/null
+++ b/xen/arch/arm/platforms/imx8qm.c
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * xen/arch/arm/platforms/imx8qm.c
+ *
+ * i.MX 8QM setup
+ *
+ * Copyright (c) 2016 Freescale Inc.
+ * Copyright 2018-2019 NXP
+ *
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <xen/sched.h>
+#include <asm/platform.h>
+#include <asm/smccc.h>
+
+static const char * const imx8qm_dt_compat[] __initconst =
+{
+ "fsl,imx8qm",
+ "fsl,imx8qxp",
+ NULL
+};
+
+#define IMX_SIP_FID(fid) \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_CONV_64, \
+ ARM_SMCCC_OWNER_SIP, \
+ (fid))
+
+#define IMX_SIP_F_CPUFREQ 0x1
+#define IMX_SIP_F_TIME 0x2
+#define IMX_SIP_F_WAKEUP_SRC 0x9
+#define IMX_SIP_F_OTP_WRITE 0xB
+
+#define IMX_SIP_TIME_SF_RTC_SET_TIME 0x00
+#define IMX_SIP_TIME_SF_WDOG_START 0x01
+#define IMX_SIP_TIME_SF_WDOG_STOP 0x02
+#define IMX_SIP_TIME_SF_WDOG_SET_ACT 0x03
+#define IMX_SIP_TIME_SF_WDOG_PING 0x04
+#define IMX_SIP_TIME_SF_WDOG_SET_TIMEOUT 0x05
+#define IMX_SIP_TIME_SF_WDOG_GET_STAT 0x06
+#define IMX_SIP_TIME_SF_WDOG_SET_PRETIME 0x07
+
+static bool imx8qm_is_sip_time_call_ok(uint32_t subfunction_id)
+{
+ switch ( subfunction_id )
+ {
+ case IMX_SIP_TIME_SF_RTC_SET_TIME:
+ return true;
+ case IMX_SIP_TIME_SF_WDOG_START:
+ case IMX_SIP_TIME_SF_WDOG_STOP:
+ case IMX_SIP_TIME_SF_WDOG_SET_ACT:
+ case IMX_SIP_TIME_SF_WDOG_PING:
+ case IMX_SIP_TIME_SF_WDOG_SET_TIMEOUT:
+ case IMX_SIP_TIME_SF_WDOG_GET_STAT:
+ case IMX_SIP_TIME_SF_WDOG_SET_PRETIME:
+ return true;
+ default:
+ gprintk(XENLOG_WARNING, "imx8qm: smc: time: Unknown subfunction id %x\n",
+ subfunction_id);
+ return false;
+ }
+}
+
+static bool imx8qm_smc(struct cpu_user_regs *regs)
+{
+ uint32_t function_id = get_user_reg(regs, 0);
+ uint32_t subfunction_id = get_user_reg(regs, 1);
+ struct arm_smccc_res res;
+
+ if ( !cpus_have_const_cap(ARM_SMCCC_1_1) )
+ {
+ printk_once(XENLOG_WARNING
+ "imx8qm: smc: no SMCCC 1.1 support. Disabling firmware calls\n");
+
+ return false;
+ }
+
+ /* Only hardware domain may use the SIP calls */
+ if ( !is_hardware_domain(current->domain) )
+ {
+ gprintk(XENLOG_WARNING, "imx8qm: smc: No access\n");
+ return false;
+ }
+
+ switch ( function_id )
+ {
+ case IMX_SIP_FID(IMX_SIP_F_CPUFREQ):
+ /* Hardware domain can't take any informed decision here */
+ return false;
+ case IMX_SIP_FID(IMX_SIP_F_TIME):
+ if ( imx8qm_is_sip_time_call_ok(subfunction_id) )
+ goto allow_call;
+ return false;
+ /* Xen doesn't have suspend support */
+ case IMX_SIP_FID(IMX_SIP_F_WAKEUP_SRC):
+ return false;
+ case IMX_SIP_FID(IMX_SIP_F_OTP_WRITE):
+ /* subfunction_id is the fuse number, no sensible check possible */
+ goto allow_call;
+ default:
+ gprintk(XENLOG_WARNING, "imx8qm: smc: Unknown function id %x\n",
+ function_id);
+ return false;
+ }
+
+ allow_call:
+ arm_smccc_1_1_smc(function_id,
+ subfunction_id,
+ get_user_reg(regs, 2),
+ get_user_reg(regs, 3),
+ get_user_reg(regs, 4),
+ get_user_reg(regs, 5),
+ get_user_reg(regs, 6),
+ get_user_reg(regs, 7),
+ &res);
+
+ set_user_reg(regs, 0, res.a0);
+ set_user_reg(regs, 1, res.a1);
+ set_user_reg(regs, 2, res.a2);
+ set_user_reg(regs, 3, res.a3);
+
+ return true;
+}
+
+PLATFORM_START(imx8qm, "i.MX 8Q{M,XP}")
+ .compatible = imx8qm_dt_compat,
+ .smc = imx8qm_smc,
+PLATFORM_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
generated by git-patchbot for /home/xen/git/xen.git#staging