From d5a4a6c23f18ff35783cbf17ee0bfbd395d3feef Mon Sep 17 00:00:00 2001 From: Andy Gross Date: Fri, 3 Jul 2015 15:44:05 -0500 Subject: [PATCH] firmware: qcom: scm: Add 64 bit PAS APIs Signed-off-by: Andy Gross --- drivers/firmware/qcom_scm-64.c | 104 +++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c index 7f985ca78eaa..751e2ef8ba41 100644 --- a/drivers/firmware/qcom_scm-64.c +++ b/drivers/firmware/qcom_scm-64.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,13 @@ #define MAX_QCOM_SCM_ARGS 10 #define MAX_QCOM_SCM_RETS 3 +enum qcom_scm_arg_types { + QCOM_SCM_VAL, + QCOM_SCM_RO, + QCOM_SCM_RW, + QCOM_SCM_BUFVAL, +}; + #define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ (((a) & 0xff) << 4) | \ (((b) & 0xff) << 6) | \ @@ -438,6 +446,102 @@ int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) return ret; } +bool __qcom_scm_pas_supported(u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = {0}; + + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_IS_SUPPORTED_CMD, + &desc); + + return ret ? false : !!desc.ret[0]; +} + +int __qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) +{ + int ret; + struct qcom_scm_desc desc = {0}; + u32 scm_ret; + dma_addr_t mdata_phys; + void *mdata_buf; + + /* + * During the scm call memory protection will be enabled for the meta + * data blob, so make sure it's physically contiguous, 4K aligned and + * non-cachable to avoid XPU violations. + */ + mdata_buf = dma_alloc_coherent(NULL, size, &mdata_phys, GFP_KERNEL); + if (!mdata_buf) { + pr_err("Allocation of metadata buffer failed.\n"); + return -ENOMEM; + } + memcpy(mdata_buf, metadata, size); + + desc.args[0] = peripheral; + desc.args[1] = mdata_phys; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW); + + ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD, + &desc); + scm_ret = desc.ret[0]; + + dma_free_coherent(NULL, size, mdata_buf, mdata_phys); + return ret ? : scm_ret; +} + +int __qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size) +{ + int ret; + struct qcom_scm_desc desc = {0}; + u32 scm_ret; + + desc.args[0] = peripheral; + desc.args[1] = addr; + desc.args[2] = size; + desc.arginfo = QCOM_SCM_ARGS(3); + + ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD, + &desc); + scm_ret = desc.ret[0]; + + return ret ? : scm_ret; +} + +int __qcom_scm_pas_auth_and_reset(u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = {0}; + u32 scm_ret; + + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_AUTH_AND_RESET_CMD, + &desc); + scm_ret = desc.ret[0]; + + return ret ? : scm_ret; +} + +int __qcom_scm_pas_shutdown(u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = {0}; + u32 scm_ret; + + desc.args[0] = peripheral; + desc.arginfo = QCOM_SCM_ARGS(1); + + ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD, + &desc); + scm_ret = desc.ret[0]; + + return ret ? : scm_ret; +} + #define QCOM_SCM_SVC_INFO 0x6 static int __init qcom_scm_init(void) { -- 2.39.5