summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2014-04-30 17:37:18 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 10:56:58 -0700
commite318d1fa2cc94c3e5afc23e35bf768e0ba524204 (patch)
tree6ab3dc6e2ac38fa14401a23fcaadb0516a1de8fa
parent0531f43f34a5d73d94aca2371119f1754c10a7cd (diff)
scsi: ufs-msm: disable the sigdet before power collapsing PHY
If UFS PHY power down is deasserted and power is restored to analog circuits, the rx_sigdet can glitch. If the glitch is wide enough, it can trigger the PHY digital logic to think it saw a DIF-N and cause it to exit Hibern8. Disabling the rx_sigdet during power-up will mask the glitch. Change-Id: I20d93d2f5b479bb9e1d9626cfb9939d280b172a5 Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-rw-r--r--drivers/scsi/ufs/ufs-msm.c49
-rw-r--r--drivers/scsi/ufs/ufs-msm.h8
2 files changed, 47 insertions, 10 deletions
diff --git a/drivers/scsi/ufs/ufs-msm.c b/drivers/scsi/ufs/ufs-msm.c
index cb6c9497cbc6..20b2e288a704 100644
--- a/drivers/scsi/ufs/ufs-msm.c
+++ b/drivers/scsi/ufs/ufs-msm.c
@@ -1855,13 +1855,6 @@ static int msm_ufs_phy_power_on(struct msm_ufs_phy *phy)
if (err)
goto out;
- 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.
- */
- mb();
-
/* vdda_pll also enables ref clock LDOs so enable it first */
err = msm_ufs_phy_enable_vreg(phy, &phy->vdda_pll);
if (err)
@@ -1871,6 +1864,20 @@ static int msm_ufs_phy_power_on(struct msm_ufs_phy *phy)
if (err)
goto out_disable_pll;
+ 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.
+ */
+ 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));
+ /* make sure that SIGDET is enabled before proceeding further */
+ mb();
+ }
+
goto out;
out_disable_pll:
@@ -1883,7 +1890,17 @@ out:
static int msm_ufs_phy_power_off(struct msm_ufs_phy *phy)
{
+ 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));
+ /* Ensure that SIGDET is disabled before PHY power collapse */
+ mb();
+ }
writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
+ /*
+ * Ensure that PHY knows its PHY analog rail is going to be powered
+ * down.
+ */
mb();
msm_ufs_disable_phy_ref_clk(phy);
@@ -2231,10 +2248,21 @@ static int msm_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
msm_ufs_save_phy_configuration(hba);
msm_ufs_disable_phy_ref_clk(phy);
+ 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));
+ /*
+ * Ensure that SIGDET is disabled before PHY power
+ * collapse
+ */
+ mb();
+ }
writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL);
/*
- * Ensure PHY knows that PHY analog rail is going to be powered
- * down.
+ * Ensure that PHY knows its PHY analog rail is going to be
+ * powered down.
*/
mb();
msm_ufs_phy_disable_vreg(phy, &phy->vdda_phy);
@@ -2558,7 +2586,8 @@ static void msm_ufs_advertise_quirks(struct ufs_hba *hba)
| UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP
| UFSHCD_QUIRK_BROKEN_LCC);
- phy->quirks = MSM_UFS_PHY_QUIRK_CFG_RESTORE;
+ phy->quirks = (MSM_UFS_PHY_QUIRK_CFG_RESTORE
+ | MSM_UFS_PHY_DIS_SIGDET_BEFORE_PWR_COLLAPSE);
}
}
diff --git a/drivers/scsi/ufs/ufs-msm.h b/drivers/scsi/ufs/ufs-msm.h
index b9afb1ddd8b0..89e575ed43ad 100644
--- a/drivers/scsi/ufs/ufs-msm.h
+++ b/drivers/scsi/ufs/ufs-msm.h
@@ -119,6 +119,14 @@ struct msm_ufs_phy {
* 7. Wait for UFS_PHY_PCS_READY_STATUS[0] to be '1'
*/
#define MSM_UFS_PHY_QUIRK_CFG_RESTORE (1 << 0)
+ /*
+ * If UFS PHY power down is deasserted and power is restored to analog
+ * circuits, the rx_sigdet can glitch. If the glitch is wide enough,
+ * it can trigger the digital logic to think it saw a DIF-N and cause
+ * it to exit Hibern8. Disabling the rx_sigdet during power-up masks
+ * the glitch.
+ */
+ #define MSM_UFS_PHY_DIS_SIGDET_BEFORE_PWR_COLLAPSE (1 << 1)
};
struct msm_ufs_bus_vote {