Enable legacy calling convention in qcom_scm-64. Update is_call_available to use legacy function numbers when using legacy convention. Signed-off-by: Elliot Berman <eberman@xxxxxxxxxxxxxx> --- drivers/firmware/qcom_scm-64.c | 43 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 7bb68f2..355d9d7 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -60,6 +60,7 @@ struct arm_smccc_args { enum qcom_smc_convention { SMC_CONVENTION_UNKNOWN, + SMC_CONVENTION_LEGACY, SMC_CONVENTION_ARM_32, SMC_CONVENTION_ARM_64, }; @@ -415,7 +416,16 @@ static int qcom_scm_call_atomic_legacy(struct device *dev, static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) { might_sleep(); - return qcom_scm_call_smccc(dev, desc, false); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, false); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } } /** @@ -431,7 +441,16 @@ static int qcom_scm_call(struct device *dev, struct qcom_scm_desc *desc) */ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) { - return qcom_scm_call_smccc(dev, desc, true); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, true); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_atomic_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } } #define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 @@ -750,8 +769,19 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) }; desc.arginfo = QCOM_SCM_ARGS(1); - desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | - (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); + switch (qcom_smc_convention) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + desc.args[0] = SMCCC_FUNCNUM(svc_id, cmd_id) | + (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT); + break; + case SMC_CONVENTION_LEGACY: + desc.args[0] = LEGACY_FUNCNUM(svc_id, cmd_id); + break; + default: + pr_err("Unknown SMC convention being used\n"); + return -EINVAL; + } ret = qcom_scm_call(dev, &desc); @@ -898,6 +928,11 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) void __qcom_scm_init(void) { + qcom_smc_convention = SMC_CONVENTION_LEGACY; + if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, + QCOM_SCM_INFO_IS_CALL_AVAIL) == 1) + goto out; + qcom_smc_convention = SMC_CONVENTION_ARM_64; if (__qcom_scm_is_call_available(NULL, QCOM_SCM_SVC_INFO, QCOM_SCM_INFO_IS_CALL_AVAIL) == 1) -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project