U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table
@ 2026-06-02  7:18 Sam Day via B4 Relay
  2026-06-02  7:18 ` [PATCH v2 1/6] armv8: spin_table: Fix missing includes Sam Day via B4 Relay
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Sam Day via B4 Relay @ 2026-06-02  7:18 UTC (permalink / raw)
  To: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, Sumit Garg
  Cc: u-boot, u-boot-qcom, Casey Connolly, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas, Sam Day

This patch series depends on the "mach-snapdragon: handle platforms
without PSCI support" patch that was submitted earlier today. That first
patch lays some groundwork to handle detecting when a device is booting
without PSCI and deletes the /psci node in that case.

This series builds on top of that detection by rewriting all CPUs with
enable-method="psci" to "spin-table".

Once this is done, the existing spin-table support in U-Boot handles
further patching the nodes with the appropriate cpu-release-addr and
reserving the memory with the spin-table instructions.

Interestingly, this spin-table code doesn't seem to be in active use
anywhere, and it had bitrotted a little. But after blowing the dust off
it and fixing a couple of missing #includes, it works great.

I extended the spin-table support a little to make it easier for
consumers to plug in a method that is called for each CPU that needs to
be brought online. This saves the qcom board code from needing to hook
into ft_board_setup or something that runs before booting the OS.

Signed-off-by: Sam Day <me@samcday.com>
---
Changes in v2:
- Reworked the SCM impl to be a proper firmware driver, and streamlined
  the API so callers aren't forced to deal with calling conventions
  (thanks Casey).
- Link to v1: https://lore.kernel.org/r/20250128-msm8916-smp-support-v1-0-39587f18cf0c@samcday.com

---
Sam Day (6):
      armv8: spin_table: Fix missing includes
      armv8: spin_table: add hook for booting cores
      firmware: Add qcom SCM driver
      mach-snapdragon: fixup CPUs with PSCI enable-method
      mach-snapdragon: MSM8916 spin-table CPU boot support
      qcom_defconfig: enable spin-table support

 MAINTAINERS                            |   2 +
 arch/arm/cpu/armv8/spin_table.c        |  20 +++
 arch/arm/include/asm/spin_table.h      |   3 +
 arch/arm/mach-snapdragon/Makefile      |   1 +
 arch/arm/mach-snapdragon/board.c       |  41 +++++
 arch/arm/mach-snapdragon/msm8916-smp.c | 138 +++++++++++++++++
 configs/qcom_defconfig                 |   3 +
 drivers/firmware/Kconfig               |   9 ++
 drivers/firmware/Makefile              |   1 +
 drivers/firmware/qcom-scm.c            | 274 +++++++++++++++++++++++++++++++++
 include/firmware/qcom/scm.h            |  71 +++++++++
 11 files changed, 563 insertions(+)
---
base-commit: 30b77f6aa146c96b831cb4ece038130b655b6a41
change-id: 20250127-msm8916-smp-support-5f5e7b49d07e

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



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 1/6] armv8: spin_table: Fix missing includes
  2026-06-02  7:18 [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table Sam Day via B4 Relay
@ 2026-06-02  7:18 ` Sam Day via B4 Relay
  2026-06-02  7:18 ` [PATCH v2 2/6] armv8: spin_table: add hook for booting cores Sam Day via B4 Relay
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Sam Day via B4 Relay @ 2026-06-02  7:18 UTC (permalink / raw)
  To: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, Sumit Garg
  Cc: u-boot, u-boot-qcom, Casey Connolly, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas, Sam Day

From: Sam Day <me@samcday.com>

Dropping the common.h header resulted in the spin table header missing
asm/types.h and the source unit missing the errno.h includes.

Fixes: 7410cde67de0 ("arm: Remove <common.h> and add needed includes")
Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Sam Day <me@samcday.com>
---
 arch/arm/include/asm/spin_table.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/include/asm/spin_table.h b/arch/arm/include/asm/spin_table.h
index dec18c6e5c1..8fc61237e07 100644
--- a/arch/arm/include/asm/spin_table.h
+++ b/arch/arm/include/asm/spin_table.h
@@ -3,6 +3,8 @@
 #ifndef __ASM_SPIN_TABLE_H__
 #define __ASM_SPIN_TABLE_H__
 
+#include <asm/types.h>
+
 extern u64 spin_table_cpu_release_addr;
 extern char spin_table_reserve_begin;
 extern char spin_table_reserve_end;

-- 
2.54.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 2/6] armv8: spin_table: add hook for booting cores
  2026-06-02  7:18 [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table Sam Day via B4 Relay
  2026-06-02  7:18 ` [PATCH v2 1/6] armv8: spin_table: Fix missing includes Sam Day via B4 Relay
@ 2026-06-02  7:18 ` Sam Day via B4 Relay
  2026-06-02  7:18 ` [PATCH v2 3/6] firmware: Add qcom SCM driver Sam Day via B4 Relay
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Sam Day via B4 Relay @ 2026-06-02  7:18 UTC (permalink / raw)
  To: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, Sumit Garg
  Cc: u-boot, u-boot-qcom, Casey Connolly, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas, Sam Day

From: Sam Day <me@samcday.com>

Introduce the weak symbol spin_table_boot_cpu, which is called by
spin_table_update_dt during pre-boot FDT fixup phase for each CPU that
has enable-method="spin-table".

This saves the board/arch code from needing to scan the DT looking for
CPUs to boot, and also makes it easier to bring the secondary CPUs online
as late as possible.

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Sam Day <me@samcday.com>
---
 arch/arm/cpu/armv8/spin_table.c   | 20 ++++++++++++++++++++
 arch/arm/include/asm/spin_table.h |  1 +
 2 files changed, 21 insertions(+)

diff --git a/arch/arm/cpu/armv8/spin_table.c b/arch/arm/cpu/armv8/spin_table.c
index 5ba20efa33b..32bf680f02c 100644
--- a/arch/arm/cpu/armv8/spin_table.c
+++ b/arch/arm/cpu/armv8/spin_table.c
@@ -8,11 +8,18 @@
 #include <linux/libfdt.h>
 #include <asm/spin_table.h>
 
+int __weak spin_table_boot_cpu(void *fdt, int cpu_offset)
+{
+	return 0;
+}
+
 int spin_table_update_dt(void *fdt)
 {
 	int cpus_offset, offset;
 	const char *prop;
+	const void *release_addr;
 	int ret;
+	int found_cpus = 0;
 	unsigned long rsv_addr = (unsigned long)&spin_table_reserve_begin;
 	unsigned long rsv_size = &spin_table_reserve_end -
 						&spin_table_reserve_begin;
@@ -45,12 +52,25 @@ int spin_table_update_dt(void *fdt)
 		if (!prop || strcmp(prop, "cpu"))
 			continue;
 
+		release_addr = fdt_getprop(fdt, offset, "cpu-release-addr", NULL);
+		if (release_addr)
+			continue;
+
+		found_cpus = 1;
+
+		ret = spin_table_boot_cpu(fdt, offset);
+		if (ret)
+			return ret;
+
 		ret = fdt_setprop_u64(fdt, offset, "cpu-release-addr",
 				(unsigned long)&spin_table_cpu_release_addr);
 		if (ret)
 			return -ENOSPC;
 	}
 
+	if (!found_cpus)
+		return 0;
+
 	ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size);
 	if (ret)
 		return -ENOSPC;
diff --git a/arch/arm/include/asm/spin_table.h b/arch/arm/include/asm/spin_table.h
index 8fc61237e07..3c422046b83 100644
--- a/arch/arm/include/asm/spin_table.h
+++ b/arch/arm/include/asm/spin_table.h
@@ -10,5 +10,6 @@ extern char spin_table_reserve_begin;
 extern char spin_table_reserve_end;
 
 int spin_table_update_dt(void *fdt);
+int spin_table_boot_cpu(void *fdt, int cpu_offset);
 
 #endif /* __ASM_SPIN_TABLE_H__ */

-- 
2.54.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 3/6] firmware: Add qcom SCM driver
  2026-06-02  7:18 [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table Sam Day via B4 Relay
  2026-06-02  7:18 ` [PATCH v2 1/6] armv8: spin_table: Fix missing includes Sam Day via B4 Relay
  2026-06-02  7:18 ` [PATCH v2 2/6] armv8: spin_table: add hook for booting cores Sam Day via B4 Relay
@ 2026-06-02  7:18 ` Sam Day via B4 Relay
  2026-06-02  7:19 ` [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method Sam Day via B4 Relay
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Sam Day via B4 Relay @ 2026-06-02  7:18 UTC (permalink / raw)
  To: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, Sumit Garg
  Cc: u-boot, u-boot-qcom, Casey Connolly, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas, Sam Day

From: Sam Day <me@samcday.com>

Qualcomm's Secure Channel Manager (SCM) handles secure world calls. SCM
calls introduce extra ceremony on top of the standard SMCCC instruction
to support passing more arguments than a typical SMC call can
accommodate. There's also a qcom-specific smccc quirk.

This new driver determines the expected calling convention on probe. A
simple API is introduced to handle querying and calling SCM services.

Signed-off-by: Sam Day <me@samcday.com>
---
 MAINTAINERS                 |   2 +
 drivers/firmware/Kconfig    |   9 ++
 drivers/firmware/Makefile   |   1 +
 drivers/firmware/qcom-scm.c | 274 ++++++++++++++++++++++++++++++++++++++++++++
 include/firmware/qcom/scm.h |  71 ++++++++++++
 5 files changed, 357 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 571af196465..16b1e8e45dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -688,6 +688,8 @@ S:	Maintained
 T:	git https://source.denx.de/u-boot/custodians/u-boot-snapdragon.git
 F:	configs/qcm6490_defconfig
 F:	configs/qcs9100_defconfig
+F:	drivers/firmware/qcom-scm.c
+F:	include/firmware/qcom/
 F:	drivers/*/*/pm8???-*
 F:	drivers/gpio/msm_gpio.c
 F:	drivers/mmc/msm_sdhci.c
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 220de731950..2d5ae35d07f 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -47,5 +47,14 @@ config ARM_SMCCC_FEATURES
 	  the PSCI driver is always probed and binds dirvers registered to the Arm SMCCC
 	  services if any and reported as supported by the SMCCC firmware.
 
+config QCOM_SCM
+	bool "Qualcomm Secure Channel Manager"
+	depends on ARM_SMCCC
+	select FIRMWARE
+	help
+	  Enable support for Qualcomm Secure Channel Manager calls. These
+	  calls are used to ask the platform firmware to perform operations
+	  such as configuring secondary CPU boot addresses.
+
 source "drivers/firmware/arm-ffa/Kconfig"
 source "drivers/firmware/scmi/Kconfig"
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 9e7b118b074..0945a2e828d 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_$(PHASE_)ARM_PSCI_FW)	+= psci.o
 obj-$(CONFIG_TI_SCI_PROTOCOL)	+= ti_sci.o
 obj-$(CONFIG_SANDBOX)		+= firmware-sandbox.o
 obj-$(CONFIG_ZYNQMP_FIRMWARE)	+= firmware-zynqmp.o
+obj-$(CONFIG_QCOM_SCM)		+= qcom-scm.o
 obj-$(CONFIG_SCMI_FIRMWARE)	+= scmi/
diff --git a/drivers/firmware/qcom-scm.c b/drivers/firmware/qcom-scm.c
new file mode 100644
index 00000000000..7bb13c6b372
--- /dev/null
+++ b/drivers/firmware/qcom-scm.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2025 Linaro Ltd. */
+
+/* Much of this code was adapted from Linux kernel */
+/* Copyright (c) 2010-2015,2019 The Linux Foundation.	 All rights reserved.
+ */
+
+#include <compiler.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <errno.h>
+#include <firmware/qcom/scm.h>
+#include <linux/arm-smccc.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <malloc.h>
+#include <memalign.h>
+
+#define QCOM_SCM_EBUSY_WAIT_MS 30
+#define QCOM_SCM_EBUSY_MAX_RETRY 20
+
+#define SCM_SMC_N_REG_ARGS	4
+#define SCM_SMC_FIRST_EXT_IDX	(SCM_SMC_N_REG_ARGS - 1)
+#define SCM_SMC_N_EXT_ARGS	(MAX_QCOM_SCM_ARGS - SCM_SMC_N_REG_ARGS + 1)
+#define SCM_SMC_FIRST_REG_IDX	2
+#define SCM_SMC_LAST_REG_IDX	(SCM_SMC_FIRST_REG_IDX + SCM_SMC_N_REG_ARGS - 1)
+
+enum qcom_scm_convention {
+	SMC_CONVENTION_UNKNOWN,
+	SMC_CONVENTION_LEGACY,
+	SMC_CONVENTION_ARM_32,
+	SMC_CONVENTION_ARM_64,
+};
+
+#define SCM_SMC_FNID(s, c)	((((s) & 0xFF) << 8) | ((c) & 0xFF))
+
+#define QCOM_SCM_SVC_INFO		0x06
+#define QCOM_SCM_INFO_IS_CALL_AVAIL	0x01
+
+/* common error codes */
+#define QCOM_SCM_V2_EBUSY	-12
+#define QCOM_SCM_ENOMEM		-5
+#define QCOM_SCM_EOPNOTSUPP	-4
+#define QCOM_SCM_EINVAL_ADDR	-3
+#define QCOM_SCM_EINVAL_ARG	-2
+#define QCOM_SCM_ERROR		-1
+#define QCOM_SCM_INTERRUPTED	1
+
+static inline int qcom_scm_remap_error(int err)
+{
+	switch (err) {
+	case QCOM_SCM_ERROR:
+		return -EIO;
+	case QCOM_SCM_EINVAL_ADDR:
+	case QCOM_SCM_EINVAL_ARG:
+		return -EINVAL;
+	case QCOM_SCM_EOPNOTSUPP:
+		return -EOPNOTSUPP;
+	case QCOM_SCM_ENOMEM:
+		return -ENOMEM;
+	case QCOM_SCM_V2_EBUSY:
+		return -EBUSY;
+	}
+	return -EINVAL;
+}
+
+/**
+ * struct arm_smccc_args
+ * @args:	The array of values used in registers in smc instruction
+ */
+struct arm_smccc_args {
+	unsigned long args[8];
+};
+
+struct qcom_scm {
+	enum qcom_scm_convention convention;
+};
+
+static void __scm_smc_do_quirk(const struct arm_smccc_args *smc,
+			       struct arm_smccc_res *res)
+{
+	unsigned long a0 = smc->args[0];
+	struct arm_smccc_quirk quirk = { .id = ARM_SMCCC_QUIRK_QCOM_A6 };
+
+	quirk.state.a6 = 0;
+
+	do {
+		arm_smccc_smc_quirk(a0, smc->args[1], smc->args[2],
+				    smc->args[3], smc->args[4], smc->args[5],
+				    quirk.state.a6, smc->args[7], res, &quirk);
+
+		if (res->a0 == QCOM_SCM_INTERRUPTED)
+			a0 = res->a0;
+
+	} while (res->a0 == QCOM_SCM_INTERRUPTED);
+}
+
+static int __scm_smc_do(struct arm_smccc_args *smc, struct arm_smccc_res *res)
+{
+	int retry_count = 0;
+
+	do {
+		__scm_smc_do_quirk(smc, res);
+
+		if (res->a0 == QCOM_SCM_V2_EBUSY) {
+			if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
+				break;
+			mdelay(QCOM_SCM_EBUSY_WAIT_MS);
+		}
+	}  while (res->a0 == QCOM_SCM_V2_EBUSY);
+
+	return 0;
+}
+
+static int __qcom_scm_call(const struct qcom_scm_desc *desc,
+			   enum qcom_scm_convention qcom_convention,
+			   struct qcom_scm_res *res)
+{
+	int arglen = desc->arginfo & 0xf;
+	void *args = NULL;
+	int i, ret;
+	struct arm_smccc_args smc = {0};
+	struct arm_smccc_res smc_res;
+	u32 qcom_smccc_convention;
+	u32 fnid = SCM_SMC_FNID(desc->svc, desc->cmd);
+
+	switch (qcom_convention) {
+	case SMC_CONVENTION_ARM_32:
+		qcom_smccc_convention = ARM_SMCCC_SMC_32;
+		break;
+	case SMC_CONVENTION_ARM_64:
+		qcom_smccc_convention = ARM_SMCCC_SMC_64;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	smc.args[0] = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
+					 qcom_smccc_convention, desc->owner, fnid);
+	smc.args[1] = desc->arginfo;
+	for (i = 0; i < SCM_SMC_N_REG_ARGS; i++)
+		smc.args[i + SCM_SMC_FIRST_REG_IDX] = desc->args[i];
+
+	if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) {
+		args = malloc_cache_aligned(SCM_SMC_N_EXT_ARGS * sizeof(u64));
+		if (!args)
+			return -ENOMEM;
+
+		if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
+			__le32 *args32 = args;
+
+			for (i = 0; i < SCM_SMC_N_EXT_ARGS; i++)
+				args32[i] = cpu_to_le32(desc->args[i +
+							SCM_SMC_FIRST_EXT_IDX]);
+		} else {
+			__le64 *args64 = args;
+
+			for (i = 0; i < SCM_SMC_N_EXT_ARGS; i++)
+				args64[i] = cpu_to_le64(desc->args[i +
+							SCM_SMC_FIRST_EXT_IDX]);
+		}
+
+		smc.args[SCM_SMC_LAST_REG_IDX] = (phys_addr_t)args;
+		flush_cache((unsigned long)args,
+			    SCM_SMC_N_EXT_ARGS * sizeof(u64));
+	}
+
+	ret = __scm_smc_do(&smc, &smc_res);
+
+	if (args)
+		free(args);
+
+	if (ret)
+		return ret;
+
+	if (res) {
+		res->result[0] = smc_res.a1;
+		res->result[1] = smc_res.a2;
+		res->result[2] = smc_res.a3;
+	}
+
+	return (long)smc_res.a0 ? qcom_scm_remap_error(smc_res.a0) : 0;
+}
+
+static enum qcom_scm_convention qcom_scm_detect_convention(void)
+{
+	struct qcom_scm_desc desc = {
+		.svc = QCOM_SCM_SVC_INFO,
+		.cmd = QCOM_SCM_INFO_IS_CALL_AVAIL,
+		.owner = ARM_SMCCC_OWNER_SIP,
+		.arginfo = QCOM_SCM_ARGS(1),
+		.args = {
+			SCM_SMC_FNID(QCOM_SCM_SVC_INFO,
+				     QCOM_SCM_INFO_IS_CALL_AVAIL) |
+			(ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT)
+		},
+	};
+	struct qcom_scm_res scm_ret = {0};
+
+	if (IS_ENABLED(CONFIG_ARM64) &&
+	    !__qcom_scm_call(&desc, SMC_CONVENTION_ARM_64, &scm_ret) &&
+	    scm_ret.result[0] == 1)
+		return SMC_CONVENTION_ARM_64;
+
+	if (!__qcom_scm_call(&desc, SMC_CONVENTION_ARM_32, &scm_ret) &&
+	    scm_ret.result[0] == 1)
+		return SMC_CONVENTION_ARM_32;
+
+	return SMC_CONVENTION_UNKNOWN;
+}
+
+static int qcom_scm_get_device(struct udevice **devp)
+{
+	return uclass_get_device_by_driver(UCLASS_FIRMWARE,
+					   DM_DRIVER_GET(qcom_scm), devp);
+}
+
+int qcom_scm_call(const struct qcom_scm_desc *desc, struct qcom_scm_res *res)
+{
+	struct qcom_scm *scm;
+	struct udevice *dev;
+	int ret;
+
+	ret = qcom_scm_get_device(&dev);
+	if (ret)
+		return ret;
+
+	scm = dev_get_priv(dev);
+	return __qcom_scm_call(desc, scm->convention, res);
+}
+
+bool qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+{
+	u32 fnid = SCM_SMC_FNID(svc_id, cmd_id);
+	struct qcom_scm_res scm_ret = {0};
+	struct qcom_scm_desc desc = {
+		.svc = QCOM_SCM_SVC_INFO,
+		.cmd = QCOM_SCM_INFO_IS_CALL_AVAIL,
+		.owner = ARM_SMCCC_OWNER_SIP,
+		.arginfo = QCOM_SCM_ARGS(1),
+		.args = {
+			fnid | (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT)
+		},
+	};
+
+	if (qcom_scm_call(&desc, &scm_ret))
+		return false;
+
+	return scm_ret.result[0];
+}
+
+static int qcom_scm_probe(struct udevice *dev)
+{
+	struct qcom_scm *scm = dev_get_priv(dev);
+
+	scm->convention = qcom_scm_detect_convention();
+	if (scm->convention == SMC_CONVENTION_UNKNOWN)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static const struct udevice_id qcom_scm_of_match[] = {
+	{ .compatible = "qcom,scm" },
+	{ }
+};
+
+U_BOOT_DRIVER(qcom_scm) = {
+	.name = "qcom_scm",
+	.id = UCLASS_FIRMWARE,
+	.of_match = qcom_scm_of_match,
+	.probe = qcom_scm_probe,
+	.priv_auto = sizeof(struct qcom_scm),
+};
diff --git a/include/firmware/qcom/scm.h b/include/firmware/qcom/scm.h
new file mode 100644
index 00000000000..9f10c769928
--- /dev/null
+++ b/include/firmware/qcom/scm.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This header was adapted from linux/drivers/firmware/qcom/qcom_scm.h
+ * Copyright (c) 2010-2015,2019 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_SCM_H
+#define QCOM_SCM_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#define QCOM_SCM_SVC_BOOT		0x01
+#define QCOM_SCM_BOOT_SET_ADDR_MC	0x11
+#define QCOM_SCM_BOOT_MC_FLAG_AARCH64	BIT(0)
+#define QCOM_SCM_BOOT_MC_FLAG_COLDBOOT	BIT(1)
+
+#define MAX_QCOM_SCM_ARGS 10
+#define MAX_QCOM_SCM_RETS 3
+
+#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
+				   (((a) & 0x3) << 4) | \
+				   (((b) & 0x3) << 6) | \
+				   (((c) & 0x3) << 8) | \
+				   (((d) & 0x3) << 10) | \
+				   (((e) & 0x3) << 12) | \
+				   (((f) & 0x3) << 14) | \
+				   (((g) & 0x3) << 16) | \
+				   (((h) & 0x3) << 18) | \
+				   (((i) & 0x3) << 20) | \
+				   (((j) & 0x3) << 22) | \
+				   ((num) & 0xf))
+#define QCOM_SCM_ARGS(...) \
+	QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
+/**
+ * struct qcom_scm_desc
+ * @arginfo:	Metadata describing the arguments in args[]
+ * @args:	The array of arguments for the secure syscall
+ */
+struct qcom_scm_desc {
+	u32 svc;
+	u32 cmd;
+	u32 arginfo;
+	u64 args[MAX_QCOM_SCM_ARGS];
+	u32 owner;
+};
+
+/**
+ * struct qcom_scm_res
+ * @result:	The values returned by the secure syscall
+ */
+struct qcom_scm_res {
+	u64 result[MAX_QCOM_SCM_RETS];
+};
+
+#if CONFIG_IS_ENABLED(QCOM_SCM)
+bool qcom_scm_is_call_available(u32 svc_id, u32 cmd_id);
+int qcom_scm_call(const struct qcom_scm_desc *desc, struct qcom_scm_res *res);
+#else
+static inline bool qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+{
+	return false;
+}
+
+int qcom_scm_call(const struct qcom_scm_desc *desc, struct qcom_scm_res *res)
+{
+	return -ENOSYS;
+}
+#endif
+
+#endif

