IPQ5332 user pd remoteproc firmwares need to be locked with MSA(modem secure access) features. This patch add support to lock/unlock MSA features. Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@xxxxxxxxxxx> --- Changes in v5: - Moved to EXPORT_SYMBOL_GPL() because scm driver moved to using EXPORT_SYMBOL_GPL() now. Changes in v4: - Rebased on linux-next drivers/firmware/qcom_scm.c | 78 ++++++++++++++++++++++++++ drivers/firmware/qcom_scm.h | 2 + include/linux/firmware/qcom/qcom_scm.h | 2 + 3 files changed, 82 insertions(+) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 5e1ff137ab52..ae5c6e495e19 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -676,6 +676,84 @@ bool qcom_scm_pas_supported(u32 peripheral) } EXPORT_SYMBOL_GPL(qcom_scm_pas_supported); +/** + * qcom_scm_msa_lock() - Lock given peripheral firmware region as MSA + * + * @peripheral: peripheral id + * + * Return 0 on success. + */ +int qcom_scm_msa_lock(u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_MSA_LOCK, + .arginfo = QCOM_SCM_ARGS(1), + .args[0] = peripheral, + .owner = ARM_SMCCC_OWNER_SIP, + }; + struct qcom_scm_res res; + + if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, + QCOM_SCM_MSA_LOCK)) + return 0; + + ret = qcom_scm_clk_enable(); + if (ret) + return ret; + + ret = qcom_scm_bw_enable(); + if (ret) + return ret; + + ret = qcom_scm_call(__scm->dev, &desc, &res); + qcom_scm_bw_disable(); + qcom_scm_clk_disable(); + + return ret ? : res.result[0]; +} +EXPORT_SYMBOL_GPL(qcom_scm_msa_lock); + +/** + * qcom_scm_msa_unlock() - Unlock given peripheral MSA firmware region + * + * @peripheral: peripheral id + * + * Return 0 on success. + */ +int qcom_scm_msa_unlock(u32 peripheral) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_PIL, + .cmd = QCOM_SCM_MSA_UNLOCK, + .arginfo = QCOM_SCM_ARGS(1), + .args[0] = peripheral, + .owner = ARM_SMCCC_OWNER_SIP, + }; + struct qcom_scm_res res; + + if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, + QCOM_SCM_MSA_UNLOCK)) + return 0; + + ret = qcom_scm_clk_enable(); + if (ret) + return ret; + + ret = qcom_scm_bw_enable(); + if (ret) + return ret; + + ret = qcom_scm_call(__scm->dev, &desc, &res); + qcom_scm_bw_disable(); + qcom_scm_clk_disable(); + + return ret ? : res.result[0]; +} +EXPORT_SYMBOL_GPL(qcom_scm_msa_unlock); + static int __qcom_scm_pas_mss_reset(struct device *dev, bool reset) { struct qcom_scm_desc desc = { diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 6ab5e7c77e8d..9480b0b57c3d 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -97,6 +97,8 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, #define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06 #define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07 #define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a +#define QCOM_SCM_MSA_LOCK 0x24 +#define QCOM_SCM_MSA_UNLOCK 0x25 #define QCOM_SCM_SVC_IO 0x05 #define QCOM_SCM_IO_READ 0x01 diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h index 0c091a3f6d49..58c476941e71 100644 --- a/include/linux/firmware/qcom/qcom_scm.h +++ b/include/linux/firmware/qcom/qcom_scm.h @@ -81,6 +81,8 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); extern bool qcom_scm_pas_supported(u32 peripheral); +extern int qcom_scm_msa_lock(u32 peripheral); +extern int qcom_scm_msa_unlock(u32 peripheral); extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); -- 2.34.1