diff options
| -rw-r--r-- | drivers/phy/phy-qcom-ufs-i.h | 18 | ||||
| -rw-r--r-- | drivers/phy/phy-qcom-ufs-qmp-14nm.c | 16 | ||||
| -rw-r--r-- | drivers/phy/phy-qcom-ufs-qmp-14nm.h | 1 |
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), |
