[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250702151441.8061-3-quic_nitirawa@quicinc.com>
Date: Wed, 2 Jul 2025 20:44:41 +0530
From: Nitin Rawat <quic_nitirawa@...cinc.com>
To: mani@...nel.org, James.Bottomley@...senPartnership.com,
martin.petersen@...cle.com, bvanassche@....org,
neil.armstrong@...aro.org, konrad.dybcio@....qualcomm.com
Cc: linux-arm-msm@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-scsi@...r.kernel.org, Nitin Rawat <quic_nitirawa@...cinc.com>
Subject: [PATCH V1 2/2] scsi: ufs: qcom: Enable QUnipro Internal Clock Gating
Enable internal clock gating for QUnipro by setting the following
attributes to 1 during host controller initialization:
- DL_VS_CLK_CFG
- PA_VS_CLK_CFG_REG
- DME_VS_CORE_CLK_CTRL.DME_HW_CGC_EN
This change is necessary to support the internal clock gating mechanism
in Qualcomm UFS host controller.
Signed-off-by: Nitin Rawat <quic_nitirawa@...cinc.com>
---
drivers/ufs/host/ufs-qcom.c | 21 +++++++++++++++++++++
drivers/ufs/host/ufs-qcom.h | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index dfdc52333a96..25b5f83b049c 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -558,11 +558,32 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
*/
static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba)
{
+ int err = 0;
+
+ /* Enable UTP internal clock gating */
ufshcd_rmwl(hba, REG_UFS_CFG2_CGC_EN_ALL, REG_UFS_CFG2_CGC_EN_ALL,
REG_UFS_CFG2);
/* Ensure that HW clock gating is enabled before next operations */
ufshcd_readl(hba, REG_UFS_CFG2);
+
+ /* Enable Unipro internal clock gating */
+ err = ufshcd_dme_rmw(hba, DL_VS_CLK_CFG_MASK,
+ DL_VS_CLK_CFG_MASK, DL_VS_CLK_CFG);
+ if (err)
+ goto out;
+
+ err = ufshcd_dme_rmw(hba, PA_VS_CLK_CFG_REG_MASK,
+ PA_VS_CLK_CFG_REG_MASK, PA_VS_CLK_CFG_REG);
+ if (err)
+ goto out;
+
+ err = ufshcd_dme_rmw(hba, DME_VS_CORE_CLK_CTRL_DME_HW_CGC_EN,
+ DME_VS_CORE_CLK_CTRL_DME_HW_CGC_EN,
+ DME_VS_CORE_CLK_CTRL);
+out:
+ if (err)
+ dev_err(hba->dev, "hw clk gating enabled failed\n");
}
static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index 0a5cfc2dd4f7..d8ad3cb3bd1c 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -24,6 +24,15 @@
#define UFS_QCOM_LIMIT_HS_RATE PA_HS_MODE_B
+/* bit and mask definitions for PA_VS_CLK_CFG_REG attribute */
+#define PA_VS_CLK_CFG_REG 0x9004
+#define PA_VS_CLK_CFG_REG_MASK GENMASK(8, 0)
+
+/* bit and mask definitions for DL_VS_CLK_CFG attribute */
+#define DL_VS_CLK_CFG 0xA00B
+#define DL_VS_CLK_CFG_MASK GENMASK(9, 0)
+#define DME_VS_CORE_CLK_CTRL_DME_HW_CGC_EN BIT(9)
+
/* QCOM UFS host controller vendor specific registers */
enum {
REG_UFS_SYS1CLK_1US = 0xC0,
@@ -234,6 +243,32 @@ static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba)
ufshcd_readl(hba, REG_UFS_CFG1);
}
+/**
+ * ufshcd_dme_rmw - get modify set a dme attribute
+ * @hba - per adapter instance
+ * @mask - mask to apply on read value
+ * @val - actual value to write
+ * @attr - dme attribute
+ */
+static inline int ufshcd_dme_rmw(struct ufs_hba *hba, u32 mask,
+ u32 val, u32 attr)
+{
+ u32 cfg = 0;
+ int err = 0;
+
+ err = ufshcd_dme_get(hba, UIC_ARG_MIB(attr), &cfg);
+ if (err)
+ goto out;
+
+ cfg &= ~mask;
+ cfg |= (val & mask);
+
+ err = ufshcd_dme_set(hba, UIC_ARG_MIB(attr), cfg);
+
+out:
+ return err;
+}
+
/* Host controller hardware version: major.minor.step */
struct ufs_hw_version {
u16 step;
--
2.48.1
Powered by blists - more mailing lists