phy: qcom-ufs-qmp-14nm: add PHY initialization workaround

UFS PHY auto calibration is not working currently hence add workaround
to have manual calibrated configuration as part of power up sequence
itself. We had another workaround for hibern8 enter/exit to work and it
had required us to save the auto calibrated VCO codes after PHY power up
sequence and then set the PHY PLL in VCO bypass mode. As the auto
calibration is not working and we are already having manually calibrated
VCO codes as part of PHY power up sequence itself, this change removes the
old workaround.

Change-Id: I570ea4f7f8c2f79a06321fb43c8cb01575bf0df0
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
Subhash Jadavani 2015-02-03 10:14:15 -08:00 committed by David Keitel
parent 10ad03a4d8
commit dcaa491021
2 changed files with 10 additions and 66 deletions

View file

@ -183,64 +183,6 @@ static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy *phy)
/* Ensure register value is committed */
mb();
}
/*
* This additional sequence is required as a workaround for following bug:
* Due to missing reset in the UFS PHY logic, the pll may not lock following
* analog power collapse. As a result the common block of the PHY must be put
* into reset during hibernate entry and taken out of reset during hibernate
* exit. The following sequence is required to save the calibrated VCO codes.
* Saving the codes will save substantial time on hibernate exit
* (<50us vs. 1.7ms).
*/
static void
ufs_qcom_phy_qmp_14nm_save_calibrated_vco_code(struct ufs_qcom_phy *phy)
{
u32 vco_tune_mode0, vco_tune_mode1;
u32 temp;
/* set common debug bus select */
writel_relaxed(0x02, phy->mmio + QSERDES_COM_DEBUG_BUS_SEL);
/* apply debug bus select before reading the debug bus registers */
mb();
/* vco_tune_mode0[7:0]: Read VCO tuning code for Series A */
vco_tune_mode0 = readl_relaxed(phy->mmio + QSERDES_COM_DEBUG_BUS0)
& 0xFF;
temp = readl_relaxed(phy->mmio + QSERDES_COM_DEBUG_BUS1);
/* vco_tune_mode0[9:8]: Read VCO tuning code for Series A */
vco_tune_mode0 |= (temp & 0x300);
/* vco_tune_mode1[5:0]: Read VCO tuning code for Series B */
vco_tune_mode1 = temp & 0x3F;
temp = readl_relaxed(phy->mmio + QSERDES_COM_DEBUG_BUS2);
/* vco_tune_mode1[9:6]: Read VCO tuning code for Series B */
vco_tune_mode1 |= (temp & 0x3C0);
/* vco_tune_mode0[7:0] */
writel_relaxed((vco_tune_mode0 & 0xff),
phy->mmio + QSERDES_COM_VCO_TUNE1_MODE0);
/* vco_tune_mode0[9:8] */
writel_relaxed((vco_tune_mode0 & 0x300) >> 8,
phy->mmio + QSERDES_COM_VCO_TUNE2_MODE0);
/* vco_tune_mode1[7:0] */
writel_relaxed((vco_tune_mode1 & 0xff),
phy->mmio + QSERDES_COM_VCO_TUNE1_MODE1);
/* vco_tune_mode1[9:8] */
writel_relaxed((vco_tune_mode1 & 0x300) >> 8,
phy->mmio + QSERDES_COM_VCO_TUNE2_MODE1);
/* apply vco tuning codes before enabling the vco bypass mode */
mb();
temp = readl_relaxed(phy->mmio + QSERDES_COM_VCO_TUNE_CTRL);
/*
* Bypass the calibrated code and use the stored code for
* both A and B series
*/
writel_relaxed((temp | 0xC), phy->mmio + QSERDES_COM_VCO_TUNE_CTRL);
/* apply this configuration before return */
mb();
}
static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
{
@ -266,10 +208,6 @@ static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common)
mb();
}
if (phy_common->quirks &
UFS_QCOM_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE)
ufs_qcom_phy_qmp_14nm_save_calibrated_vco_code(phy_common);
out:
return err;
}

View file

@ -27,12 +27,14 @@
#define QSERDES_COM_BG_TIMER COM_OFF(0x0C)
#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN COM_OFF(0x34)
#define QSERDES_COM_SYS_CLK_CTRL COM_OFF(0x3C)
#define QSERDES_COM_PLL_IVCO COM_OFF(0x48)
#define QSERDES_COM_LOCK_CMP1_MODE0 COM_OFF(0x4C)
#define QSERDES_COM_LOCK_CMP2_MODE0 COM_OFF(0x50)
#define QSERDES_COM_LOCK_CMP3_MODE0 COM_OFF(0x54)
#define QSERDES_COM_LOCK_CMP1_MODE1 COM_OFF(0x58)
#define QSERDES_COM_LOCK_CMP2_MODE1 COM_OFF(0x5C)
#define QSERDES_COM_LOCK_CMP3_MODE1 COM_OFF(0x60)
#define QSERDES_COM_BG_TRIM COM_OFF(0x70)
#define QSERDES_COM_CP_CTRL_MODE0 COM_OFF(0x78)
#define QSERDES_COM_CP_CTRL_MODE1 COM_OFF(0x7C)
#define QSERDES_COM_PLL_RCTRL_MODE0 COM_OFF(0x84)
@ -41,6 +43,7 @@
#define QSERDES_COM_PLL_CCTRL_MODE1 COM_OFF(0x94)
#define QSERDES_COM_SYSCLK_EN_SEL COM_OFF(0xAC)
#define QSERDES_COM_RESETSM_CNTRL COM_OFF(0xB4)
#define QSERDES_COM_RESCODE_DIV_NUM COM_OFF(0xC4)
#define QSERDES_COM_LOCK_CMP_EN COM_OFF(0xC8)
#define QSERDES_COM_LOCK_CMP_CFG COM_OFF(0xCC)
#define QSERDES_COM_DEC_START_MODE0 COM_OFF(0xD0)
@ -127,7 +130,7 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_2_0_0[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV, 0x0a),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_EN, 0x01),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x10),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x1C),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x20),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORE_CLK_EN, 0x00),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_CFG, 0x00),
@ -144,8 +147,8 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_2_0_0[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x3F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x01),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
@ -158,7 +161,7 @@ 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, 0xd6),
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),
@ -178,6 +181,9 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_2_0_0[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IVCO, 0x0F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TRIM, 0x0F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESCODE_DIV_NUM, 0x15),
/*
* UFS_PHY_RX_PWM_GEAR_BAND configuration is changed after the power up
* sequence so make sure that this register gets set to power on reset