diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 0382f9fa4501..491bbf70c94a 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -266,6 +266,28 @@ static int qcom_scm_set_boot_addr(void *entry, const u8 *cpu_bits) return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL); } +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 = { + virt_to_phys(entry), + /* Apply to all CPUs in all affinity levels */ + ~0ULL, ~0ULL, ~0ULL, ~0ULL, + flags, + }, + }; + + /* Need a device for DMA of the additional arguments */ + if (!__scm || __get_convention() == SMC_CONVENTION_LEGACY) + return -EOPNOTSUPP; + + return qcom_scm_call(__scm->dev, &desc, NULL); +} + /** * qcom_scm_set_warm_boot_addr() - Set the warm boot address for all cpus * @entry: Entry point function for the cpus @@ -275,7 +297,10 @@ static int qcom_scm_set_boot_addr(void *entry, const u8 *cpu_bits) */ int qcom_scm_set_warm_boot_addr(void *entry) { - return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_warm_bits); + if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_WARMBOOT)) + /* Fallback to old SCM call */ + return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_warm_bits); + return 0; } EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); @@ -285,7 +310,10 @@ EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); */ int qcom_scm_set_cold_boot_addr(void *entry) { - return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_cold_bits); + if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_COLDBOOT)) + /* Fallback to old SCM call */ + return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_cold_bits); + return 0; } EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 122b7baa3e2d..0d51eef2472f 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -78,9 +78,13 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, #define QCOM_SCM_BOOT_SET_ADDR 0x01 #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 +#define QCOM_SCM_BOOT_SET_ADDR_MC 0x11 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 #define QCOM_SCM_BOOT_MAX_CPUS 4 +#define QCOM_SCM_BOOT_MC_FLAG_AARCH64 BIT(0) +#define QCOM_SCM_BOOT_MC_FLAG_COLDBOOT BIT(1) +#define QCOM_SCM_BOOT_MC_FLAG_WARMBOOT BIT(2) #define QCOM_SCM_SVC_PIL 0x02 #define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01