summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/phy/phy-qcom-ufs-i.h18
-rw-r--r--drivers/phy/phy-qcom-ufs-qmp-14nm.c16
-rw-r--r--drivers/phy/phy-qcom-ufs-qmp-14nm.h1
3 files changed, 32 insertions, 3 deletions
diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
index f0ed60f3bc9e..9c56264889be 100644
--- a/drivers/phy/phy-qcom-ufs-i.h
+++ b/drivers/phy/phy-qcom-ufs-i.h
@@ -107,6 +107,23 @@ struct ufs_qcom_phy {
*/
#define UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE BIT(0)
+ /*
+ * On some UFS PHY HW revisions, UFS PHY power up calibration sequence
+ * cannot have SVS mode configuration otherwise calibration result
+ * cannot be used in HS-G3. So there are additional register writes must
+ * be done after the PHY is initialized but before the controller
+ * requests hibernate exit.
+ */
+ #define UFS_QCOM_PHY_QUIRK_SVS_MODE BIT(1)
+
+ /*
+ * On some UFS PHY HW revisions, UFS PHY power up calibration sequence
+ * requires manual VCO tuning code and its better to rely on the VCO
+ * tuning code programmed by boot loader. Enable this quirk to enable
+ * programming the manually tuned VCO code.
+ */
+ #define UFS_QCOM_PHY_QUIRK_VCO_MANUAL_TUNING BIT(2)
+
u8 host_ctrl_rev_major;
u16 host_ctrl_rev_minor;
u16 host_ctrl_rev_step;
@@ -116,6 +133,7 @@ struct ufs_qcom_phy {
int cached_regs_table_size;
bool is_powered_on;
struct ufs_qcom_phy_specific_ops *phy_spec_ops;
+ u32 vco_tune1_mode1;
};
/**
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
index 6495681a4291..132a1f1f6be7 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c
+++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
@@ -48,7 +48,11 @@ int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
err = ufs_qcom_phy_calibrate(ufs_qcom_phy,
tbl_A, tbl_size_A,
tbl_B, tbl_size_B,
- rate);
+ is_rate_B);
+
+ if (ufs_qcom_phy->quirks & UFS_QCOM_PHY_QUIRK_VCO_MANUAL_TUNING)
+ writel_relaxed(ufs_qcom_phy->vco_tune1_mode1,
+ ufs_qcom_phy->mmio + QSERDES_COM_VCO_TUNE1_MODE1);
out:
if (err)
dev_err(ufs_qcom_phy->dev,
@@ -67,7 +71,8 @@ void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
if ((major == 0x2) && (minor == 0x000) && (step == 0x0000))
phy_common->quirks =
UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE |
- UFS_QCOM_PHY_QUIRK_SVS_MODE;
+ UFS_QCOM_PHY_QUIRK_SVS_MODE |
+ UFS_QCOM_PHY_QUIRK_VCO_MANUAL_TUNING;
}
static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy)
@@ -94,6 +99,13 @@ static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy)
ufs_qcom_phy_qmp_14nm_advertise_quirks(phy_common);
+ if (phy_common->quirks & UFS_QCOM_PHY_QUIRK_VCO_MANUAL_TUNING) {
+ phy_common->vco_tune1_mode1 = readl_relaxed(phy_common->mmio +
+ QSERDES_COM_VCO_TUNE1_MODE1);
+ dev_info(phy_common->dev, "%s: vco_tune1_mode1 0x%x\n",
+ __func__, phy_common->vco_tune1_mode1);
+ }
+
out:
return err;
}
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.h b/drivers/phy/phy-qcom-ufs-qmp-14nm.h
index 41397bea5f0e..3eaa0ef3b8c6 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-14nm.h
+++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.h
@@ -162,7 +162,6 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_2_0_0[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0x7F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),