-- 
2.54.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method
  2026-06-02  7:18 [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table Sam Day via B4 Relay
                   ` (2 preceding siblings ...)
  2026-06-02  7:18 ` [PATCH v2 3/6] firmware: Add qcom SCM driver Sam Day via B4 Relay
@ 2026-06-02  7:19 ` Sam Day via B4 Relay
  2026-06-03 14:05   ` Stephan Gerhold
  2026-06-04  6:33   ` Neil Armstrong
  2026-06-02  7:19 ` [PATCH v2 5/6] mach-snapdragon: MSM8916 spin-table CPU boot support Sam Day via B4 Relay
  2026-06-02  7:19 ` [PATCH v2 6/6] qcom_defconfig: enable spin-table support Sam Day via B4 Relay
  5 siblings, 2 replies; 14+ messages in thread
From: Sam Day via B4 Relay @ 2026-06-02  7:19 UTC (permalink / raw)
  To: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, Sumit Garg
  Cc: u-boot, u-boot-qcom, Casey Connolly, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas, Sam Day

From: Sam Day <me@samcday.com>

If there's no PSCI implementation, then change the enable-method of all
CPUs from "psci" to "spin-table". Later, when spin_table_update_dt runs,
it will further patch the CPU nodes with the necessary cpu-release-addr.

This new fixup is only applied when CONFIG_ARMV8_SPIN_TABLE is enabled,
since that also determines whether spin_table_update_dt runs.

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

diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index 829a0109ac7..3b08069af98 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -183,7 +183,9 @@ static void show_psci_version(void)
 static void qcom_psci_fixup(void *fdt)
 {
 	int offset, ret;
+	uint reg;
 	struct arm_smccc_res res;
+	const char *prop;
 
 	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
 
@@ -198,6 +200,45 @@ static void qcom_psci_fixup(void *fdt)
 	ret = fdt_del_node(fdt, offset);
 	if (ret)
 		log_err("Failed to delete /psci node: %d\n", ret);
+
+	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
+		return;
+
+	/* If spin-table support is enabled, make sure any CPU nodes with a
+	 * PSCI enable-method are updated to spin-table. Further, any PSCI
+	 * power-domains properties are removed.
+	 */
+
+	offset = fdt_path_offset(fdt, "/cpus");
+	if (offset < 0)
+		return;
+
+	for (offset = fdt_first_subnode(fdt, offset);
+	     offset >= 0;
+	     offset = fdt_next_subnode(fdt, offset)) {
+		prop = fdt_getprop(fdt, offset, "device_type", NULL);
+		if (!prop || strcmp(prop, "cpu"))
+			continue;
+
+		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
+		if (!prop || strcmp(prop, "psci"))
+			continue;
+
+		reg = fdtdec_get_uint(fdt, offset, "reg", 0);
+		ret = fdt_setprop_string(fdt, offset,
+					 "enable-method", "spin-table");
+		if (ret)
+			log_err("Failed to set CPU%d enable-method to 'spin-table', this CPU will not be available to booted OS! %d\n",
+				reg, ret);
+
+		log_info("Patched CPU%d enable-method to 'spin-table'\n", reg);
+
+		prop = fdt_getprop(fdt, offset, "power-domain-names", NULL);
+		if (prop && !strcmp(prop, "psci")) {
+			fdt_delprop(fdt, offset, "power-domains");
+			fdt_delprop(fdt, offset, "power-domain-names");
+		}
+	}
 }
 
 /* We support booting U-Boot with an internal DT when running as a first-stage bootloader

-- 
2.54.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 5/6] mach-snapdragon: MSM8916 spin-table CPU boot support
  2026-06-02  7:18 [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table Sam Day via B4 Relay
                   ` (3 preceding siblings ...)
  2026-06-02  7:19 ` [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method Sam Day via B4 Relay
@ 2026-06-02  7:19 ` Sam Day via B4 Relay
  2026-06-03 14:12   ` Stephan Gerhold
  2026-06-02  7:19 ` [PATCH v2 6/6] qcom_defconfig: enable spin-table support Sam Day via B4 Relay
  5 siblings, 1 reply; 14+ messages in thread
From: Sam Day via B4 Relay @ 2026-06-02  7:19 UTC (permalink / raw)
  To: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, Sumit Garg
  Cc: u-boot, u-boot-qcom, Casey Connolly, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas, Sam Day

From: Sam Day <me@samcday.com>

Most MSM8916 devices lack PSCI support, instead they're brought online
with a qcom SCM call to set the boot address, and some register poking
of the APCS register block.

Signed-off-by: Sam Day <me@samcday.com>
---
 arch/arm/mach-snapdragon/Makefile      |   1 +
 arch/arm/mach-snapdragon/msm8916-smp.c | 138 +++++++++++++++++++++++++++++++++
 2 files changed, 139 insertions(+)

diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
index 343e825c6fd..584b8af055a 100644
--- a/arch/arm/mach-snapdragon/Makefile
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -5,3 +5,4 @@
 obj-y += board.o
 obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += capsule_update.o
 obj-$(CONFIG_OF_LIVE) += of_fixup.o
+obj-$(CONFIG_ARMV8_SPIN_TABLE) += msm8916-smp.o
diff --git a/arch/arm/mach-snapdragon/msm8916-smp.c b/arch/arm/mach-snapdragon/msm8916-smp.c
new file mode 100644
index 00000000000..24f5590ccc3
--- /dev/null
+++ b/arch/arm/mach-snapdragon/msm8916-smp.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * On MSM8916 devices that lack a PSCI implementation, firing up the secondary
+ * cores requires a call to TZ to set the boot address, and some poking of ACPS
+ * register block.
+ *
+ * Copyright (c) 2025 Linaro Ltd.
+ */
+
+#include <asm/io.h>
+#include <asm/spin_table.h>
+#include <asm/system.h>
+#include <cpu_func.h>
+#include <dm/ofnode.h>
+#include <firmware/qcom/scm.h>
+#include <linux/arm-smccc.h>
+#include <linux/delay.h>
+
+#define APCS_CPU_PWR_CTL	0x04
+#define CORE_PWRD_UP		BIT(7)
+#define COREPOR_RST		BIT(5)
+#define CORE_RST		BIT(4)
+#define CORE_MEM_HS		BIT(3)
+#define CORE_MEM_CLAMP		BIT(1)
+#define CLAMP			BIT(0)
+
+#define APC_PWR_GATE_CTL	0x14
+#define GDHS_CNT_SHIFT		24
+#define GDHS_EN			BIT(0)
+
+static void qcom_boot_cortex_a53(phys_addr_t acc_base)
+{
+	u32 reg_val;
+
+	/* Put the CPU into reset. */
+	reg_val = CORE_RST | COREPOR_RST | CLAMP | CORE_MEM_CLAMP;
+	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
+
+	/* Turn on the GDHS and set the GDHS_CNT to 16 XO clock cycles */
+	writel(GDHS_EN | (0x10 << GDHS_CNT_SHIFT), acc_base + APC_PWR_GATE_CTL);
+	/* Wait for the GDHS to settle */
+	udelay(2);
+
+	reg_val &= ~CORE_MEM_CLAMP;
+	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
+	reg_val |= CORE_MEM_HS;
+	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
+	udelay(2);
+
+	reg_val &= ~CLAMP;
+	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
+	udelay(2);
+
+	/* Release CPU out of reset and bring it to life. */
+	reg_val &= ~(CORE_RST | COREPOR_RST);
+	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
+	reg_val |= CORE_PWRD_UP;
+	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
+}
+
+static int qcom_scm_set_boot_addr_mc(void *entry, unsigned int flags)
+{
+	struct qcom_scm_desc desc = {
+		.svc = QCOM_SCM_SVC_BOOT,
+		.cmd = QCOM_SCM_BOOT_SET_ADDR_MC,
+		.owner = ARM_SMCCC_OWNER_SIP,
+		.arginfo = QCOM_SCM_ARGS(6),
+		.args = {
+			(u64)entry,
+			/* Apply to all CPUs in all affinity levels */
+			~0ULL, ~0ULL, ~0ULL, ~0ULL,
+			flags,
+		},
+	};
+
+	if (!qcom_scm_is_call_available(desc.svc, desc.cmd))
+		return -EOPNOTSUPP;
+
+	return qcom_scm_call(&desc, NULL);
+}
+
+static bool boot_addr_set;
+
+int spin_table_boot_cpu(void *fdt, int cpu_offset)
+{
+	struct fdtdec_phandle_args acc;
+	u32 mpidr_aff, acc_base, reg;
+	int ret;
+
+	if (fdt_node_check_compatible(fdt, 0, "qcom,msm8916"))
+		return 0;
+
+	reg = fdtdec_get_uint(fdt, cpu_offset, "reg", 0);
+
+	if (fdt_node_check_compatible(fdt, cpu_offset, "arm,cortex-a53")) {
+		log_warning("CPU%d is not arm,cortex-a53 compatible\n", reg);
+		return -EINVAL;
+	}
+
+	if (!boot_addr_set) {
+		debug("Setting CPU boot address to 0x%llx\n",
+		      (phys_addr_t)&spin_table_reserve_begin);
+		ret = qcom_scm_set_boot_addr_mc(&spin_table_reserve_begin,
+						QCOM_SCM_BOOT_MC_FLAG_AARCH64 |
+						QCOM_SCM_BOOT_MC_FLAG_COLDBOOT);
+		if (ret) {
+			log_err("Failed to set CPU boot addr: %d\n", ret);
+			return ret;
+		}
+
+		boot_addr_set = true;
+	}
+
+	mpidr_aff = read_mpidr() & 0xffffff;
+
+	if (reg == mpidr_aff) {
+		debug("Skipping boot of current CPU%d\n", reg);
+		return 0;
+	}
+
+	ret = fdtdec_parse_phandle_with_args(fdt, cpu_offset, "qcom,acc",
+					     NULL, 0, 0, &acc);
+	if (ret) {
+		log_err("Failed to parse qcom,acc phandle: %d\n", reg);
+		return ret;
+	}
+
+	acc_base = fdtdec_get_addr_size_auto_noparent(fdt, acc.node, "reg", 0,
+						      NULL, true);
+	if (!acc_base) {
+		log_err("Failed to parse qcom,acc regbase\n");
+		return -EINVAL;
+	}
+
+	log_info("Booting CPU%d @ 0x%x\n", reg, acc_base);
+	qcom_boot_cortex_a53(acc_base);
+	return 0;
+}

-- 
2.54.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 6/6] qcom_defconfig: enable spin-table support
  2026-06-02  7:18 [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table Sam Day via B4 Relay
                   ` (4 preceding siblings ...)
  2026-06-02  7:19 ` [PATCH v2 5/6] mach-snapdragon: MSM8916 spin-table CPU boot support Sam Day via B4 Relay
@ 2026-06-02  7:19 ` Sam Day via B4 Relay
  5 siblings, 0 replies; 14+ messages in thread
From: Sam Day via B4 Relay @ 2026-06-02  7:19 UTC (permalink / raw)
  To: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, Sumit Garg
  Cc: u-boot, u-boot-qcom, Casey Connolly, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas, Sam Day

From: Sam Day <me@samcday.com>

This is used by MSM8916 to bring secondary cores online when no PSCI
support is available.

Signed-off-by: Sam Day <me@samcday.com>
---
 configs/qcom_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index d0d54ec5a70..95897fe977e 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -1,4 +1,6 @@
 CONFIG_ARM=y
+CONFIG_ARMV8_MULTIENTRY=y
+CONFIG_ARMV8_SPIN_TABLE=y
 CONFIG_SKIP_LOWLEVEL_INIT=y
 CONFIG_POSITION_INDEPENDENT=y
 CONFIG_SYS_INIT_SP_BSS_OFFSET=0x180000
@@ -52,6 +54,7 @@ CONFIG_OF_LIVE=y
 CONFIG_OF_UPSTREAM_BUILD_VENDOR=y
 CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y
 CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="board/qualcomm/default.env"
+CONFIG_QCOM_SCM=y
 CONFIG_BUTTON_QCOM_PMIC=y
 CONFIG_CLK=y
 CONFIG_CLK_STUB=y

-- 
2.54.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method
  2026-06-02  7:19 ` [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method Sam Day via B4 Relay
@ 2026-06-03 14:05   ` Stephan Gerhold
  2026-06-04  6:33   ` Neil Armstrong
  1 sibling, 0 replies; 14+ messages in thread
From: Stephan Gerhold @ 2026-06-03 14:05 UTC (permalink / raw)
  To: me
  Cc: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, u-boot, u-boot-qcom, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas

On Tue, Jun 02, 2026 at 05:19:00PM +1000, Sam Day via B4 Relay wrote:
> From: Sam Day <me@samcday.com>
> 
> If there's no PSCI implementation, then change the enable-method of all
> CPUs from "psci" to "spin-table". Later, when spin_table_update_dt runs,
> it will further patch the CPU nodes with the necessary cpu-release-addr.
> 
> This new fixup is only applied when CONFIG_ARMV8_SPIN_TABLE is enabled,
> since that also determines whether spin_table_update_dt runs.
> 
> Signed-off-by: Sam Day <me@samcday.com>
> ---
>  arch/arm/mach-snapdragon/board.c | 41 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
> index 829a0109ac7..3b08069af98 100644
> --- a/arch/arm/mach-snapdragon/board.c
> +++ b/arch/arm/mach-snapdragon/board.c
> @@ -183,7 +183,9 @@ static void show_psci_version(void)
>  static void qcom_psci_fixup(void *fdt)
>  {
>  	int offset, ret;
> +	uint reg;
>  	struct arm_smccc_res res;
> +	const char *prop;
>  
>  	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
>  
> @@ -198,6 +200,45 @@ static void qcom_psci_fixup(void *fdt)
>  	ret = fdt_del_node(fdt, offset);
>  	if (ret)
>  		log_err("Failed to delete /psci node: %d\n", ret);
> +
> +	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
> +		return;
> +
> +	/* If spin-table support is enabled, make sure any CPU nodes with a
> +	 * PSCI enable-method are updated to spin-table. Further, any PSCI
> +	 * power-domains properties are removed.
> +	 */
> +
> +	offset = fdt_path_offset(fdt, "/cpus");
> +	if (offset < 0)
> +		return;
> +
> +	for (offset = fdt_first_subnode(fdt, offset);
> +	     offset >= 0;
> +	     offset = fdt_next_subnode(fdt, offset)) {

fdt_for_each_subnode()?

> +		prop = fdt_getprop(fdt, offset, "device_type", NULL);
> +		if (!prop || strcmp(prop, "cpu"))
> +			continue;
> +
> +		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
> +		if (!prop || strcmp(prop, "psci"))
> +			continue;
> +
> +		reg = fdtdec_get_uint(fdt, offset, "reg", 0);
> +		ret = fdt_setprop_string(fdt, offset,
> +					 "enable-method", "spin-table");
> +		if (ret)
> +			log_err("Failed to set CPU%d enable-method to 'spin-table', this CPU will not be available to booted OS! %d\n",
> +				reg, ret);
> +
> +		log_info("Patched CPU%d enable-method to 'spin-table'\n", reg);
> +
> +		prop = fdt_getprop(fdt, offset, "power-domain-names", NULL);
> +		if (prop && !strcmp(prop, "psci")) {
> +			fdt_delprop(fdt, offset, "power-domains");
> +			fdt_delprop(fdt, offset, "power-domain-names");
> +		}

So what if there is more than one power domains assigned and only one of
them is "psci"? (I had this at some point in a draft for full cpufreq
support for MSM8916)

I guess it makes sense deleting the "psci" power domain, since the
"idle-states" modification lk2nd does depends on some non-upstream
functionality in the msm8916-mainline/linux fork. But then it should
ideally look at the names more carefully somehow.

Thanks,
Stephan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 5/6] mach-snapdragon: MSM8916 spin-table CPU boot support
  2026-06-02  7:19 ` [PATCH v2 5/6] mach-snapdragon: MSM8916 spin-table CPU boot support Sam Day via B4 Relay
@ 2026-06-03 14:12   ` Stephan Gerhold
  2026-06-03 23:25     ` Sam Day
  0 siblings, 1 reply; 14+ messages in thread
From: Stephan Gerhold @ 2026-06-03 14:12 UTC (permalink / raw)
  To: me
  Cc: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, u-boot, u-boot-qcom, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas

On Tue, Jun 02, 2026 at 05:19:01PM +1000, Sam Day via B4 Relay wrote:
> From: Sam Day <me@samcday.com>
> 
> Most MSM8916 devices lack PSCI support, instead they're brought online
> with a qcom SCM call to set the boot address, and some register poking
> of the APCS register block.
> 
> Signed-off-by: Sam Day <me@samcday.com>
> ---
>  arch/arm/mach-snapdragon/Makefile      |   1 +
>  arch/arm/mach-snapdragon/msm8916-smp.c | 138 +++++++++++++++++++++++++++++++++
>  2 files changed, 139 insertions(+)
> 
> diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
> index 343e825c6fd..584b8af055a 100644
> --- a/arch/arm/mach-snapdragon/Makefile
> +++ b/arch/arm/mach-snapdragon/Makefile
> @@ -5,3 +5,4 @@
>  obj-y += board.o
>  obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += capsule_update.o
>  obj-$(CONFIG_OF_LIVE) += of_fixup.o
> +obj-$(CONFIG_ARMV8_SPIN_TABLE) += msm8916-smp.o
> diff --git a/arch/arm/mach-snapdragon/msm8916-smp.c b/arch/arm/mach-snapdragon/msm8916-smp.c
> new file mode 100644
> index 00000000000..24f5590ccc3
> --- /dev/null
> +++ b/arch/arm/mach-snapdragon/msm8916-smp.c
> @@ -0,0 +1,138 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * On MSM8916 devices that lack a PSCI implementation, firing up the secondary
> + * cores requires a call to TZ to set the boot address, and some poking of ACPS
> + * register block.
> + *
> + * Copyright (c) 2025 Linaro Ltd.
> + */

Was Linaro involved in this in 2025? Did you write the code yourself
(the init sequence, especially) or take it over from somewhere else?
Would be good to be precise here.

> +
> +#include <asm/io.h>
> +#include <asm/spin_table.h>
> +#include <asm/system.h>
> +#include <cpu_func.h>
> +#include <dm/ofnode.h>
> +#include <firmware/qcom/scm.h>
> +#include <linux/arm-smccc.h>
> +#include <linux/delay.h>
> +
> +#define APCS_CPU_PWR_CTL	0x04
> +#define CORE_PWRD_UP		BIT(7)
> +#define COREPOR_RST		BIT(5)
> +#define CORE_RST		BIT(4)
> +#define CORE_MEM_HS		BIT(3)
> +#define CORE_MEM_CLAMP		BIT(1)
> +#define CLAMP			BIT(0)
> +
> +#define APC_PWR_GATE_CTL	0x14
> +#define GDHS_CNT_SHIFT		24
> +#define GDHS_EN			BIT(0)
> +
> +static void qcom_boot_cortex_a53(phys_addr_t acc_base)
> +{
> +	u32 reg_val;
> +
> +	/* Put the CPU into reset. */
> +	reg_val = CORE_RST | COREPOR_RST | CLAMP | CORE_MEM_CLAMP;
> +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> +
> +	/* Turn on the GDHS and set the GDHS_CNT to 16 XO clock cycles */
> +	writel(GDHS_EN | (0x10 << GDHS_CNT_SHIFT), acc_base + APC_PWR_GATE_CTL);
> +	/* Wait for the GDHS to settle */
> +	udelay(2);
> +
> +	reg_val &= ~CORE_MEM_CLAMP;
> +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> +	reg_val |= CORE_MEM_HS;
> +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> +	udelay(2);
> +
> +	reg_val &= ~CLAMP;
> +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> +	udelay(2);
> +
> +	/* Release CPU out of reset and bring it to life. */
> +	reg_val &= ~(CORE_RST | COREPOR_RST);
> +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> +	reg_val |= CORE_PWRD_UP;
> +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);

Nitpick (might be fine as-is, since Linux seems to have the same):
Strictly speaking, I think we need some memory barriers / DSBs in here
to make sure the write is complete before the udelay() starts (although
this is notoriously hard. If you're interested in this, take a look at
https://youtu.be/i6DayghhA8Q?t=1677, although I think it doesn't
translate exactly to U-Boot).

> +}
> +
> +static int qcom_scm_set_boot_addr_mc(void *entry, unsigned int flags)
> +{
> +	struct qcom_scm_desc desc = {
> +		.svc = QCOM_SCM_SVC_BOOT,
> +		.cmd = QCOM_SCM_BOOT_SET_ADDR_MC,
> +		.owner = ARM_SMCCC_OWNER_SIP,
> +		.arginfo = QCOM_SCM_ARGS(6),
> +		.args = {
> +			(u64)entry,
> +			/* Apply to all CPUs in all affinity levels */
> +			~0ULL, ~0ULL, ~0ULL, ~0ULL,
> +			flags,
> +		},
> +	};
> +
> +	if (!qcom_scm_is_call_available(desc.svc, desc.cmd))
> +		return -EOPNOTSUPP;
> +
> +	return qcom_scm_call(&desc, NULL);
> +}
> +
> +static bool boot_addr_set;
> +
> +int spin_table_boot_cpu(void *fdt, int cpu_offset)
> +{
> +	struct fdtdec_phandle_args acc;
> +	u32 mpidr_aff, acc_base, reg;
> +	int ret;
> +
> +	if (fdt_node_check_compatible(fdt, 0, "qcom,msm8916"))
> +		return 0;

What if we have a qcom,apq8016? :)

> +
> +	reg = fdtdec_get_uint(fdt, cpu_offset, "reg", 0);
> +
> +	if (fdt_node_check_compatible(fdt, cpu_offset, "arm,cortex-a53")) {
> +		log_warning("CPU%d is not arm,cortex-a53 compatible\n", reg);
> +		return -EINVAL;
> +	}
> +
> +	if (!boot_addr_set) {
> +		debug("Setting CPU boot address to 0x%llx\n",
> +		      (phys_addr_t)&spin_table_reserve_begin);
> +		ret = qcom_scm_set_boot_addr_mc(&spin_table_reserve_begin,
> +						QCOM_SCM_BOOT_MC_FLAG_AARCH64 |
> +						QCOM_SCM_BOOT_MC_FLAG_COLDBOOT);
> +		if (ret) {
> +			log_err("Failed to set CPU boot addr: %d\n", ret);
> +			return ret;
> +		}
> +
> +		boot_addr_set = true;
> +	}

I would move this below log_info("Booting CPU"), so you don't waste
doing this for nothing if one of the other check fails.

> +
> +	mpidr_aff = read_mpidr() & 0xffffff;
> +
> +	if (reg == mpidr_aff) {
> +		debug("Skipping boot of current CPU%d\n", reg);
> +		return 0;
> +	}
> +
> +	ret = fdtdec_parse_phandle_with_args(fdt, cpu_offset, "qcom,acc",
> +					     NULL, 0, 0, &acc);
> +	if (ret) {
> +		log_err("Failed to parse qcom,acc phandle: %d\n", reg);
> +		return ret;
> +	}
> +
> +	acc_base = fdtdec_get_addr_size_auto_noparent(fdt, acc.node, "reg", 0,
> +						      NULL, true);
> +	if (!acc_base) {
> +		log_err("Failed to parse qcom,acc regbase\n");
> +		return -EINVAL;
> +	}
> +
> +	log_info("Booting CPU%d @ 0x%x\n", reg, acc_base);
> +	qcom_boot_cortex_a53(acc_base);
> +	return 0;
> +}

Thanks,
Stephan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 5/6] mach-snapdragon: MSM8916 spin-table CPU boot support
  2026-06-03 14:12   ` Stephan Gerhold
@ 2026-06-03 23:25     ` Sam Day
  0 siblings, 0 replies; 14+ messages in thread
From: Sam Day @ 2026-06-03 23:25 UTC (permalink / raw)
  To: Stephan Gerhold
  Cc: Tom Rini, Neil Armstrong, Mark Kettenis, Sumit Garg,
	Casey Connolly, u-boot, u-boot-qcom, Simon Glass, Kory Maincent,
	Yao Zi, Peng Fan, Kuan-Wei Chiu, Raymond Mao, Quentin Schulz,
	Stefan Roese, Jerome Forissier, Philip Molloy, Michael Trimarchi,
	Michal Simek, Sughosh Ganu, Antony Kurniawan Soemardi,
	Aswin Murugan, Varadarajan Narayanan, Marek Vasut, Luca Weiss,
	Ilias Apalodimas

Hey Stephan,

On Thursday, 4 June 2026 at 12:12 AM, Stephan Gerhold <stephan.gerhold@linaro.org> wrote:

> On Tue, Jun 02, 2026 at 05:19:01PM +1000, Sam Day via B4 Relay wrote:
> > From: Sam Day <me@samcday.com>
> >
> > Most MSM8916 devices lack PSCI support, instead they're brought online
> > with a qcom SCM call to set the boot address, and some register poking
> > of the APCS register block.
> >
> > Signed-off-by: Sam Day <me@samcday.com>
> > ---
> >  arch/arm/mach-snapdragon/Makefile      |   1 +
> >  arch/arm/mach-snapdragon/msm8916-smp.c | 138 +++++++++++++++++++++++++++++++++
> >  2 files changed, 139 insertions(+)
> >
> > diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
> > index 343e825c6fd..584b8af055a 100644
> > --- a/arch/arm/mach-snapdragon/Makefile
> > +++ b/arch/arm/mach-snapdragon/Makefile
> > @@ -5,3 +5,4 @@
> >  obj-y += board.o
> >  obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += capsule_update.o
> >  obj-$(CONFIG_OF_LIVE) += of_fixup.o
> > +obj-$(CONFIG_ARMV8_SPIN_TABLE) += msm8916-smp.o
> > diff --git a/arch/arm/mach-snapdragon/msm8916-smp.c b/arch/arm/mach-snapdragon/msm8916-smp.c
> > new file mode 100644
> > index 00000000000..24f5590ccc3
> > --- /dev/null
> > +++ b/arch/arm/mach-snapdragon/msm8916-smp.c
> > @@ -0,0 +1,138 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * On MSM8916 devices that lack a PSCI implementation, firing up the secondary
> > + * cores requires a call to TZ to set the boot address, and some poking of ACPS
> > + * register block.
> > + *
> > + * Copyright (c) 2025 Linaro Ltd.
> > + */
> 
> Was Linaro involved in this in 2025? Did you write the code yourself
> (the init sequence, especially) or take it over from somewhere else?
> Would be good to be precise here.

Uh - I don't remember why Jan-2025 Sam thought to place Linaro copyrights here.
I think the logic was that, since I don't care about owning the copyright, I
figured I'd just assign it to the entity that owns a lot of the code in
mach-snapdragon already.

Anyway, since most of the code here came from the kernel, and I used lk2nd as
a reference, I'll just preserve those copyrights in v3 instead.

> 
> > +
> > +#include <asm/io.h>
> > +#include <asm/spin_table.h>
> > +#include <asm/system.h>
> > +#include <cpu_func.h>
> > +#include <dm/ofnode.h>
> > +#include <firmware/qcom/scm.h>
> > +#include <linux/arm-smccc.h>
> > +#include <linux/delay.h>
> > +
> > +#define APCS_CPU_PWR_CTL	0x04
> > +#define CORE_PWRD_UP		BIT(7)
> > +#define COREPOR_RST		BIT(5)
> > +#define CORE_RST		BIT(4)
> > +#define CORE_MEM_HS		BIT(3)
> > +#define CORE_MEM_CLAMP		BIT(1)
> > +#define CLAMP			BIT(0)
> > +
> > +#define APC_PWR_GATE_CTL	0x14
> > +#define GDHS_CNT_SHIFT		24
> > +#define GDHS_EN			BIT(0)
> > +
> > +static void qcom_boot_cortex_a53(phys_addr_t acc_base)
> > +{
> > +	u32 reg_val;
> > +
> > +	/* Put the CPU into reset. */
> > +	reg_val = CORE_RST | COREPOR_RST | CLAMP | CORE_MEM_CLAMP;
> > +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> > +
> > +	/* Turn on the GDHS and set the GDHS_CNT to 16 XO clock cycles */
> > +	writel(GDHS_EN | (0x10 << GDHS_CNT_SHIFT), acc_base + APC_PWR_GATE_CTL);
> > +	/* Wait for the GDHS to settle */
> > +	udelay(2);
> > +
> > +	reg_val &= ~CORE_MEM_CLAMP;
> > +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> > +	reg_val |= CORE_MEM_HS;
> > +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> > +	udelay(2);
> > +
> > +	reg_val &= ~CLAMP;
> > +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> > +	udelay(2);
> > +
> > +	/* Release CPU out of reset and bring it to life. */
> > +	reg_val &= ~(CORE_RST | COREPOR_RST);
> > +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> > +	reg_val |= CORE_PWRD_UP;
> > +	writel(reg_val, acc_base + APCS_CPU_PWR_CTL);
> 
> Nitpick (might be fine as-is, since Linux seems to have the same):
> Strictly speaking, I think we need some memory barriers / DSBs in here
> to make sure the write is complete before the udelay() starts (although
> this is notoriously hard. If you're interested in this, take a look at
> https://youtu.be/i6DayghhA8Q?t=1677, although I think it doesn't
> translate exactly to U-Boot).

Hmm yeah, it's odd because kernel is *not* issuing barriers in the
cortex_a7 startup sequence, but *is* for kpss v1/v2. Since lk2nd
already has prior art for this I'll just follow that lead in v3.

> 
> > +}
> > +
> > +static int qcom_scm_set_boot_addr_mc(void *entry, unsigned int flags)
> > +{
> > +	struct qcom_scm_desc desc = {
> > +		.svc = QCOM_SCM_SVC_BOOT,
> > +		.cmd = QCOM_SCM_BOOT_SET_ADDR_MC,
> > +		.owner = ARM_SMCCC_OWNER_SIP,
> > +		.arginfo = QCOM_SCM_ARGS(6),
> > +		.args = {
> > +			(u64)entry,
> > +			/* Apply to all CPUs in all affinity levels */
> > +			~0ULL, ~0ULL, ~0ULL, ~0ULL,
> > +			flags,
> > +		},
> > +	};
> > +
> > +	if (!qcom_scm_is_call_available(desc.svc, desc.cmd))
> > +		return -EOPNOTSUPP;
> > +
> > +	return qcom_scm_call(&desc, NULL);
> > +}
> > +
> > +static bool boot_addr_set;
> > +
> > +int spin_table_boot_cpu(void *fdt, int cpu_offset)
> > +{
> > +	struct fdtdec_phandle_args acc;
> > +	u32 mpidr_aff, acc_base, reg;
> > +	int ret;
> > +
> > +	if (fdt_node_check_compatible(fdt, 0, "qcom,msm8916"))
> > +		return 0;
> 
> What if we have a qcom,apq8016? :)

Wellll, in that case there's a functional TZ that can handle the PSCI call,
right? ;) I suppose there's probably situations where that's not the case.
Rabble rabble rabble.

Anyway, I added this check in the eleventh hour right before submitting,
because I was paranoid that it might impact some other platform (big-tent board
code is great but also hellish). In retrospect this is unnecessary:
spin_table_boot_cpu() is kicked by the generic code for each spin-table CPU
it finds in the DT. We only force cores to spin-table enablement when we detect
the busted-PSCI situation.

I've removed this check entirely in v3.

> 
> > +
> > +	reg = fdtdec_get_uint(fdt, cpu_offset, "reg", 0);
> > +
> > +	if (fdt_node_check_compatible(fdt, cpu_offset, "arm,cortex-a53")) {
> > +		log_warning("CPU%d is not arm,cortex-a53 compatible\n", reg);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!boot_addr_set) {
> > +		debug("Setting CPU boot address to 0x%llx\n",
> > +		      (phys_addr_t)&spin_table_reserve_begin);
> > +		ret = qcom_scm_set_boot_addr_mc(&spin_table_reserve_begin,
> > +						QCOM_SCM_BOOT_MC_FLAG_AARCH64 |
> > +						QCOM_SCM_BOOT_MC_FLAG_COLDBOOT);
> > +		if (ret) {
> > +			log_err("Failed to set CPU boot addr: %d\n", ret);
> > +			return ret;
> > +		}
> > +
> > +		boot_addr_set = true;
> > +	}
> 
> I would move this below log_info("Booting CPU"), so you don't waste
> doing this for nothing if one of the other check fails.

Good catch, fixed in v3.

Thanks for the thorough review Stephan!
-Sam

> 
> > +
> > +	mpidr_aff = read_mpidr() & 0xffffff;
> > +
> > +	if (reg == mpidr_aff) {
> > +		debug("Skipping boot of current CPU%d\n", reg);
> > +		return 0;
> > +	}
> > +
> > +	ret = fdtdec_parse_phandle_with_args(fdt, cpu_offset, "qcom,acc",
> > +					     NULL, 0, 0, &acc);
> > +	if (ret) {
> > +		log_err("Failed to parse qcom,acc phandle: %d\n", reg);
> > +		return ret;
> > +	}
> > +
> > +	acc_base = fdtdec_get_addr_size_auto_noparent(fdt, acc.node, "reg", 0,
> > +						      NULL, true);
> > +	if (!acc_base) {
> > +		log_err("Failed to parse qcom,acc regbase\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	log_info("Booting CPU%d @ 0x%x\n", reg, acc_base);
> > +	qcom_boot_cortex_a53(acc_base);
> > +	return 0;
> > +}
> 
> Thanks,
> Stephan
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method
  2026-06-02  7:19 ` [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method Sam Day via B4 Relay
  2026-06-03 14:05   ` Stephan Gerhold
@ 2026-06-04  6:33   ` Neil Armstrong
  2026-06-04  6:53     ` Sam Day
  1 sibling, 1 reply; 14+ messages in thread
From: Neil Armstrong @ 2026-06-04  6:33 UTC (permalink / raw)
  To: me, Tom Rini, Mark Kettenis, Sumit Garg, Casey Connolly
  Cc: u-boot, u-boot-qcom, Simon Glass, Kory Maincent, Yao Zi, Peng Fan,
	Kuan-Wei Chiu, Raymond Mao, Quentin Schulz, Stefan Roese,
	Jerome Forissier, Philip Molloy, Michael Trimarchi, Michal Simek,
	Sughosh Ganu, Antony Kurniawan Soemardi, Aswin Murugan,
	Varadarajan Narayanan, Marek Vasut, Luca Weiss, Ilias Apalodimas

On 6/2/26 09:19, Sam Day via B4 Relay wrote:
> From: Sam Day <me@samcday.com>
> 
> If there's no PSCI implementation, then change the enable-method of all
> CPUs from "psci" to "spin-table". Later, when spin_table_update_dt runs,
> it will further patch the CPU nodes with the necessary cpu-release-addr.
> 
> This new fixup is only applied when CONFIG_ARMV8_SPIN_TABLE is enabled,
> since that also determines whether spin_table_update_dt runs.
> 
> Signed-off-by: Sam Day <me@samcday.com>
> ---
>   arch/arm/mach-snapdragon/board.c | 41 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 41 insertions(+)
> 
> diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
> index 829a0109ac7..3b08069af98 100644
> --- a/arch/arm/mach-snapdragon/board.c
> +++ b/arch/arm/mach-snapdragon/board.c
> @@ -183,7 +183,9 @@ static void show_psci_version(void)
>   static void qcom_psci_fixup(void *fdt)
>   {
>   	int offset, ret;
> +	uint reg;
>   	struct arm_smccc_res res;
> +	const char *prop;
>   
>   	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
>   
> @@ -198,6 +200,45 @@ static void qcom_psci_fixup(void *fdt)
>   	ret = fdt_del_node(fdt, offset);
>   	if (ret)
>   		log_err("Failed to delete /psci node: %d\n", ret);
> +
> +	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
> +		return;

Can this be dynamic ?

Neil

> +
> +	/* If spin-table support is enabled, make sure any CPU nodes with a
> +	 * PSCI enable-method are updated to spin-table. Further, any PSCI
> +	 * power-domains properties are removed.
> +	 */
> +
> +	offset = fdt_path_offset(fdt, "/cpus");
> +	if (offset < 0)
> +		return;
> +
> +	for (offset = fdt_first_subnode(fdt, offset);
> +	     offset >= 0;
> +	     offset = fdt_next_subnode(fdt, offset)) {
> +		prop = fdt_getprop(fdt, offset, "device_type", NULL);
> +		if (!prop || strcmp(prop, "cpu"))
> +			continue;
> +
> +		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
> +		if (!prop || strcmp(prop, "psci"))
> +			continue;
> +
> +		reg = fdtdec_get_uint(fdt, offset, "reg", 0);
> +		ret = fdt_setprop_string(fdt, offset,
> +					 "enable-method", "spin-table");
> +		if (ret)
> +			log_err("Failed to set CPU%d enable-method to 'spin-table', this CPU will not be available to booted OS! %d\n",
> +				reg, ret);
> +
> +		log_info("Patched CPU%d enable-method to 'spin-table'\n", reg);
> +
> +		prop = fdt_getprop(fdt, offset, "power-domain-names", NULL);
> +		if (prop && !strcmp(prop, "psci")) {
> +			fdt_delprop(fdt, offset, "power-domains");
> +			fdt_delprop(fdt, offset, "power-domain-names");
> +		}
> +	}
>   }
>   
>   /* We support booting U-Boot with an internal DT when running as a first-stage bootloader
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method
  2026-06-04  6:33   ` Neil Armstrong
@ 2026-06-04  6:53     ` Sam Day
  2026-06-04  6:59       ` Neil Armstrong
  0 siblings, 1 reply; 14+ messages in thread
From: Sam Day @ 2026-06-04  6:53 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: Tom Rini, Mark Kettenis, Sumit Garg, Casey Connolly, u-boot,
	u-boot-qcom, Simon Glass, Kory Maincent, Yao Zi, Peng Fan,
	Kuan-Wei Chiu, Raymond Mao, Quentin Schulz, Stefan Roese,
	Jerome Forissier, Philip Molloy, Michael Trimarchi, Michal Simek,
	Sughosh Ganu, Antony Kurniawan Soemardi, Aswin Murugan,
	Varadarajan Narayanan, Marek Vasut, Luca Weiss, Ilias Apalodimas

Hey Neil,

On Thursday, 4 June 2026 at 4:33 PM, Neil Armstrong <neil.armstrong@linaro.org> wrote:

> On 6/2/26 09:19, Sam Day via B4 Relay wrote:
> > From: Sam Day <me@samcday.com>
> >
> > If there's no PSCI implementation, then change the enable-method of all
> > CPUs from "psci" to "spin-table". Later, when spin_table_update_dt runs,
> > it will further patch the CPU nodes with the necessary cpu-release-addr.
> >
> > This new fixup is only applied when CONFIG_ARMV8_SPIN_TABLE is enabled,
> > since that also determines whether spin_table_update_dt runs.
> >
> > Signed-off-by: Sam Day <me@samcday.com>
> > ---
> >   arch/arm/mach-snapdragon/board.c | 41 ++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 41 insertions(+)
> >
> > diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
> > index 829a0109ac7..3b08069af98 100644
> > --- a/arch/arm/mach-snapdragon/board.c
> > +++ b/arch/arm/mach-snapdragon/board.c
> > @@ -183,7 +183,9 @@ static void show_psci_version(void)
> >   static void qcom_psci_fixup(void *fdt)
> >   {
> >   	int offset, ret;
> > +	uint reg;
> >   	struct arm_smccc_res res;
> > +	const char *prop;
> >
> >   	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
> >
> > @@ -198,6 +200,45 @@ static void qcom_psci_fixup(void *fdt)
> >   	ret = fdt_del_node(fdt, offset);
> >   	if (ret)
> >   		log_err("Failed to delete /psci node: %d\n", ret);
> > +
> > +	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
> > +		return;
> 
> Can this be dynamic ?

Sure can! ... Just as soon as I pin down exactly what you mean by that :D

Are you asking that this be guarded not just by ARMV8_SPIN_TABLE
enablement, but also by root device compatible?

e.g:

	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
		return;

	if (fdt_node_check_compatible(fdt, 0, "qcom,msm8916") &&
        fdt_node_check_compatible(fdt, 0, "qcom,apq8016"))
		return;

Kind regards,
Sam

> 
> Neil
> 
> > +
> > +	/* If spin-table support is enabled, make sure any CPU nodes with a
> > +	 * PSCI enable-method are updated to spin-table. Further, any PSCI
> > +	 * power-domains properties are removed.
> > +	 */
> > +
> > +	offset = fdt_path_offset(fdt, "/cpus");
> > +	if (offset < 0)
> > +		return;
> > +
> > +	for (offset = fdt_first_subnode(fdt, offset);
> > +	     offset >= 0;
> > +	     offset = fdt_next_subnode(fdt, offset)) {
> > +		prop = fdt_getprop(fdt, offset, "device_type", NULL);
> > +		if (!prop || strcmp(prop, "cpu"))
> > +			continue;
> > +
> > +		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
> > +		if (!prop || strcmp(prop, "psci"))
> > +			continue;
> > +
> > +		reg = fdtdec_get_uint(fdt, offset, "reg", 0);
> > +		ret = fdt_setprop_string(fdt, offset,
> > +					 "enable-method", "spin-table");
> > +		if (ret)
> > +			log_err("Failed to set CPU%d enable-method to 'spin-table', this CPU will not be available to booted OS! %d\n",
> > +				reg, ret);
> > +
> > +		log_info("Patched CPU%d enable-method to 'spin-table'\n", reg);
> > +
> > +		prop = fdt_getprop(fdt, offset, "power-domain-names", NULL);
> > +		if (prop && !strcmp(prop, "psci")) {
> > +			fdt_delprop(fdt, offset, "power-domains");
> > +			fdt_delprop(fdt, offset, "power-domain-names");
> > +		}
> > +	}
> >   }
> >
> >   /* We support booting U-Boot with an internal DT when running as a first-stage bootloader
> >
> 
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method
  2026-06-04  6:53     ` Sam Day
@ 2026-06-04  6:59       ` Neil Armstrong
  2026-06-07  3:49         ` Sam Day
  0 siblings, 1 reply; 14+ messages in thread
From: Neil Armstrong @ 2026-06-04  6:59 UTC (permalink / raw)
  To: Sam Day
  Cc: Tom Rini, Mark Kettenis, Sumit Garg, Casey Connolly, u-boot,
	u-boot-qcom, Simon Glass, Kory Maincent, Yao Zi, Peng Fan,
	Kuan-Wei Chiu, Raymond Mao, Quentin Schulz, Stefan Roese,
	Jerome Forissier, Philip Molloy, Michael Trimarchi, Michal Simek,
	Sughosh Ganu, Antony Kurniawan Soemardi, Aswin Murugan,
	Varadarajan Narayanan, Marek Vasut, Luca Weiss, Ilias Apalodimas

Hi,

On 6/4/26 08:53, Sam Day wrote:
> Hey Neil,
> 
> On Thursday, 4 June 2026 at 4:33 PM, Neil Armstrong <neil.armstrong@linaro.org> wrote:
> 
>> On 6/2/26 09:19, Sam Day via B4 Relay wrote:
>>> From: Sam Day <me@samcday.com>
>>>
>>> If there's no PSCI implementation, then change the enable-method of all
>>> CPUs from "psci" to "spin-table". Later, when spin_table_update_dt runs,
>>> it will further patch the CPU nodes with the necessary cpu-release-addr.
>>>
>>> This new fixup is only applied when CONFIG_ARMV8_SPIN_TABLE is enabled,
>>> since that also determines whether spin_table_update_dt runs.
>>>
>>> Signed-off-by: Sam Day <me@samcday.com>
>>> ---
>>>    arch/arm/mach-snapdragon/board.c | 41 ++++++++++++++++++++++++++++++++++++++++
>>>    1 file changed, 41 insertions(+)
>>>
>>> diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
>>> index 829a0109ac7..3b08069af98 100644
>>> --- a/arch/arm/mach-snapdragon/board.c
>>> +++ b/arch/arm/mach-snapdragon/board.c
>>> @@ -183,7 +183,9 @@ static void show_psci_version(void)
>>>    static void qcom_psci_fixup(void *fdt)
>>>    {
>>>    	int offset, ret;
>>> +	uint reg;
>>>    	struct arm_smccc_res res;
>>> +	const char *prop;
>>>
>>>    	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
>>>
>>> @@ -198,6 +200,45 @@ static void qcom_psci_fixup(void *fdt)
>>>    	ret = fdt_del_node(fdt, offset);
>>>    	if (ret)
>>>    		log_err("Failed to delete /psci node: %d\n", ret);
>>> +
>>> +	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
>>> +		return;
>>
>> Can this be dynamic ?
> 
> Sure can! ... Just as soon as I pin down exactly what you mean by that :D
> 
> Are you asking that this be guarded not just by ARMV8_SPIN_TABLE
> enablement, but also by root device compatible?
> 
> e.g:
> 
> 	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
> 		return;
> 
> 	if (fdt_node_check_compatible(fdt, 0, "qcom,msm8916") &&
>          fdt_node_check_compatible(fdt, 0, "qcom,apq8016"))
> 		return;

Yes perhaps move this in a helper function to guard all the spin table functionality ?

Thanks,
Neil

> 
> Kind regards,
> Sam
> 
>>
>> Neil
>>
>>> +
>>> +	/* If spin-table support is enabled, make sure any CPU nodes with a
>>> +	 * PSCI enable-method are updated to spin-table. Further, any PSCI
>>> +	 * power-domains properties are removed.
>>> +	 */
>>> +
>>> +	offset = fdt_path_offset(fdt, "/cpus");
>>> +	if (offset < 0)
>>> +		return;
>>> +
>>> +	for (offset = fdt_first_subnode(fdt, offset);
>>> +	     offset >= 0;
>>> +	     offset = fdt_next_subnode(fdt, offset)) {
>>> +		prop = fdt_getprop(fdt, offset, "device_type", NULL);
>>> +		if (!prop || strcmp(prop, "cpu"))
>>> +			continue;
>>> +
>>> +		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
>>> +		if (!prop || strcmp(prop, "psci"))
>>> +			continue;
>>> +
>>> +		reg = fdtdec_get_uint(fdt, offset, "reg", 0);
>>> +		ret = fdt_setprop_string(fdt, offset,
>>> +					 "enable-method", "spin-table");
>>> +		if (ret)
>>> +			log_err("Failed to set CPU%d enable-method to 'spin-table', this CPU will not be available to booted OS! %d\n",
>>> +				reg, ret);
>>> +
>>> +		log_info("Patched CPU%d enable-method to 'spin-table'\n", reg);
>>> +
>>> +		prop = fdt_getprop(fdt, offset, "power-domain-names", NULL);
>>> +		if (prop && !strcmp(prop, "psci")) {
>>> +			fdt_delprop(fdt, offset, "power-domains");
>>> +			fdt_delprop(fdt, offset, "power-domain-names");
>>> +		}
>>> +	}
>>>    }
>>>
>>>    /* We support booting U-Boot with an internal DT when running as a first-stage bootloader
>>>
>>
>>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method
  2026-06-04  6:59       ` Neil Armstrong
@ 2026-06-07  3:49         ` Sam Day
  0 siblings, 0 replies; 14+ messages in thread
From: Sam Day @ 2026-06-07  3:49 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: Tom Rini, Mark Kettenis, Sumit Garg, Casey Connolly, u-boot,
	u-boot-qcom, Simon Glass, Kory Maincent, Yao Zi, Peng Fan,
	Kuan-Wei Chiu, Raymond Mao, Quentin Schulz, Stefan Roese,
	Jerome Forissier, Philip Molloy, Michael Trimarchi, Michal Simek,
	Sughosh Ganu, Antony Kurniawan Soemardi, Aswin Murugan,
	Varadarajan Narayanan, Marek Vasut, Luca Weiss, Ilias Apalodimas

Hello Neil,

On Thursday, 4 June 2026 at 4:59 PM, Neil Armstrong <neil.armstrong@linaro.org> wrote:

> Hi,
> 
> On 6/4/26 08:53, Sam Day wrote:
> > Hey Neil,
> >
> > On Thursday, 4 June 2026 at 4:33 PM, Neil Armstrong <neil.armstrong@linaro.org> wrote:
> >
> >> On 6/2/26 09:19, Sam Day via B4 Relay wrote:
> >>> From: Sam Day <me@samcday.com>
> >>>
> >>> If there's no PSCI implementation, then change the enable-method of all
> >>> CPUs from "psci" to "spin-table". Later, when spin_table_update_dt runs,
> >>> it will further patch the CPU nodes with the necessary cpu-release-addr.
> >>>
> >>> This new fixup is only applied when CONFIG_ARMV8_SPIN_TABLE is enabled,
> >>> since that also determines whether spin_table_update_dt runs.
> >>>
> >>> Signed-off-by: Sam Day <me@samcday.com>
> >>> ---
> >>>    arch/arm/mach-snapdragon/board.c | 41 ++++++++++++++++++++++++++++++++++++++++
> >>>    1 file changed, 41 insertions(+)
> >>>
> >>> diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
> >>> index 829a0109ac7..3b08069af98 100644
> >>> --- a/arch/arm/mach-snapdragon/board.c
> >>> +++ b/arch/arm/mach-snapdragon/board.c
> >>> @@ -183,7 +183,9 @@ static void show_psci_version(void)
> >>>    static void qcom_psci_fixup(void *fdt)
> >>>    {
> >>>    	int offset, ret;
> >>> +	uint reg;
> >>>    	struct arm_smccc_res res;
> >>> +	const char *prop;
> >>>
> >>>    	arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
> >>>
> >>> @@ -198,6 +200,45 @@ static void qcom_psci_fixup(void *fdt)
> >>>    	ret = fdt_del_node(fdt, offset);
> >>>    	if (ret)
> >>>    		log_err("Failed to delete /psci node: %d\n", ret);
> >>> +
> >>> +	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
> >>> +		return;
> >>
> >> Can this be dynamic ?
> >
> > Sure can! ... Just as soon as I pin down exactly what you mean by that :D
> >
> > Are you asking that this be guarded not just by ARMV8_SPIN_TABLE
> > enablement, but also by root device compatible?
> >
> > e.g:
> >
> > 	if (!CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE))
> > 		return;
> >
> > 	if (fdt_node_check_compatible(fdt, 0, "qcom,msm8916") &&
> >          fdt_node_check_compatible(fdt, 0, "qcom,apq8016"))
> > 		return;
> 
> Yes perhaps move this in a helper function to guard all the spin table functionality ?

Ack, I've queued that up for v3. This series already introduces msm8916-smp.c, so
it was easy enough to move it over there.

Best,
-Sam

> 
> Thanks,
> Neil
> 
> >
> > Kind regards,
> > Sam
> >
> >>
> >> Neil
> >>
> >>> +
> >>> +	/* If spin-table support is enabled, make sure any CPU nodes with a
> >>> +	 * PSCI enable-method are updated to spin-table. Further, any PSCI
> >>> +	 * power-domains properties are removed.
> >>> +	 */
> >>> +
> >>> +	offset = fdt_path_offset(fdt, "/cpus");
> >>> +	if (offset < 0)
> >>> +		return;
> >>> +
> >>> +	for (offset = fdt_first_subnode(fdt, offset);
> >>> +	     offset >= 0;
> >>> +	     offset = fdt_next_subnode(fdt, offset)) {
> >>> +		prop = fdt_getprop(fdt, offset, "device_type", NULL);
> >>> +		if (!prop || strcmp(prop, "cpu"))
> >>> +			continue;
> >>> +
> >>> +		prop = fdt_getprop(fdt, offset, "enable-method", NULL);
> >>> +		if (!prop || strcmp(prop, "psci"))
> >>> +			continue;
> >>> +
> >>> +		reg = fdtdec_get_uint(fdt, offset, "reg", 0);
> >>> +		ret = fdt_setprop_string(fdt, offset,
> >>> +					 "enable-method", "spin-table");
> >>> +		if (ret)
> >>> +			log_err("Failed to set CPU%d enable-method to 'spin-table', this CPU will not be available to booted OS! %d\n",
> >>> +				reg, ret);
> >>> +
> >>> +		log_info("Patched CPU%d enable-method to 'spin-table'\n", reg);
> >>> +
> >>> +		prop = fdt_getprop(fdt, offset, "power-domain-names", NULL);
> >>> +		if (prop && !strcmp(prop, "psci")) {
> >>> +			fdt_delprop(fdt, offset, "power-domains");
> >>> +			fdt_delprop(fdt, offset, "power-domain-names");
> >>> +		}
> >>> +	}
> >>>    }
> >>>
> >>>    /* We support booting U-Boot with an internal DT when running as a first-stage bootloader
> >>>
> >>
> >>
> 
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-06-07  3:49 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-02  7:18 [PATCH v2 0/6] MSM8916: Bring secondary cores online with spin-table Sam Day via B4 Relay
2026-06-02  7:18 ` [PATCH v2 1/6] armv8: spin_table: Fix missing includes Sam Day via B4 Relay
2026-06-02  7:18 ` [PATCH v2 2/6] armv8: spin_table: add hook for booting cores Sam Day via B4 Relay
2026-06-02  7:18 ` [PATCH v2 3/6] firmware: Add qcom SCM driver Sam Day via B4 Relay
2026-06-02  7:19 ` [PATCH v2 4/6] mach-snapdragon: fixup CPUs with PSCI enable-method Sam Day via B4 Relay
2026-06-03 14:05   ` Stephan Gerhold
2026-06-04  6:33   ` Neil Armstrong
2026-06-04  6:53     ` Sam Day
2026-06-04  6:59       ` Neil Armstrong
2026-06-07  3:49         ` Sam Day
2026-06-02  7:19 ` [PATCH v2 5/6] mach-snapdragon: MSM8916 spin-table CPU boot support Sam Day via B4 Relay
2026-06-03 14:12   ` Stephan Gerhold
2026-06-03 23:25     ` Sam Day
2026-06-02  7:19 ` [PATCH v2 6/6] qcom_defconfig: enable spin-table support Sam Day via B4 Relay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox