[PATCH] mach-snapdragon: handle platforms without PSCI support

Sam Day me at samcday.com
Mon Jan 27 15:48:55 CET 2025


Most MSM8916 devices shipped without PSCI support. The history is quite
nuanced (a good overview can be found in [1]), but the end result is
that the upstream DTs for this SoC pretend that PSCI exists, and it's
expected that the bootloader handles the case where it doesn't. This is
codified by the de-facto bootloader for MSM8916 devices, lk2nd [2].

So we handle it here by deleting the /psci node if we detect the absence
of PSCI. We need to do this early to ensure sysreset works correctly,
since the PSCI firmware driver is PRE_RELOC and binds the PSCI sysreset
driver.

Additionally, show_psci_version is updated to check that PSCI exists.
Currently this banner outputs "PSCI: 65535.65535" on devices without
PSCI support, which isn't very useful :)

[1]: https://github.com/msm8916-mainline/linux/issues/388
[2]: https://github.com/msm8916-mainline/lk2nd/blob/8183ea2/lk2nd/smp/spin-table/spin-table.c#L237

Signed-off-by: Sam Day <me at samcday.com>
---
 arch/arm/mach-snapdragon/board.c | 43 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index e87551784b8d7afb4186533d43b8bddacba9faec..75b9cf1a8a1b3383665eb2d4e6725efe59718de0 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -162,11 +162,42 @@ static void show_psci_version(void)
 
 	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
 
+	/* Some older SoCs like MSM8916 don't always support PSCI */
+	if ((int)res.a0 == PSCI_RET_NOT_SUPPORTED)
+		return;
+
 	debug("PSCI:  v%ld.%ld\n",
 	      PSCI_VERSION_MAJOR(res.a0),
 	      PSCI_VERSION_MINOR(res.a0));
 }
 
+/**
+ * Most MSM8916 devices in the wild shipped without PSCI support, but the
+ * upstream DTs pretend that PSCI exists. If that situation is detected here,
+ * the /psci node is deleted. This is done very early to ensure the PSCI
+ * firmware driver doesn't bind (which then binds a sysreset driver that won't
+ * work).
+ */
+static void qcom_psci_fixup(void *fdt)
+{
+	int offset, ret;
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
+
+	if ((int)res.a0 != PSCI_RET_NOT_SUPPORTED)
+		return;
+
+	offset = fdt_path_offset(fdt, "/psci");
+	if (offset < 0)
+		return;
+
+	debug("Found /psci DT node on device with no PSCI. Deleting.\n");
+	ret = fdt_del_node(fdt, offset);
+	if (ret)
+		log_err("Failed to delete /psci node: %d\n", ret);
+}
+
 /* We support booting U-Boot with an internal DT when running as a first-stage bootloader
  * or for supporting quirky devices where it's easier to leave the downstream DT in place
  * to improve ABL compatibility. Otherwise, we use the DT provided by ABL.
@@ -212,12 +243,16 @@ int board_fdt_blob_setup(void **fdtp)
 
 	if (internal_valid) {
 		debug("Using built in FDT\n");
-		return -EEXIST;
+		ret = -EEXIST;
+	} else {
+		debug("Using external FDT\n");
+		*fdtp = external_fdt;
+		ret = 0;
 	}
 
-	debug("Using external FDT\n");
-	*fdtp = external_fdt;
-	return 0;
+	qcom_psci_fixup(*fdtp);
+
+	return ret;
 }
 
 void reset_cpu(void)

---
base-commit: 2eed5a1ff36217372e19f7513bd07077fc76718a
change-id: 20250127-qcom-handle-absent-psci-6e8e8af7bcd7
prerequisite-change-id: 20250120-qcom-parse-memory-updates-96ffe248cdf1:v3
prerequisite-patch-id: 65448b5a93120d2117c1361035afc9bd911d005f

Best regards,
-- 
Sam Day <me at samcday.com>




More information about the U-Boot mailing list