From ea0f09d68332f80ae3affb11cca602b703781461 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Fri, 25 Oct 2019 11:33:36 -0700 Subject: [PATCH] firmware: qcom_scm-64: Improve SMC convention detection Improve the calling convention detection to use qcom_scm_call_atomic and not blindly assume 32-bit mode if the checks fails. __qcom_scm_is_call_available() cannot be used directly here as we want an atomic variant of is_call_available(). This is also a necessary requirement later when merging in legacy convention. Change-Id: I66beec550d05afde6c680d256183e8ad207d7268 Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-64.c | 35 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 66baa4ae7c10..694f8788a981 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -582,20 +582,29 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) void __qcom_scm_init(void) { - u64 cmd; - struct arm_smccc_res res; - u32 function = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, - QCOM_SCM_INFO_IS_CALL_AVAIL); + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_INFO, + .cmd = QCOM_SCM_INFO_IS_CALL_AVAIL, + .args[1] = SMCCC_FUNCNUM(QCOM_SCM_SVC_INFO, + QCOM_SCM_INFO_IS_CALL_AVAIL) | + (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT), + .arginfo = QCOM_SCM_ARGS(1); + .owner = ARM_SMCCC_OWNER_SIP, + }; - /* First try a SMC64 call */ - cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, - ARM_SMCCC_OWNER_SIP, function); + qcom_smcc_convention = ARM_SMCCC_SMC_64; + ret = qcom_scm_call_atomic(NULL, &desc); + if (!ret && desc.res[0] == 1) + goto out; - arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)), - 0, 0, 0, 0, 0, &res); + qcom_smcc_convention = ARM_SMCCC_SMC_32; + ret = qcom_scm_call_atomic(NULL, &desc); + if (!ret && desc.res[0] == 1) + goto out; - if (!res.a0 && res.a1) - qcom_smccc_convention = ARM_SMCCC_SMC_64; - else - qcom_smccc_convention = ARM_SMCCC_SMC_32; + qcom_smccc_convention = -1; + BUG(); +out: + pr_debug("QCOM SCM SMC Convention: %d\n", qcom_smcc_convention); }