scsi: ufs-msm-phy-qmp-20nm: fix hibern8 exit failure

If UFS link is put into Hibern8 and if UFS PHY analog hardware is power
collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL), Hibern8 exit might fail
even after powering on UFS PHY analog hardware. This change provides
workaround to solve above issue by doing custom PHY settings just before
PHY analog power collapse.

Change-Id: I63d43329798c5475e07511248ac35450b8fe208d
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
Subhash Jadavani 2014-07-18 11:39:16 -07:00
parent 6459505bac
commit 3d4dab853d
2 changed files with 37 additions and 22 deletions

View file

@ -82,36 +82,41 @@ void ufs_msm_phy_qmp_20nm_power_control(struct ufs_msm_phy *phy, bool val)
writel_relaxed(0x1, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
/*
* Before any transactions involving PHY, ensure PHY knows
* that it's analog rail is powered ON. This also ensures
* that PHY is out of power collapse before enabling the
* SIGDET.
* that it's analog rail is powered ON.
*/
mb();
if (phy->quirks &
MSM_UFS_PHY_DIS_SIGDET_BEFORE_PWR_COLLAPSE) {
writel_relaxed(0xC0,
phy->mmio + QSERDES_RX_SIGDET_CNTRL(0));
writel_relaxed(0xC0,
phy->mmio + QSERDES_RX_SIGDET_CNTRL(1));
MSM_UFS_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE) {
/*
* make sure that SIGDET is enabled before proceeding
* further.
* Give atleast 1us delay after restoring PHY analog
* power.
*/
mb();
}
} else {
if (phy->quirks &
MSM_UFS_PHY_DIS_SIGDET_BEFORE_PWR_COLLAPSE) {
writel_relaxed(0x0,
phy->mmio + QSERDES_RX_SIGDET_CNTRL(0));
writel_relaxed(0x0,
phy->mmio + QSERDES_RX_SIGDET_CNTRL(1));
usleep_range(1, 2);
writel_relaxed(0x0A, phy->mmio +
QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
writel_relaxed(0x08, phy->mmio +
QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
/*
* Ensure that SIGDET is disabled before PHY power
* collapse
* Make sure workaround is deactivated before proceeding
* with normal PHY operations.
*/
mb();
}
} else {
if (phy->quirks &
MSM_UFS_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE) {
writel_relaxed(0x0A, phy->mmio +
QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
writel_relaxed(0x02, phy->mmio +
QSERDES_COM_SYSCLK_EN_SEL_TXBAND);
/*
* Make sure that above workaround is activated before
* PHY analog power collapse.
*/
mb();
}
writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
/*
* ensure that PHY knows its PHY analog rail is going
@ -158,7 +163,8 @@ static void ufs_msm_phy_qmp_20nm_advertise_quirks(struct phy *generic_phy)
struct ufs_msm_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy);
struct ufs_msm_phy *phy_common = &(phy->common_cfg);
phy_common->quirks = 0;
phy_common->quirks =
MSM_UFS_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE;
}
struct phy_ops ufs_msm_phy_qmp_20nm_phy_ops = {

View file

@ -108,6 +108,15 @@ struct ufs_msm_phy {
*/
#define MSM_UFS_PHY_DIS_SIGDET_BEFORE_PWR_COLLAPSE (1 << 1)
/*
* If UFS link is put into Hibern8 and if UFS PHY analog hardware is
* power collapsed (by clearing UFS_PHY_POWER_DOWN_CONTROL), Hibern8
* exit might fail even after powering on UFS PHY analog hardware.
* Enabling this quirk will help to solve above issue by doing
* custom PHY settings just before PHY analog power collapse.
*/
#define MSM_UFS_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE (1 << 2)
char name[UFS_MSM_PHY_NAME_LEN];
struct ufs_msm_phy_calibration *cached_regs;
int cached_regs_table_size;