Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 408b9f05 authored by Subhash Jadavani's avatar Subhash Jadavani Committed by Can Guo
Browse files

phy: ufs-qcom: disable RX LineCfg



Some UFS devices send incorrect LineCfg data as part of power mode change
sequence which may cause host PHY to go into bad state. Currently we
workaround this issue by disabling the device's TX LCC but disabling TX
LCC is much more complicated if both host and device supports UniPro 1.6
specification. To simplify the workaround, this change disables the host
PHY's RX LineCfg to skip processing incorrect LineCfg from device.

Change-Id: I1eac56c11dd001eb0c53ba8e16aa512a656ab9ea
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
[venkatg@codeaurora.org: resolved trivial merge conflicts]
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
[cang@codeaurora.org: Resolved trivial merge conflicts]
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
parent a68a355c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -126,6 +126,8 @@ struct ufs_qcom_phy {
 * @is_physical_coding_sublayer_ready: pointer to a function that
 * checks pcs readiness. returns 0 for success and non-zero for error.
 * @set_tx_lane_enable: pointer to a function that enable tx lanes
 * @ctrl_rx_linecfg: pointer to a function that controls the Host Rx LineCfg
 * state.
 * @power_control: pointer to a function that controls analog rail of phy
 * and writes to QSERDES_RX_SIGDET_CNTRL attribute
 */
@@ -134,6 +136,7 @@ struct ufs_qcom_phy_specific_ops {
	void (*start_serdes)(struct ufs_qcom_phy *phy);
	int (*is_physical_coding_sublayer_ready)(struct ufs_qcom_phy *phy);
	void (*set_tx_lane_enable)(struct ufs_qcom_phy *phy, u32 val);
	void (*ctrl_rx_linecfg)(struct ufs_qcom_phy *phy, bool ctrl);
	void (*power_control)(struct ufs_qcom_phy *phy, bool val);
};

+18 −0
Original line number Diff line number Diff line
@@ -72,6 +72,23 @@ void ufs_qcom_phy_qmp_14nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val)
	 */
}

static
void ufs_qcom_phy_qmp_14nm_ctrl_rx_linecfg(struct ufs_qcom_phy *phy, bool ctrl)
{
	u32 temp;

	temp = readl_relaxed(phy->mmio + UFS_PHY_LINECFG_DISABLE);

	if (ctrl) /* enable RX LineCfg */
		temp &= ~UFS_PHY_RX_LINECFG_DISABLE_BIT;
	else /* disable RX LineCfg */
		temp |= UFS_PHY_RX_LINECFG_DISABLE_BIT;

	writel_relaxed(temp, phy->mmio + UFS_PHY_LINECFG_DISABLE);
	/* make sure that RX LineCfg config applied before we return */
	mb();
}

static inline void ufs_qcom_phy_qmp_14nm_start_serdes(struct ufs_qcom_phy *phy)
{
	u32 tmp;
@@ -110,6 +127,7 @@ static struct ufs_qcom_phy_specific_ops phy_14nm_ops = {
	.start_serdes		= ufs_qcom_phy_qmp_14nm_start_serdes,
	.is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_14nm_is_pcs_ready,
	.set_tx_lane_enable	= ufs_qcom_phy_qmp_14nm_set_tx_lane_enable,
	.ctrl_rx_linecfg	= ufs_qcom_phy_qmp_14nm_ctrl_rx_linecfg,
	.power_control		= ufs_qcom_phy_qmp_14nm_power_control,
};

+5 −0
Original line number Diff line number Diff line
@@ -74,6 +74,9 @@
/* UFS PHY registers */
#define UFS_PHY_PHY_START			PHY_OFF(0x00)
#define UFS_PHY_POWER_DOWN_CONTROL		PHY_OFF(0x04)
#define UFS_PHY_LINECFG_DISABLE			PHY_OFF(0x138)
#define UFS_PHY_RX_PWM_GEAR_BAND		PHY_OFF(0x154)

#define UFS_PHY_PCS_READY_STATUS		PHY_OFF(0x168)

/* UFS PHY TX registers */
@@ -93,6 +96,8 @@
#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL	RX_OFF(0, 0x11C)
#define QSERDES_RX_RX_INTERFACE_MODE		RX_OFF(0, 0x12C)

#define UFS_PHY_RX_LINECFG_DISABLE_BIT		BIT(1)

/*
 * This structure represents the 14nm specific phy.
 * common_cfg MUST remain the first field in this structure
+18 −0
Original line number Diff line number Diff line
@@ -131,6 +131,23 @@ void ufs_qcom_phy_qmp_20nm_set_tx_lane_enable(struct ufs_qcom_phy *phy, u32 val)
	mb();
}

static
void ufs_qcom_phy_qmp_20nm_ctrl_rx_linecfg(struct ufs_qcom_phy *phy, bool ctrl)
{
	u32 temp;

	temp = readl_relaxed(phy->mmio + UFS_PHY_LINECFG_DISABLE);

	if (ctrl) /* enable RX LineCfg */
		temp &= ~UFS_PHY_RX_LINECFG_DISABLE_BIT;
	else /* disable RX LineCfg */
		temp |= UFS_PHY_RX_LINECFG_DISABLE_BIT;

	writel_relaxed(temp, phy->mmio + UFS_PHY_LINECFG_DISABLE);
	/* make sure that RX LineCfg config applied before we return */
	mb();
}

static inline void ufs_qcom_phy_qmp_20nm_start_serdes(struct ufs_qcom_phy *phy)
{
	u32 tmp;
@@ -168,6 +185,7 @@ static struct ufs_qcom_phy_specific_ops phy_20nm_ops = {
	.start_serdes		= ufs_qcom_phy_qmp_20nm_start_serdes,
	.is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_20nm_is_pcs_ready,
	.set_tx_lane_enable	= ufs_qcom_phy_qmp_20nm_set_tx_lane_enable,
	.ctrl_rx_linecfg	= ufs_qcom_phy_qmp_20nm_ctrl_rx_linecfg,
	.power_control		= ufs_qcom_phy_qmp_20nm_power_control,
};

+2 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@
#define UFS_PHY_RX_MIN_SAVE_CONFIG_TIME_CAPABILITY	PHY_OFF(0xE8)
#define UFS_PHY_RX_PWM_BURST_CLOSURE_LENGTH_CAPABILITY	PHY_OFF(0xFC)
#define UFS_PHY_RX_MIN_ACTIVATETIME_CAPABILITY		PHY_OFF(0x100)
#define UFS_PHY_LINECFG_DISABLE				PHY_OFF(0x134)
#define UFS_PHY_RX_SIGDET_CTRL3				PHY_OFF(0x14c)
#define UFS_PHY_RMMI_ATTR_CTRL			PHY_OFF(0x160)
#define UFS_PHY_RMMI_RX_CFGUPDT_L1	(1 << 7)
@@ -118,6 +119,7 @@
#define UFS_PHY_PCS_READY_STATUS		PHY_OFF(0x174)

#define UFS_PHY_TX_LANE_ENABLE_MASK		0x3
#define UFS_PHY_RX_LINECFG_DISABLE_BIT		BIT(1)

/*
 * This structure represents the 20nm specific phy.
Loading