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
*/
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);
*/
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);
#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