mirror of https://gitee.com/openkylin/linux.git
firmware: qcom_scm-64: Add SCM results struct
Remove knowledge of arm_smccc_res struct from client wrappers so that client wrappers only work QCOM SCM data structures. SCM calls may have up to 3 arguments, so qcom_scm_call_smccc is responsible now for filling those 3 arguments accordingly. This is necessary to support merging legacy and SMC conventions in an upcoming patch. Tested-by: Brian Masney <masneyb@onstation.org> # arm32 Tested-by: Stephan Gerhold <stephan@gerhold.net> Signed-off-by: Elliot Berman <eberman@codeaurora.org> Link: https://lore.kernel.org/r/1578431066-19600-7-git-send-email-eberman@codeaurora.org Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
parent
b30a2a72b8
commit
1f7166fdae
|
@ -45,7 +45,6 @@ enum qcom_scm_arg_types {
|
|||
* struct qcom_scm_desc
|
||||
* @arginfo: Metadata describing the arguments in args[]
|
||||
* @args: The array of arguments for the secure syscall
|
||||
* @res: The values returned by the secure syscall
|
||||
*/
|
||||
struct qcom_scm_desc {
|
||||
u32 svc;
|
||||
|
@ -55,6 +54,14 @@ struct qcom_scm_desc {
|
|||
u32 owner;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct qcom_scm_res
|
||||
* @result: The values returned by the secure syscall
|
||||
*/
|
||||
struct qcom_scm_res {
|
||||
u64 result[MAX_QCOM_SCM_RETS];
|
||||
};
|
||||
|
||||
static u64 qcom_smccc_convention = -1;
|
||||
static DEFINE_MUTEX(qcom_scm_lock);
|
||||
|
||||
|
@ -116,7 +123,7 @@ static void __scm_smc_do(const struct qcom_scm_desc *desc,
|
|||
}
|
||||
|
||||
static int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
|
||||
struct arm_smccc_res *res, bool atomic)
|
||||
struct qcom_scm_res *res, bool atomic)
|
||||
{
|
||||
int arglen = desc->arginfo & 0xf;
|
||||
int i;
|
||||
|
@ -125,6 +132,7 @@ static int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
|
|||
void *args_virt = NULL;
|
||||
size_t alloc_len;
|
||||
gfp_t flag = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
struct arm_smccc_res smc_res;
|
||||
|
||||
if (unlikely(arglen > SCM_SMC_N_REG_ARGS)) {
|
||||
alloc_len = SCM_SMC_N_EXT_ARGS * sizeof(u64);
|
||||
|
@ -158,17 +166,20 @@ static int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
|
|||
x5 = args_phys;
|
||||
}
|
||||
|
||||
__scm_smc_do(desc, res, x5, atomic);
|
||||
__scm_smc_do(desc, &smc_res, x5, atomic);
|
||||
|
||||
if (args_virt) {
|
||||
dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
|
||||
kfree(args_virt);
|
||||
}
|
||||
|
||||
if ((long)res->a0 < 0)
|
||||
return qcom_scm_remap_error(res->a0);
|
||||
if (res) {
|
||||
res->result[0] = smc_res.a1;
|
||||
res->result[1] = smc_res.a2;
|
||||
res->result[2] = smc_res.a3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (long)smc_res.a0 ? qcom_scm_remap_error(smc_res.a0) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,7 +193,7 @@ static int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc,
|
|||
* This should *only* be called in pre-emptible context.
|
||||
*/
|
||||
static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc,
|
||||
struct arm_smccc_res *res)
|
||||
struct qcom_scm_res *res)
|
||||
{
|
||||
might_sleep();
|
||||
return __scm_smc_call(dev, desc, res, false);
|
||||
|
@ -201,7 +212,7 @@ static int qcom_scm_call(struct device *dev, const struct qcom_scm_desc *desc,
|
|||
*/
|
||||
static int qcom_scm_call_atomic(struct device *dev,
|
||||
const struct qcom_scm_desc *desc,
|
||||
struct arm_smccc_res *res)
|
||||
struct qcom_scm_res *res)
|
||||
{
|
||||
return __scm_smc_call(dev, desc, res, true);
|
||||
}
|
||||
|
@ -254,7 +265,7 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
|
|||
.cmd = QCOM_SCM_INFO_IS_CALL_AVAIL,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
desc.arginfo = QCOM_SCM_ARGS(1);
|
||||
desc.args[0] = SCM_SMC_FNID(svc_id, cmd_id) |
|
||||
|
@ -262,7 +273,7 @@ int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
|
||||
|
@ -274,7 +285,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
|
|||
.cmd = QCOM_SCM_HDCP_INVOKE,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
|
||||
return -ERANGE;
|
||||
|
@ -292,7 +303,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
|
|||
desc.arginfo = QCOM_SCM_ARGS(10);
|
||||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
*resp = res.a1;
|
||||
*resp = res.result[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -336,14 +347,14 @@ bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral)
|
|||
.cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
desc.args[0] = peripheral;
|
||||
desc.arginfo = QCOM_SCM_ARGS(1);
|
||||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? false : !!res.a1;
|
||||
return ret ? false : !!res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
|
||||
|
@ -355,7 +366,7 @@ int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
|
|||
.cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
desc.args[0] = peripheral;
|
||||
desc.args[1] = metadata_phys;
|
||||
|
@ -363,7 +374,7 @@ int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
|
||||
|
@ -375,7 +386,7 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
|
|||
.cmd = QCOM_SCM_PIL_PAS_MEM_SETUP,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
desc.args[0] = peripheral;
|
||||
desc.args[1] = addr;
|
||||
|
@ -384,7 +395,7 @@ int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral)
|
||||
|
@ -395,14 +406,14 @@ int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral)
|
|||
.cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
desc.args[0] = peripheral;
|
||||
desc.arginfo = QCOM_SCM_ARGS(1);
|
||||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral)
|
||||
|
@ -413,14 +424,14 @@ int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral)
|
|||
.cmd = QCOM_SCM_PIL_PAS_SHUTDOWN,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
desc.args[0] = peripheral;
|
||||
desc.arginfo = QCOM_SCM_ARGS(1);
|
||||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
|
||||
|
@ -430,7 +441,7 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
|
|||
.cmd = QCOM_SCM_PIL_PAS_MSS_RESET,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = reset;
|
||||
|
@ -439,7 +450,7 @@ int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
|
||||
|
@ -449,7 +460,7 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
|
|||
.cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = state;
|
||||
|
@ -458,7 +469,7 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
|
||||
|
@ -471,7 +482,7 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
|
|||
.cmd = QCOM_SCM_MP_ASSIGN,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
|
||||
desc.args[0] = mem_region;
|
||||
desc.args[1] = mem_sz;
|
||||
|
@ -487,7 +498,7 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
|
||||
|
@ -497,7 +508,7 @@ int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
|
|||
.cmd = QCOM_SCM_MP_RESTORE_SEC_CFG,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = device_id;
|
||||
|
@ -506,7 +517,7 @@ int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
return ret ? : res.a1;
|
||||
return ret ? : res.result[0];
|
||||
}
|
||||
|
||||
int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
|
||||
|
@ -517,7 +528,7 @@ int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
|
|||
.cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = spare;
|
||||
|
@ -526,9 +537,9 @@ int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
|
|||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
|
||||
if (size)
|
||||
*size = res.a1;
|
||||
*size = res.result[0];
|
||||
|
||||
return ret ? : res.a2;
|
||||
return ret ? : res.result[1];
|
||||
}
|
||||
|
||||
int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
|
||||
|
@ -539,7 +550,6 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
|
|||
.cmd = QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = addr;
|
||||
|
@ -548,7 +558,7 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
|
|||
desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
|
||||
QCOM_SCM_VAL);
|
||||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
ret = qcom_scm_call(dev, &desc, NULL);
|
||||
|
||||
/* the pg table has been initialized already, ignore the error */
|
||||
if (ret == -EPERM)
|
||||
|
@ -564,13 +574,12 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
|
|||
.cmd = QCOM_SCM_BOOT_SET_DLOAD_MODE,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
|
||||
desc.args[0] = QCOM_SCM_BOOT_SET_DLOAD_MODE;
|
||||
desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0;
|
||||
desc.arginfo = QCOM_SCM_ARGS(2);
|
||||
|
||||
return qcom_scm_call(dev, &desc, &res);
|
||||
return qcom_scm_call(dev, &desc, NULL);
|
||||
}
|
||||
|
||||
int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
|
||||
|
@ -581,7 +590,7 @@ int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
|
|||
.cmd = QCOM_SCM_IO_READ,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
struct qcom_scm_res res;
|
||||
int ret;
|
||||
|
||||
desc.args[0] = addr;
|
||||
|
@ -589,7 +598,7 @@ int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
|
|||
|
||||
ret = qcom_scm_call(dev, &desc, &res);
|
||||
if (ret >= 0)
|
||||
*val = res.a1;
|
||||
*val = res.result[0];
|
||||
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
@ -601,13 +610,12 @@ int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val)
|
|||
.cmd = QCOM_SCM_IO_WRITE,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
|
||||
desc.args[0] = addr;
|
||||
desc.args[1] = val;
|
||||
desc.arginfo = QCOM_SCM_ARGS(2);
|
||||
|
||||
return qcom_scm_call(dev, &desc, &res);
|
||||
return qcom_scm_call(dev, &desc, NULL);
|
||||
}
|
||||
|
||||
int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en)
|
||||
|
@ -617,11 +625,10 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en)
|
|||
.cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1,
|
||||
.owner = ARM_SMCCC_OWNER_SIP,
|
||||
};
|
||||
struct arm_smccc_res res;
|
||||
|
||||
desc.args[0] = QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL;
|
||||
desc.args[1] = en;
|
||||
desc.arginfo = QCOM_SCM_ARGS(2);
|
||||
|
||||
return qcom_scm_call_atomic(dev, &desc, &res);
|
||||
return qcom_scm_call_atomic(dev, &desc, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue