[PATCH 1/4] qcom-scm: add ocmem support
Rob Clark
robdclark at gmail.com
Mon Sep 28 14:08:27 PDT 2015
On Mon, Sep 28, 2015 at 4:51 PM, Stephen Boyd <sboyd at codeaurora.org> wrote:
> On 09/28, Rob Clark wrote:
>> Add interfaces needed for configuring OCMEM.
>>
>> Signed-off-by: Rob Clark <robdclark at gmail.com>
>> ---
>> drivers/firmware/qcom_scm-32.c | 57 ++++++++++++++++++++++
>> drivers/firmware/qcom_scm-64.c | 16 +++++++
>> drivers/firmware/qcom_scm.c | 106 +++++++++++++++++++++++++++++++++++++++++
>> drivers/firmware/qcom_scm.h | 13 +++++
>> include/linux/qcom_scm.h | 10 ++++
>> 5 files changed, 202 insertions(+)
>>
>> diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
>> index e9c306b..656d8fe 100644
>> --- a/drivers/firmware/qcom_scm-32.c
>> +++ b/drivers/firmware/qcom_scm-32.c
>> @@ -500,6 +500,63 @@ int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
>> req, req_cnt * sizeof(*req), resp, sizeof(*resp));
>> }
>>
>> +int __qcom_scm_ocmem_secure_cfg(unsigned sec_id)
>> +{
>> + int ret, scm_ret = 0;
>> + struct msm_scm_sec_cfg {
>> + unsigned int id;
>> + unsigned int spare;
>
>
> __le32 for both
>
>> + } cfg;
>> +
>> + cfg.id = sec_id;
>> +
>> +
>
> nitpick: drop double space
>
>> + ret = qcom_scm_call(QCOM_SCM_OCMEM_SECURE_SVC, QCOM_SCM_OCMEM_SECURE_CFG,
>> + &cfg, sizeof(cfg), &scm_ret, sizeof(scm_ret));
>> +
>> + if (ret || scm_ret) {
>> + pr_err("ocmem: Failed to enable secure programming\n");
>
> Maybe the caller should print something if they care instead of
> burying it down here.
>
>> + return ret ? ret : -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +int __qcom_scm_ocmem_lock(uint32_t id, uint32_t offset, uint32_t size,
>> + uint32_t mode)
>
> Please use u32 here instead of uint32_t. uint32_t is not for
> kernel code.
>
>> +{
>> + struct ocmem_tz_lock {
>> + u32 id;
>> + u32 offset;
>> + u32 size;
>> + u32 mode;
>
> All __le32
>
>> + } request;
>> +
>> + request.id = id;
>> + request.offset = offset;
>> + request.size = size;
>> + request.mode = mode;
>
> And then do the cpu_to_le32() stuff here.
>
>> +
>> + return qcom_scm_call(QCOM_SCM_OCMEM_SVC, QCOM_SCM_OCMEM_LOCK_CMD,
>> + &request, sizeof(request), NULL, 0);
>> +}
>> +
>> +int __qcom_scm_ocmem_unlock(uint32_t id, uint32_t offset, uint32_t size)
>
> u32
>
>> +{
>> + struct ocmem_tz_unlock {
>> + u32 id;
>> + u32 offset;
>> + u32 size;
>
> __le32
>
>> + } request;
>> +
>> + request.id = id;
>> + request.offset = offset;
>> + request.size = size;
>> +
>> + return qcom_scm_call(QCOM_SCM_OCMEM_SVC, QCOM_SCM_OCMEM_UNLOCK_CMD,
>> + &request, sizeof(request), NULL, 0);
>> +}
>> +
>> bool __qcom_scm_pas_supported(u32 peripheral)
>> {
>> __le32 out;
>> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
>> index 118df0a..59b1007 100644
>> --- a/drivers/firmware/qcom_scm.c
>> +++ b/drivers/firmware/qcom_scm.c
>> @@ -154,6 +154,112 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
>> EXPORT_SYMBOL(qcom_scm_hdcp_req);
>>
>> /**
>> + * qcom_scm_ocmem_secure_available() - Check if secure environment supports
>> + * OCMEM.
>> + *
>> + * Return true if OCMEM secure interface is supported, false if not.
>> + */
>> +bool qcom_scm_ocmem_secure_available(void)
>> +{
>> + int ret = qcom_scm_clk_enable();
>
> I doubt we need to enable clocks to figure out if a call is
> available. Please drop clk stuff here.
hmm, hdcp did, but pas didn't.. otoh it looks like the call to
__qcom_scm_pas_supported() *should* be wrapped in clk enable/disable..
And __qcom_scm_is_call_available() does call qcom_scm_call(). Which
is, I assume, what needs the clk's.. so not entirely sure if *all*
the clk enable/disable stuff should be stripped out, or if missing clk
stuff should be added in qcom_scm_pas_supported()..
>> +
>> + if (ret)
>> + goto clk_err;
>> +
>> + ret = __qcom_scm_is_call_available(QCOM_SCM_OCMEM_SECURE_SVC,
>> + QCOM_SCM_OCMEM_SECURE_CFG);
>> +
>> + qcom_scm_clk_disable();
>> +
>> +clk_err:
>> + return (ret > 0) ? true : false;
>> +}
>> +EXPORT_SYMBOL(qcom_scm_ocmem_secure_available);
>> +
>> +/**
>> + * qcom_scm_ocmem_secure_cfg() - call OCMEM secure cfg interface
>> + */
>> +int qcom_scm_ocmem_secure_cfg(unsigned sec_id)
>> +{
>> + int ret = qcom_scm_clk_enable();
>> +
>> + if (ret)
>> + return ret;
>> +
>> + ret = __qcom_scm_ocmem_secure_cfg(sec_id);
>> + qcom_scm_clk_disable();
>> +
>> + return ret;
>> +}
>> +EXPORT_SYMBOL(qcom_scm_ocmem_secure_cfg);
>> +
>> +/**
>> + * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available
>> + */
>> +bool qcom_scm_ocmem_lock_available(void)
>> +{
>> + int ret = qcom_scm_clk_enable();
>
> No need for clocks?
>
>> +
>> + if (ret)
>> + goto clk_err;
>> +
>> + ret = __qcom_scm_is_call_available(QCOM_SCM_OCMEM_SVC,
>> + QCOM_SCM_OCMEM_LOCK_CMD);
>> +
>> + qcom_scm_clk_disable();
>> +
>> +clk_err:
>> + return (ret > 0) ? true : false;
>> +}
>> +EXPORT_SYMBOL(qcom_scm_ocmem_lock_available);
>> +
>> +/**
>> + * qcom_scm_ocmem_lock() - call OCMEM lock interface to assign an OCMEM
>> + * region to the specified initiator
>> + *
>> + * @id: tz initiator id
>> + * @offset: OCMEM offset
>> + * @size: OCMEM size
>> + * @mode: access mode (WIDE/NARROW)
>> + */
>> +int qcom_scm_ocmem_lock(uint32_t id, uint32_t offset, uint32_t size,
>> + uint32_t mode)
>> +{
>> + int ret = qcom_scm_clk_enable();
>> +
>> + if (ret)
>> + return ret;
>> +
>> + ret = __qcom_scm_ocmem_lock(id, offset, size, mode);
>> + qcom_scm_clk_disable();
>> +
>> + return ret;
>> +}
>> +EXPORT_SYMBOL(qcom_scm_ocmem_lock);
>> +
>> +/**
>> + * qcom_scm_ocmem_unlock() - call OCMEM unlock interface to release an OCMEM
>> + * region from the specified initiator
>> + *
>> + * @id: tz initiator id
>> + * @offset: OCMEM offset
>> + * @size: OCMEM size
>> + */
>> +int qcom_scm_ocmem_unlock(uint32_t id, uint32_t offset, uint32_t size)
>> +{
>> + int ret = qcom_scm_clk_enable();
>> +
>> + if (ret)
>> + return ret;
>> +
>> + ret = __qcom_scm_ocmem_unlock(id, offset, size);
>> + qcom_scm_clk_disable();
>> +
>> + return ret;
>> +}
>> +EXPORT_SYMBOL(qcom_scm_ocmem_unlock);
>
> I don't think we need any clocks for lock/unlock/cfg either. The
> scm clocks are some crypto clocks that the secure side isn't able
> to enable and we don't have a device in DT for them. In the ocmem
> case, we should rely on the ocmem device to get the clocks and
> turn them on before calling any scm APIs that may require those
> clocks.
Hmm, if that is true then we should probably drop the clks for hdcp
fxns too, and maybe add a comment somewhere since it isn't really
clear what the clks are for (and when it is unclear, folks will just
cargo-cult what the existing fxns are doing). As-is it is hard to
tell what is required and what is luck..
>> diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
>> index 46d41e4..a934457 100644
>> --- a/include/linux/qcom_scm.h
>> +++ b/include/linux/qcom_scm.h
>> @@ -23,10 +23,20 @@ struct qcom_scm_hdcp_req {
>> u32 val;
>> };
>>
>> +extern bool qcom_scm_is_available(void);
>
> Is this used? Looks like noise.
perhaps should be split out into a separate patch.. but I am using
this, and it seems like a good idea to avoid null ptr deref's of
__scm. Probably some of the scm callers should call this first..
either that or we should make other scm entry points behave better if
__scm is null..
BR,
-R
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
More information about the dri-devel
mailing list