2022-09-15 14:56:51

by Hiren Gohel

[permalink] [raw]
Subject: [PATCH] usb: phy: qusb: Use scm call to update value in register

Registers used by vendors to control any functionality could be
implemented by making the register secured. In such cases the
register cannot be updated with a new value since the normal
write ops will fail.

Hence, use the scm_call to do a secure write to the register.

Signed-off-by: Hiren Gohel <[email protected]>
---
drivers/firmware/qcom_scm.c | 19 +++++++++++++++++++
drivers/firmware/qcom_scm.h | 1 +
include/linux/qcom_scm.h | 2 ++
3 files changed, 22 insertions(+)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index cdbfe54..7131df8 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -400,6 +400,25 @@ int qcom_scm_set_remote_state(u32 state, u32 id)
}
EXPORT_SYMBOL(qcom_scm_set_remote_state);

+void qcom_scm_phy_update_scm_level_shifter(u32 val)
+{
+ int ret;
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_BOOT,
+ .cmd = QCOM_SCM_QUSB2PHY_LVL_SHIFTER_CMD_ID,
+ .owner = ARM_SMCCC_OWNER_SIP
+ };
+
+ desc.args[0] = val;
+ desc.args[1] = 0;
+ desc.arginfo = QCOM_SCM_ARGS(2);
+
+ ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ if (ret)
+ pr_err("Failed to update scm level shifter=0x%x\n", ret);
+}
+EXPORT_SYMBOL(qcom_scm_phy_update_scm_level_shifter);
+
static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
{
struct qcom_scm_desc desc = {
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 0d51eef..0a8c25b 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -81,6 +81,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#define QCOM_SCM_BOOT_SET_ADDR_MC 0x11
#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
#define QCOM_SCM_FLUSH_FLAG_MASK 0x3
+#define QCOM_SCM_QUSB2PHY_LVL_SHIFTER_CMD_ID 0x1B
#define QCOM_SCM_BOOT_MAX_CPUS 4
#define QCOM_SCM_BOOT_MC_FLAG_AARCH64 BIT(0)
#define QCOM_SCM_BOOT_MC_FLAG_COLDBOOT BIT(1)
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index f8335644..3e5cbe9 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -124,4 +124,6 @@ extern int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
extern int qcom_scm_lmh_profile_change(u32 profile_id);
extern bool qcom_scm_lmh_dcvsh_available(void);

+extern void qcom_scm_phy_update_scm_level_shifter(u32 val);
+
#endif
--
2.7.4


2022-09-15 17:50:54

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH] usb: phy: qusb: Use scm call to update value in register

On Thu, Sep 15, 2022 at 07:17:07PM +0530, Hiren Gohel wrote:
> Registers used by vendors to control any functionality could be
> implemented by making the register secured. In such cases the
> register cannot be updated with a new value since the normal
> write ops will fail.
>
> Hence, use the scm_call to do a secure write to the register.
>

This looks reasonable, but we need a caller of this API in order to
merge this patch.

> Signed-off-by: Hiren Gohel <[email protected]>
> ---
> drivers/firmware/qcom_scm.c | 19 +++++++++++++++++++
> drivers/firmware/qcom_scm.h | 1 +
> include/linux/qcom_scm.h | 2 ++
> 3 files changed, 22 insertions(+)
>
> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> index cdbfe54..7131df8 100644
> --- a/drivers/firmware/qcom_scm.c
> +++ b/drivers/firmware/qcom_scm.c
> @@ -400,6 +400,25 @@ int qcom_scm_set_remote_state(u32 state, u32 id)
> }
> EXPORT_SYMBOL(qcom_scm_set_remote_state);
>
> +void qcom_scm_phy_update_scm_level_shifter(u32 val)

That second "scm" doesn't seem necessary.

> +{
> + int ret;
> + struct qcom_scm_desc desc = {
> + .svc = QCOM_SCM_SVC_BOOT,
> + .cmd = QCOM_SCM_QUSB2PHY_LVL_SHIFTER_CMD_ID,
> + .owner = ARM_SMCCC_OWNER_SIP
> + };
> +
> + desc.args[0] = val;
> + desc.args[1] = 0;
> + desc.arginfo = QCOM_SCM_ARGS(2);
> +
> + ret = qcom_scm_call(__scm->dev, &desc, NULL);

Would it not make sense to return this error to the caller?

Regards,
Bjorn

> + if (ret)
> + pr_err("Failed to update scm level shifter=0x%x\n", ret);
> +}
> +EXPORT_SYMBOL(qcom_scm_phy_update_scm_level_shifter);
> +
> static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
> {
> struct qcom_scm_desc desc = {
> diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
> index 0d51eef..0a8c25b 100644
> --- a/drivers/firmware/qcom_scm.h
> +++ b/drivers/firmware/qcom_scm.h
> @@ -81,6 +81,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
> #define QCOM_SCM_BOOT_SET_ADDR_MC 0x11
> #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
> #define QCOM_SCM_FLUSH_FLAG_MASK 0x3
> +#define QCOM_SCM_QUSB2PHY_LVL_SHIFTER_CMD_ID 0x1B
> #define QCOM_SCM_BOOT_MAX_CPUS 4
> #define QCOM_SCM_BOOT_MC_FLAG_AARCH64 BIT(0)
> #define QCOM_SCM_BOOT_MC_FLAG_COLDBOOT BIT(1)
> diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
> index f8335644..3e5cbe9 100644
> --- a/include/linux/qcom_scm.h
> +++ b/include/linux/qcom_scm.h
> @@ -124,4 +124,6 @@ extern int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
> extern int qcom_scm_lmh_profile_change(u32 profile_id);
> extern bool qcom_scm_lmh_dcvsh_available(void);
>
> +extern void qcom_scm_phy_update_scm_level_shifter(u32 val);
> +
> #endif
> --
> 2.7.4
>