Skip to contentSkip to conversation

Support for Qualcomm UFS QMP PHY on SDM845

PATCH Superseded Can Guo 3 participants 10 messages May 29, 2018 – Jun 14, 2018

Subsystems (3)

v6 of 10 Superseded Latest is v10 →

lore
Share & tools
lore

Can Guo

author
#0 lore raw

v6 cover Support for Qualcomm UFS QMP PHY on SDM845

This patch series adds support for UFS QMP PHY on SDM845 and the
compatible string for it. This patch series depends on the current
proposed QMP V3 USB3 UNI PHY support for sdm845 driver [1], on
the DT bindings for the QMP V3 USB3 PHYs based dirver [2], and also
rebased on updated pipe_clk initialization sequence [3]. This series
can only be merged once the dependent patches do.
[1] http://lists-archives.com/linux-kernel/29071659-dt-bindings-phy-qcom-qmp-update-bindings-for-sdm845.html
[2] http://lists-archives.com/linux-kernel/29071660-phy-qcom-qmp-add-qmp-v3-usb3-uni-phy-support-for-sdm845.html
[3] https://patchwork.kernel.org/patch/10376551/

Changes since v5:
- Updates the PHY power control sequence.
- Updates UFS PHY power on condition check.

Changes since v4:
- Adds 'ref_aux' clock back to SDM845 UFS PHY clock list.
- Power on PHY before serdes configuration starts.
- Updates the UFS PHY initialization sequence.
- Updates a few UFS PHY registers.
- Incorporated review comments from Vivek and Manu.

Changes since v3:
- Incorporated review comments from Vivek and Rob.

Changes since v2:
- Incorporated review comments from Vivek and Rob.
- Remove "ref_aux" from sdm845 ufs phy clock list structure.

Changes since v1:
- Incorporated review comments from Vivek and Manu.
- Update the commit title of patch 2.

Can Guo (3):
phy: Update PHY power control sequence
phy: Add QMP phy based UFS phy support for sdm845
dt-bindings: phy-qcom-qmp: Add UFS phy compatible string for sdm845

 .../devicetree/bindings/phy/qcom-qmp-phy.txt       |   4 +-
 drivers/phy/qualcomm/phy-qcom-qmp.c                | 205 +++++++++++++++++++--
 drivers/phy/qualcomm/phy-qcom-qmp.h                |  15 ++
 3 files changed, 210 insertions(+), 14 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
author
#1 lore raw

PATCH v6 1/3 phy: Update PHY power control sequence

All PHYs should be powered on before register configuration starts. And only PCIe PHYs need an extra power control before deasserts reset state.

---
 drivers/phy/qualcomm/phy-qcom-qmp.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-qmp.c +4 -1
index 97ef942..f779b0f 100644
@@ -982,6 +982,8 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
 	if (cfg->has_phy_com_ctrl)
 		qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
 			     SW_PWRDN);
+	else
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
 
 	if (cfg->has_phy_dp_com_ctrl) {
 		qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
@@ -1127,7 +1129,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
 	 * Pull out PHY from POWER DOWN state.
 	 * This is active low enable signal to power-down PHY.
 	 */
-	qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
+	if (cfg->type == PHY_TYPE_PCIE)
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
 
 	if (cfg->has_pwrdn_delay)
 		usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#2 lore raw

Re: [PATCH v6 1/3] phy: Update PHY power control sequence

Hi,

Quoted 13 lines · Can Guo

All PHYs should be powered on before register configuration starts. And only PCIe PHYs need an extra power control before deasserts reset state.

---
 drivers/phy/qualcomm/phy-qcom-qmp.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-qmp.c +0 -0
index 97ef942..f779b0f 100644

drivers/phy/qualcomm/phy-qcom-qmp.c static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) · line 986

Quoted 5 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -0
@@ -982,6 +982,8 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
 	if (cfg->has_phy_com_ctrl)
 		qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
 			     SW_PWRDN);
+	else
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);

We should power-up PHYs after following dp_com_ctrl programming which powers-off USB-DP combo PHY when it brings DP_COM block out of reset reset.

Quoted 13 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -1
 	if (cfg->has_phy_dp_com_ctrl) {
 		qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
@@ -1127,7 +1129,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
 	 * Pull out PHY from POWER DOWN state.
 	 * This is active low enable signal to power-down PHY.
 	 */
-	qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
+	if (cfg->type == PHY_TYPE_PCIE)
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
 
 	if (cfg->has_pwrdn_delay)
 		usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#3 lore raw

Re: [PATCH v6 1/3] phy: Update PHY power control sequence

Quoted 11 lines · Manu Gautam

Hi,

Quoted 8 lines · Can Guo

All PHYs should be powered on before register configuration starts. And only PCIe PHYs need an extra power control before deasserts reset state.

---
 drivers/phy/qualcomm/phy-qcom-qmp.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
Quoted 16 lines

drivers/phy/qualcomm/phy-qcom-qmp.c static int qcom_qmp_phy_com_init(struct qcom_qmp · line 987

Quoted 11 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -0
index 97ef942..f779b0f 100644
@@ -982,6 +982,8 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp 
 *qmp)
 	if (cfg->has_phy_com_ctrl)
 		qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
 			     SW_PWRDN);
+	else
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);

We should power-up PHYs after following dp_com_ctrl programming which powers-off USB-DP combo PHY when it brings DP_COM block out of reset reset.

Sure Manu

Quoted 13 lines
Quoted 13 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -1
 	if (cfg->has_phy_dp_com_ctrl) {
 		qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
@@ -1127,7 +1129,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
 	 * Pull out PHY from POWER DOWN state.
 	 * This is active low enable signal to power-down PHY.
 	 */
-	qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
+	if (cfg->type == PHY_TYPE_PCIE)
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
 
 	if (cfg->has_pwrdn_delay)
 		usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
#4 lore raw

Re: [PATCH v6 1/3] phy: Update PHY power control sequence

In reply to Can Guo

Hi Can,

Quoted 13 lines · Can Guo

All PHYs should be powered on before register configuration starts. And only PCIe PHYs need an extra power control before deasserts reset state.

---
  drivers/phy/qualcomm/phy-qcom-qmp.c | 5 ++++-
  1 file changed, 4 insertions(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-qmp.c +0 -0
index 97ef942..f779b0f 100644

drivers/phy/qualcomm/phy-qcom-qmp.c static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) · line 986

Quoted 5 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -0
@@ -982,6 +982,8 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
  	if (cfg->has_phy_com_ctrl)
  		qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
  			     SW_PWRDN);
+	else
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);

No definition of 'pcs' in this function. You are doing that in the second patch. But, we should add this definition here.

Also instead of having the change like this:

+ struct qmp_phy *qphy = qmp->phys[0];
void __iomem *serdes = qmp->serdes;
+ void __iomem *pcs = qphy->pcs;

Let's pass 'struct qmp_phy' to qcom_qmp_phy_com_init(), and then get 'struct qcom_qmp' and 'void __iomem *pcs' from that.

So,

-static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) +static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) {
+       struct qcom_qmp *qmp = qphy->qmp; const struct qmp_phy_cfg *cfg = qmp->cfg; void __iomem *serdes = qmp->serdes; void __iomem *dp_com = qmp->dp_com;
+       void __iomem *pcs = qphy->pcs;

and

-       ret = qcom_qmp_phy_com_init(qmp);
+       ret = qcom_qmp_phy_com_init(qphy);

That looks cleaner than extracting from the 0th phys.

BRs
Vivek

Quoted 13 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -1
  	if (cfg->has_phy_dp_com_ctrl) {
  		qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
@@ -1127,7 +1129,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
  	 * Pull out PHY from POWER DOWN state.
  	 * This is active low enable signal to power-down PHY.
  	 */
-	qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
+	if (cfg->type == PHY_TYPE_PCIE)
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
 
  	if (cfg->has_pwrdn_delay)
  		usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
#5 lore raw

Re: [PATCH v6 1/3] phy: Update PHY power control sequence

Quoted 49 lines · Vivek Gautam

Hi Can,

Quoted 13 lines · Can Guo

All PHYs should be powered on before register configuration starts. And only PCIe PHYs need an extra power control before deasserts reset state.

---
  drivers/phy/qualcomm/phy-qcom-qmp.c | 5 ++++-
  1 file changed, 4 insertions(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-qmp.c +0 -0
index 97ef942..f779b0f 100644

drivers/phy/qualcomm/phy-qcom-qmp.c static int qcom_qmp_phy_com_init(struct qcom_qmp · line 987

Quoted 6 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -0
@@ -982,6 +982,8 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp 
 *qmp)
  	if (cfg->has_phy_com_ctrl)
  		qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
  			     SW_PWRDN);
+	else
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);

No definition of 'pcs' in this function. You are doing that in the second patch. But, we should add this definition here.

Also instead of having the change like this:

(quoted diff) +2 -0
+	struct qmp_phy *qphy = qmp->phys[0];
 	void __iomem *serdes = qmp->serdes;
+	void __iomem *pcs = qphy->pcs;

Let's pass 'struct qmp_phy' to qcom_qmp_phy_com_init(), and then get 'struct qcom_qmp' and 'void __iomem *pcs' from that.

So,

(quoted diff) +1 -1
-static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
+static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)

 {
+       struct qcom_qmp *qmp = qphy->qmp;
        const struct qmp_phy_cfg *cfg = qmp->cfg;
        void __iomem *serdes = qmp->serdes;
        void __iomem *dp_com = qmp->dp_com;
+       void __iomem *pcs = qphy->pcs;

and

Quoted 7 lines

-       ret = qcom_qmp_phy_com_init(qmp);
+       ret = qcom_qmp_phy_com_init(qphy);

That looks cleaner than extracting from the 0th phys.

BRs
Vivek

Sure Vivek

Quoted 11 lines
Quoted 11 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -1
    	if (cfg->has_phy_dp_com_ctrl) {
  		qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
@@ -1127,7 +1129,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
  	 * Pull out PHY from POWER DOWN state.
  	 * This is active low enable signal to power-down PHY.
  	 */
-	qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
+	if (cfg->type == PHY_TYPE_PCIE)
+		qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl);
    	if (cfg->has_pwrdn_delay)
  		usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
author
#6 lore raw

PATCH v6 2/3 phy: Add QMP phy based UFS phy support for sdm845

In reply to Can Guo

Add UFS PHY support to make SDM845 UFS work with common PHY framework.

---
 drivers/phy/qualcomm/phy-qcom-qmp.c | 200 +++++++++++++++++++++++++++++++++---
 drivers/phy/qualcomm/phy-qcom-qmp.h |  15 +++
 2 files changed, 203 insertions(+), 12 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp.c +188 -12
index f779b0f..ee74dcd 100644
@@ -156,6 +156,11 @@ enum qphy_reg_layout {
 	[QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170,
 };
 
+static const unsigned int sdm845_ufsphy_regs_layout[] = {
+	[QPHY_START_CTRL]		= 0x00,
+	[QPHY_PCS_READY_STATUS]		= 0x160,
+};
+
 static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
 	QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
 	QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
@@ -601,6 +606,83 @@ enum qphy_reg_layout {
 	QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60),
 };
 
+static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f),
+
+	/* Rate B */
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02),
+};
 
 /* struct qmp_phy_cfg - per-PHY initialization config */
 struct qmp_phy_cfg {
@@ -649,9 +731,14 @@ struct qmp_phy_cfg {
 
 	/* true, if PHY has a separate DP_COM control block */
 	bool has_phy_dp_com_ctrl;
+	/* true, if PHY has secondary tx/rx lanes to be configured */
+	bool is_dual_lane_phy;
 	/* Register offset of secondary tx/rx lanes for USB DP combo PHY */
 	unsigned int tx_b_lane_offset;
 	unsigned int rx_b_lane_offset;
+
+	/* true, if PCS block has no separate SW_RESET register */
+	bool no_pcs_sw_reset;
 };
 
 /**
@@ -748,6 +835,10 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 	"aux", "cfg_ahb", "ref", "com_aux",
 };
 
+static const char * const sdm845_ufs_phy_clk_l[] = {
+	"ref", "ref_aux",
+};
+
 /* list of resets */
 static const char * const msm8996_pciephy_reset_l[] = {
 	"phy", "common", "cfg",
@@ -758,7 +849,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 };
 
 /* list of regulators */
-static const char * const msm8996_phy_vreg_l[] = {
+static const char * const qmp_phy_vreg_l[] = {
 	"vdda-phy", "vdda-pll",
 };
 
@@ -778,8 +869,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 	.num_clks		= ARRAY_SIZE(msm8996_phy_clk_l),
 	.reset_list		= msm8996_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_pciephy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= pciephy_regs_layout,
 
 	.start_ctrl		= PCS_START | PLL_READY_GATE_EN,
@@ -809,8 +900,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 	.num_clks		= ARRAY_SIZE(msm8996_phy_clk_l),
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= usb3phy_regs_layout,
 
 	.start_ctrl		= SERDES_START | PCS_START,
@@ -870,8 +961,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 	.num_clks		= ARRAY_SIZE(qmp_v3_phy_clk_l),
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= qmp_v3_usb3phy_regs_layout,
 
 	.start_ctrl		= SERDES_START | PCS_START,
@@ -883,6 +974,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 	.pwrdn_delay_max	= POWER_DOWN_DELAY_US_MAX,
 
 	.has_phy_dp_com_ctrl	= true,
+	.is_dual_lane_phy	= true,
 	.tx_b_lane_offset	= 0x400,
 	.rx_b_lane_offset	= 0x400,
 };
@@ -903,8 +995,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 	.num_clks		= ARRAY_SIZE(qmp_v3_phy_clk_l),
 	.reset_list		= msm8996_usb3phy_reset_l,
 	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
 	.regs			= qmp_v3_usb3phy_regs_layout,
 
 	.start_ctrl		= SERDES_START | PCS_START,
@@ -916,6 +1008,35 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
 	.pwrdn_delay_max	= POWER_DOWN_DELAY_US_MAX,
 };
 
+static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
+	.type			= PHY_TYPE_UFS,
+	.nlanes			= 2,
+
+	.serdes_tbl		= sdm845_ufsphy_serdes_tbl,
+	.serdes_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_serdes_tbl),
+	.tx_tbl			= sdm845_ufsphy_tx_tbl,
+	.tx_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_tx_tbl),
+	.rx_tbl			= sdm845_ufsphy_rx_tbl,
+	.rx_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_rx_tbl),
+	.pcs_tbl		= sdm845_ufsphy_pcs_tbl,
+	.pcs_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_pcs_tbl),
+	.clk_list		= sdm845_ufs_phy_clk_l,
+	.num_clks		= ARRAY_SIZE(sdm845_ufs_phy_clk_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+	.regs			= sdm845_ufsphy_regs_layout,
+
+	.start_ctrl		= SERDES_START,
+	.pwrdn_ctrl		= SW_PWRDN,
+	.mask_pcs_ready		= PCS_READY,
+
+	.is_dual_lane_phy	= true,
+	.tx_b_lane_offset	= 0x400,
+	.rx_b_lane_offset	= 0x400,
+
+	.no_pcs_sw_reset	= true,
+};
+
 static void qcom_qmp_phy_configure(void __iomem *base,
 				   const unsigned int *regs,
 				   const struct qmp_phy_init_tbl tbl[],
@@ -938,7 +1059,9 @@ static void qcom_qmp_phy_configure(void __iomem *base,
 static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
 {
 	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	struct qmp_phy *qphy = qmp->phys[0];
 	void __iomem *serdes = qmp->serdes;
+	void __iomem *pcs = qphy->pcs;
 	void __iomem *dp_com = qmp->dp_com;
 	int ret, i;
 
@@ -1114,18 +1237,27 @@ static int qcom_qmp_phy_init(struct phy *phy)
 	/* Tx, Rx, and PCS configurations */
 	qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num);
 	/* Configuration for other LANE for USB-DP combo PHY */
-	if (cfg->has_phy_dp_com_ctrl)
+	if (cfg->is_dual_lane_phy)
 		qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs,
 				       cfg->tx_tbl, cfg->tx_tbl_num);
 
 	qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num);
-	if (cfg->has_phy_dp_com_ctrl)
+	if (cfg->is_dual_lane_phy)
 		qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs,
 				       cfg->rx_tbl, cfg->rx_tbl_num);
 
 	qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
 
 	/*
+	 * UFS PHY requires the deassert of software reset before serdes start.
+	 * For UFS PHY that has not software reset control bits in its address
+	 * space, it should skip starting serdes here. UFS PHY Serdes shall
+	 * start when UFS explicitly calls PHY power on.
+	 */
+	if ((cfg->type == PHY_TYPE_UFS) && cfg->no_pcs_sw_reset)
+		goto out;
+
+	/*
 	 * Pull out PHY from POWER DOWN state.
 	 * This is active low enable signal to power-down PHY.
 	 */
@@ -1154,6 +1286,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
 	}
 	qmp->phy_initialized = true;
 
+out:
 	return ret;
 
 err_pcs_ready:
@@ -1176,7 +1309,8 @@ static int qcom_qmp_phy_exit(struct phy *phy)
 	clk_disable_unprepare(qphy->pipe_clk);
 
 	/* PHY reset */
-	qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+	if (!cfg->no_pcs_sw_reset)
+		qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
 
 	/* stop SerDes and Phy-Coding-Sublayer */
 	qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
@@ -1194,6 +1328,44 @@ static int qcom_qmp_phy_exit(struct phy *phy)
 	return 0;
 }
 
+static int qcom_qmp_phy_poweron(struct phy *phy)
+{
+	struct qmp_phy *qphy = phy_get_drvdata(phy);
+	struct qcom_qmp *qmp = qphy->qmp;
+	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	void __iomem *pcs = qphy->pcs;
+	void __iomem *status;
+	unsigned int mask, val;
+	int ret = 0;
+
+	if (cfg->type != PHY_TYPE_UFS)
+		return 0;
+
+	/*
+	 * For UFS PHY that has not software reset control, serdes start
+	 * should only happen when UFS driver explicitly calls phy_power_on
+	 * after it deasserts software reset.
+	 */
+	if (cfg->no_pcs_sw_reset && !qmp->phy_initialized &&
+	    (qmp->init_count !=0)) {
+		/* start SerDes and Phy-Coding-Sublayer */
+		qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
+
+		status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
+		mask = cfg->mask_pcs_ready;
+
+		ret = readl_poll_timeout(status, val, !(val & mask), 1,
+					 PHY_INIT_COMPLETE_TIMEOUT);
+		if (ret) {
+			dev_err(qmp->dev, "phy initialization timed-out\n");
+			return ret;
+		}
+		qmp->phy_initialized = true;
+	}
+
+	return ret;
+}
+
 static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode)
 {
 	struct qmp_phy *qphy = phy_get_drvdata(phy);
@@ -1423,6 +1595,7 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
 static const struct phy_ops qcom_qmp_phy_gen_ops = {
 	.init		= qcom_qmp_phy_init,
 	.exit		= qcom_qmp_phy_exit,
+	.power_on	= qcom_qmp_phy_poweron,
 	.set_mode	= qcom_qmp_phy_set_mode,
 	.owner		= THIS_MODULE,
 };
@@ -1528,6 +1701,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
 	}, {
 		.compatible = "qcom,sdm845-qmp-usb3-uni-phy",
 		.data = &qmp_v3_usb3_uniphy_cfg,
+	}, {
+		.compatible = "qcom,sdm845-qmp-ufs-phy",
+		.data = &sdm845_ufsphy_cfg,
 	},
 	{ },
 };
drivers/phy/qualcomm/phy-qcom-qmp.h +15 -0
index 5d78d43..d201cc3 100644
@@ -184,6 +184,8 @@
 #define QSERDES_V3_COM_VCO_TUNE2_MODE0			0x0f8
 #define QSERDES_V3_COM_VCO_TUNE1_MODE1			0x0fc
 #define QSERDES_V3_COM_VCO_TUNE2_MODE1			0x100
+#define QSERDES_V3_COM_VCO_TUNE_INITVAL1		0x104
+#define QSERDES_V3_COM_VCO_TUNE_INITVAL2		0x108
 #define QSERDES_V3_COM_VCO_TUNE_TIMER1			0x11c
 #define QSERDES_V3_COM_VCO_TUNE_TIMER2			0x120
 #define QSERDES_V3_COM_CLK_SELECT			0x138
@@ -211,8 +213,13 @@
 /* Only for QMP V3 PHY - RX registers */
 #define QSERDES_V3_RX_UCDR_SO_GAIN_HALF			0x00c
 #define QSERDES_V3_RX_UCDR_SO_GAIN			0x014
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF		0x024
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER		0x028
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN			0x02c
 #define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN		0x030
 #define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE	0x034
+#define QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW		0x03c
+#define QSERDES_V3_RX_UCDR_PI_CONTROLS			0x044
 #define QSERDES_V3_RX_RX_TERM_BW			0x07c
 #define QSERDES_V3_RX_VGA_CAL_CNTRL1			0x0bc
 #define QSERDES_V3_RX_VGA_CAL_CNTRL2			0x0c0
@@ -239,6 +246,8 @@
 #define QPHY_V3_PCS_TXMGN_V3				0x018
 #define QPHY_V3_PCS_TXMGN_V4				0x01c
 #define QPHY_V3_PCS_TXMGN_LS				0x020
+#define QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL		0x02c
+#define QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL		0x034
 #define QPHY_V3_PCS_TXDEEMPH_M6DB_V0			0x024
 #define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0			0x028
 #define QPHY_V3_PCS_TXDEEMPH_M6DB_V1			0x02c
@@ -275,6 +284,12 @@
 #define QPHY_V3_PCS_FLL_CNT_VAL_L			0x0cc
 #define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL			0x0d0
 #define QPHY_V3_PCS_FLL_MAN_CODE			0x0d4
+#define QPHY_V3_PCS_RX_SYM_RESYNC_CTRL			0x134
+#define QPHY_V3_PCS_RX_MIN_HIBERN8_TIME			0x138
+#define QPHY_V3_PCS_RX_SIGDET_CTRL1			0x13c
+#define QPHY_V3_PCS_RX_SIGDET_CTRL2			0x140
+#define QPHY_V3_PCS_TX_MID_TERM_CTRL1			0x1bc
+#define QPHY_V3_PCS_MULTI_LANE_CTRL1			0x1c4
 #define QPHY_V3_PCS_RX_SIGDET_LVL			0x1d8
 #define QPHY_V3_PCS_REFGEN_REQ_CONFIG1			0x20c
 #define QPHY_V3_PCS_REFGEN_REQ_CONFIG2			0x210
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
#7 lore raw

Re: [PATCH v6 2/3] phy: Add QMP phy based UFS phy support for sdm845

Hi Can,

Quoted 109 lines · Can Guo

Add UFS PHY support to make SDM845 UFS work with common PHY framework.

---
  drivers/phy/qualcomm/phy-qcom-qmp.c | 200 +++++++++++++++++++++++++++++++++---
  drivers/phy/qualcomm/phy-qcom-qmp.h |  15 +++
  2 files changed, 203 insertions(+), 12 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp.c +82 -0
index f779b0f..ee74dcd 100644
@@ -156,6 +156,11 @@ enum qphy_reg_layout {
  	[QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170,
  };
 
+static const unsigned int sdm845_ufsphy_regs_layout[] = {
+	[QPHY_START_CTRL]		= 0x00,
+	[QPHY_PCS_READY_STATUS]		= 0x160,
+};
+
  static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
  	QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
  	QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
@@ -601,6 +606,83 @@ enum qphy_reg_layout {
  	QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60),
  };
 
+static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f),
+
+	/* Rate B */
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02),
+};
 
  /* struct qmp_phy_cfg - per-PHY initialization config */
  struct qmp_phy_cfg {

drivers/phy/qualcomm/phy-qcom-qmp.c struct qmp_phy_cfg { · line 735

Quoted 5 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -0
@@ -649,9 +731,14 @@ struct qmp_phy_cfg {
 
  	/* true, if PHY has a separate DP_COM control block */
  	bool has_phy_dp_com_ctrl;
+	/* true, if PHY has secondary tx/rx lanes to be configured */
+	bool is_dual_lane_phy;

Separate out this change to a new patch please.

Quoted 21 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +7 -0
  	/* Register offset of secondary tx/rx lanes for USB DP combo PHY */
  	unsigned int tx_b_lane_offset;
  	unsigned int rx_b_lane_offset;
+
+	/* true, if PCS block has no separate SW_RESET register */
+	bool no_pcs_sw_reset;
  };
 
  /**
@@ -748,6 +835,10 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  	"aux", "cfg_ahb", "ref", "com_aux",
  };
 
+static const char * const sdm845_ufs_phy_clk_l[] = {
+	"ref", "ref_aux",
+};
+
  /* list of resets */
  static const char * const msm8996_pciephy_reset_l[] = {
  	"phy", "common", "cfg",

drivers/phy/qualcomm/phy-qcom-qmp.c static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) · line 852

Quoted 5 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +1 -1
@@ -758,7 +849,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  };
 
  /* list of regulators */
-static const char * const msm8996_phy_vreg_l[] = {
+static const char * const qmp_phy_vreg_l[] = {

These changes are not related to ufs, so better keep all these in a separate patch, say 'cleanup', as mentioned above.

drivers/phy/qualcomm/phy-qcom-qmp.c static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) · line 873

Quoted 11 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -2
  	"vdda-phy", "vdda-pll",
  };
 
@@ -778,8 +869,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  	.num_clks		= ARRAY_SIZE(msm8996_phy_clk_l),
  	.reset_list		= msm8996_pciephy_reset_l,
  	.num_resets		= ARRAY_SIZE(msm8996_pciephy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),

So this changes and other vreg changes in cfg goes to the separate patch.

Quoted 26 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +4 -4
  	.regs			= pciephy_regs_layout,
 
  	.start_ctrl		= PCS_START | PLL_READY_GATE_EN,
@@ -809,8 +900,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  	.num_clks		= ARRAY_SIZE(msm8996_phy_clk_l),
  	.reset_list		= msm8996_usb3phy_reset_l,
  	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
  	.regs			= usb3phy_regs_layout,
 
  	.start_ctrl		= SERDES_START | PCS_START,
@@ -870,8 +961,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  	.num_clks		= ARRAY_SIZE(qmp_v3_phy_clk_l),
  	.reset_list		= msm8996_usb3phy_reset_l,
  	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
  	.regs			= qmp_v3_usb3phy_regs_layout,
 
  	.start_ctrl		= SERDES_START | PCS_START,

drivers/phy/qualcomm/phy-qcom-qmp.c static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) · line 977

Quoted 4 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +1 -0
@@ -883,6 +974,7 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  	.pwrdn_delay_max	= POWER_DOWN_DELAY_US_MAX,
 
  	.has_phy_dp_com_ctrl	= true,
+	.is_dual_lane_phy	= true,

This too goes to the new patch.

Quoted 62 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +33 -2
  	.tx_b_lane_offset	= 0x400,
  	.rx_b_lane_offset	= 0x400,
  };
@@ -903,8 +995,8 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  	.num_clks		= ARRAY_SIZE(qmp_v3_phy_clk_l),
  	.reset_list		= msm8996_usb3phy_reset_l,
  	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
  	.regs			= qmp_v3_usb3phy_regs_layout,
 
  	.start_ctrl		= SERDES_START | PCS_START,
@@ -916,6 +1008,35 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
  	.pwrdn_delay_max	= POWER_DOWN_DELAY_US_MAX,
  };
 
+static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
+	.type			= PHY_TYPE_UFS,
+	.nlanes			= 2,
+
+	.serdes_tbl		= sdm845_ufsphy_serdes_tbl,
+	.serdes_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_serdes_tbl),
+	.tx_tbl			= sdm845_ufsphy_tx_tbl,
+	.tx_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_tx_tbl),
+	.rx_tbl			= sdm845_ufsphy_rx_tbl,
+	.rx_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_rx_tbl),
+	.pcs_tbl		= sdm845_ufsphy_pcs_tbl,
+	.pcs_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_pcs_tbl),
+	.clk_list		= sdm845_ufs_phy_clk_l,
+	.num_clks		= ARRAY_SIZE(sdm845_ufs_phy_clk_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+	.regs			= sdm845_ufsphy_regs_layout,
+
+	.start_ctrl		= SERDES_START,
+	.pwrdn_ctrl		= SW_PWRDN,
+	.mask_pcs_ready		= PCS_READY,
+
+	.is_dual_lane_phy	= true,
+	.tx_b_lane_offset	= 0x400,
+	.rx_b_lane_offset	= 0x400,
+
+	.no_pcs_sw_reset	= true,
+};
+
  static void qcom_qmp_phy_configure(void __iomem *base,
  				   const unsigned int *regs,
  				   const struct qmp_phy_init_tbl tbl[],
@@ -938,7 +1059,9 @@ static void qcom_qmp_phy_configure(void __iomem *base,
  static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
  {
  	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	struct qmp_phy *qphy = qmp->phys[0];
  	void __iomem *serdes = qmp->serdes;
+	void __iomem *pcs = qphy->pcs;
  	void __iomem *dp_com = qmp->dp_com;
  	int ret, i;
 
@@ -1114,18 +1237,27 @@ static int qcom_qmp_phy_init(struct phy *phy)
  	/* Tx, Rx, and PCS configurations */

drivers/phy/qualcomm/phy-qcom-qmp.c static int qcom_qmp_phy_init(struct phy *phy) · line 1245

Quoted 10 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -2
  	qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num);
  	/* Configuration for other LANE for USB-DP combo PHY */
-	if (cfg->has_phy_dp_com_ctrl)
+	if (cfg->is_dual_lane_phy)
  		qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs,
  				       cfg->tx_tbl, cfg->tx_tbl_num);
 
  	qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num);
-	if (cfg->has_phy_dp_com_ctrl)
+	if (cfg->is_dual_lane_phy)

And these couple of changes too to the new patch. This helps in bisecting in the time of issue.

Quoted 148 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +54 -1
  		qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs,
  				       cfg->rx_tbl, cfg->rx_tbl_num);
 
  	qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
 
  	/*
+	 * UFS PHY requires the deassert of software reset before serdes start.
+	 * For UFS PHY that has not software reset control bits in its address
+	 * space, it should skip starting serdes here. UFS PHY Serdes shall
+	 * start when UFS explicitly calls PHY power on.
+	 */
+	if ((cfg->type == PHY_TYPE_UFS) && cfg->no_pcs_sw_reset)
+		goto out;
+
+	/*
  	 * Pull out PHY from POWER DOWN state.
  	 * This is active low enable signal to power-down PHY.
  	 */
@@ -1154,6 +1286,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
  	}
  	qmp->phy_initialized = true;
 
+out:
  	return ret;
 
  err_pcs_ready:
@@ -1176,7 +1309,8 @@ static int qcom_qmp_phy_exit(struct phy *phy)
  	clk_disable_unprepare(qphy->pipe_clk);
 
  	/* PHY reset */
-	qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+	if (!cfg->no_pcs_sw_reset)
+		qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
 
  	/* stop SerDes and Phy-Coding-Sublayer */
  	qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
@@ -1194,6 +1328,44 @@ static int qcom_qmp_phy_exit(struct phy *phy)
  	return 0;
  }
 
+static int qcom_qmp_phy_poweron(struct phy *phy)
+{
+	struct qmp_phy *qphy = phy_get_drvdata(phy);
+	struct qcom_qmp *qmp = qphy->qmp;
+	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	void __iomem *pcs = qphy->pcs;
+	void __iomem *status;
+	unsigned int mask, val;
+	int ret = 0;
+
+	if (cfg->type != PHY_TYPE_UFS)
+		return 0;
+
+	/*
+	 * For UFS PHY that has not software reset control, serdes start
+	 * should only happen when UFS driver explicitly calls phy_power_on
+	 * after it deasserts software reset.
+	 */
+	if (cfg->no_pcs_sw_reset && !qmp->phy_initialized &&
+	    (qmp->init_count !=0)) {
+		/* start SerDes and Phy-Coding-Sublayer */
+		qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
+
+		status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
+		mask = cfg->mask_pcs_ready;
+
+		ret = readl_poll_timeout(status, val, !(val & mask), 1,
+					 PHY_INIT_COMPLETE_TIMEOUT);
+		if (ret) {
+			dev_err(qmp->dev, "phy initialization timed-out\n");
+			return ret;
+		}
+		qmp->phy_initialized = true;
+	}
+
+	return ret;
+}
+
  static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode)
  {
  	struct qmp_phy *qphy = phy_get_drvdata(phy);
@@ -1423,6 +1595,7 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
  static const struct phy_ops qcom_qmp_phy_gen_ops = {
  	.init		= qcom_qmp_phy_init,
  	.exit		= qcom_qmp_phy_exit,
+	.power_on	= qcom_qmp_phy_poweron,
  	.set_mode	= qcom_qmp_phy_set_mode,
  	.owner		= THIS_MODULE,
  };
@@ -1528,6 +1701,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
  	}, {
  		.compatible = "qcom,sdm845-qmp-usb3-uni-phy",
  		.data = &qmp_v3_usb3_uniphy_cfg,
+	}, {
+		.compatible = "qcom,sdm845-qmp-ufs-phy",
+		.data = &sdm845_ufsphy_cfg,
  	},
  	{ },
  };
drivers/phy/qualcomm/phy-qcom-qmp.h +15 -0
index 5d78d43..d201cc3 100644
@@ -184,6 +184,8 @@
  #define QSERDES_V3_COM_VCO_TUNE2_MODE0			0x0f8
  #define QSERDES_V3_COM_VCO_TUNE1_MODE1			0x0fc
  #define QSERDES_V3_COM_VCO_TUNE2_MODE1			0x100
+#define QSERDES_V3_COM_VCO_TUNE_INITVAL1		0x104
+#define QSERDES_V3_COM_VCO_TUNE_INITVAL2		0x108
  #define QSERDES_V3_COM_VCO_TUNE_TIMER1			0x11c
  #define QSERDES_V3_COM_VCO_TUNE_TIMER2			0x120
  #define QSERDES_V3_COM_CLK_SELECT			0x138
@@ -211,8 +213,13 @@
  /* Only for QMP V3 PHY - RX registers */
  #define QSERDES_V3_RX_UCDR_SO_GAIN_HALF			0x00c
  #define QSERDES_V3_RX_UCDR_SO_GAIN			0x014
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF		0x024
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER		0x028
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN			0x02c
  #define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN		0x030
  #define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE	0x034
+#define QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW		0x03c
+#define QSERDES_V3_RX_UCDR_PI_CONTROLS			0x044
  #define QSERDES_V3_RX_RX_TERM_BW			0x07c
  #define QSERDES_V3_RX_VGA_CAL_CNTRL1			0x0bc
  #define QSERDES_V3_RX_VGA_CAL_CNTRL2			0x0c0
@@ -239,6 +246,8 @@
  #define QPHY_V3_PCS_TXMGN_V3				0x018
  #define QPHY_V3_PCS_TXMGN_V4				0x01c
  #define QPHY_V3_PCS_TXMGN_LS				0x020
+#define QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL		0x02c
+#define QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL		0x034
  #define QPHY_V3_PCS_TXDEEMPH_M6DB_V0			0x024
  #define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0			0x028
  #define QPHY_V3_PCS_TXDEEMPH_M6DB_V1			0x02c
@@ -275,6 +284,12 @@
  #define QPHY_V3_PCS_FLL_CNT_VAL_L			0x0cc
  #define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL			0x0d0
  #define QPHY_V3_PCS_FLL_MAN_CODE			0x0d4
+#define QPHY_V3_PCS_RX_SYM_RESYNC_CTRL			0x134
+#define QPHY_V3_PCS_RX_MIN_HIBERN8_TIME			0x138
+#define QPHY_V3_PCS_RX_SIGDET_CTRL1			0x13c
+#define QPHY_V3_PCS_RX_SIGDET_CTRL2			0x140
+#define QPHY_V3_PCS_TX_MID_TERM_CTRL1			0x1bc
+#define QPHY_V3_PCS_MULTI_LANE_CTRL1			0x1c4
  #define QPHY_V3_PCS_RX_SIGDET_LVL			0x1d8
  #define QPHY_V3_PCS_REFGEN_REQ_CONFIG1			0x20c
  #define QPHY_V3_PCS_REFGEN_REQ_CONFIG2			0x210
#8 lore raw

Re: [PATCH v6 2/3] phy: Add QMP phy based UFS phy support for sdm845

Quoted 109 lines · Vivek Gautam

Hi Can,

Quoted 105 lines · Can Guo

Add UFS PHY support to make SDM845 UFS work with common PHY framework.

---
  drivers/phy/qualcomm/phy-qcom-qmp.c | 200 
+++++++++++++++++++++++++++++++++---
  drivers/phy/qualcomm/phy-qcom-qmp.h |  15 +++
  2 files changed, 203 insertions(+), 12 deletions(-)
drivers/phy/qualcomm/phy-qcom-qmp.c +80 -0
index f779b0f..ee74dcd 100644
@@ -156,6 +156,11 @@ enum qphy_reg_layout {
  	[QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170,
  };
  +static const unsigned int sdm845_ufsphy_regs_layout[] = {
+	[QPHY_START_CTRL]		= 0x00,
+	[QPHY_PCS_READY_STATUS]		= 0x160,
+};
+
  static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
  	QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
  	QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
@@ -601,6 +606,83 @@ enum qphy_reg_layout {
  	QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60),
  };
  +static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32),
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f),
+
+	/* Rate B */
+	QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80),
+	QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59),
+};
+
+static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a),
+	QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02),
+};
    /* struct qmp_phy_cfg - per-PHY initialization config */
Quoted 9 lines

drivers/phy/qualcomm/phy-qcom-qmp.c struct qmp_phy_cfg { · line 734

Quoted 6 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +2 -0
  struct qmp_phy_cfg {
@@ -649,9 +731,14 @@ struct qmp_phy_cfg {
    	/* true, if PHY has a separate DP_COM control block */
  	bool has_phy_dp_com_ctrl;
+	/* true, if PHY has secondary tx/rx lanes to be configured */
+	bool is_dual_lane_phy;

Separate out this change to a new patch please.

Sure Vivek

Quoted 20 lines
Quoted 20 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +6 -0
  	/* Register offset of secondary tx/rx lanes for USB DP combo PHY */
  	unsigned int tx_b_lane_offset;
  	unsigned int rx_b_lane_offset;
+
+	/* true, if PCS block has no separate SW_RESET register */
+	bool no_pcs_sw_reset;
  };
    /**
@@ -748,6 +835,10 @@ static inline void qphy_clrbits(void __iomem 
 *base, u32 offset, u32 val)
  	"aux", "cfg_ahb", "ref", "com_aux",
  };
  +static const char * const sdm845_ufs_phy_clk_l[] = {
+	"ref", "ref_aux",
+};
+
  /* list of resets */
  static const char * const msm8996_pciephy_reset_l[] = {
  	"phy", "common", "cfg",
@@ -758,7 +849,7 @@ static inline void qphy_clrbits(void __iomem 
Quoted 9 lines

drivers/phy/qualcomm/phy-qcom-qmp.c static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) · line 852

Quoted 5 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +1 -1
 *base, u32 offset, u32 val)
  };
    /* list of regulators */
-static const char * const msm8996_phy_vreg_l[] = {
+static const char * const qmp_phy_vreg_l[] = {

These changes are not related to ufs, so better keep all these in a separate patch, say 'cleanup', as mentioned above.

Make sense, shall do so.

Quoted 37 lines

drivers/phy/qualcomm/phy-qcom-qmp.c static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) · line 873

Quoted 11 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +0 -0
  	"vdda-phy", "vdda-pll",
  };
  @@ -778,8 +869,8 @@ static inline void qphy_clrbits(void __iomem 

*base, u32 offset, u32 val)
.num_clks = ARRAY_SIZE(msm8996_phy_clk_l),
.reset_list = msm8996_pciephy_reset_l,
.num_resets = ARRAY_SIZE(msm8996_pciephy_reset_l),

drivers/phy/qualcomm/phy-qcom-qmp.c +2 -2
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),

So this changes and other vreg changes in cfg goes to the separate patch.

Quoted 23 lines

.regs = pciephy_regs_layout,
.start_ctrl = PCS_START | PLL_READY_GATE_EN,

drivers/phy/qualcomm/phy-qcom-qmp.c +4 -4
@@ -809,8 +900,8 @@ static inline void qphy_clrbits(void __iomem 
 *base, u32 offset, u32 val)
  	.num_clks		= ARRAY_SIZE(msm8996_phy_clk_l),
  	.reset_list		= msm8996_usb3phy_reset_l,
  	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
  	.regs			= usb3phy_regs_layout,
    	.start_ctrl		= SERDES_START | PCS_START,
@@ -870,8 +961,8 @@ static inline void qphy_clrbits(void __iomem 
 *base, u32 offset, u32 val)
  	.num_clks		= ARRAY_SIZE(qmp_v3_phy_clk_l),
  	.reset_list		= msm8996_usb3phy_reset_l,
  	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
  	.regs			= qmp_v3_usb3phy_regs_layout,
Quoted 9 lines

drivers/phy/qualcomm/phy-qcom-qmp.c static inline void qphy_clrbits(void __iomem · line 977

Quoted 6 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +1 -0
    	.start_ctrl		= SERDES_START | PCS_START,
@@ -883,6 +974,7 @@ static inline void qphy_clrbits(void __iomem 
 *base, u32 offset, u32 val)
  	.pwrdn_delay_max	= POWER_DOWN_DELAY_US_MAX,
    	.has_phy_dp_com_ctrl	= true,
+	.is_dual_lane_phy	= true,

This too goes to the new patch.

Shall do so

Quoted 69 lines
Quoted 69 lines
drivers/phy/qualcomm/phy-qcom-qmp.c +32 -2
  	.tx_b_lane_offset	= 0x400,
  	.rx_b_lane_offset	= 0x400,
  };
@@ -903,8 +995,8 @@ static inline void qphy_clrbits(void __iomem 
 *base, u32 offset, u32 val)
  	.num_clks		= ARRAY_SIZE(qmp_v3_phy_clk_l),
  	.reset_list		= msm8996_usb3phy_reset_l,
  	.num_resets		= ARRAY_SIZE(msm8996_usb3phy_reset_l),
-	.vreg_list		= msm8996_phy_vreg_l,
-	.num_vregs		= ARRAY_SIZE(msm8996_phy_vreg_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
  	.regs			= qmp_v3_usb3phy_regs_layout,
    	.start_ctrl		= SERDES_START | PCS_START,
@@ -916,6 +1008,35 @@ static inline void qphy_clrbits(void __iomem 
 *base, u32 offset, u32 val)
  	.pwrdn_delay_max	= POWER_DOWN_DELAY_US_MAX,
  };
  +static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
+	.type			= PHY_TYPE_UFS,
+	.nlanes			= 2,
+
+	.serdes_tbl		= sdm845_ufsphy_serdes_tbl,
+	.serdes_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_serdes_tbl),
+	.tx_tbl			= sdm845_ufsphy_tx_tbl,
+	.tx_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_tx_tbl),
+	.rx_tbl			= sdm845_ufsphy_rx_tbl,
+	.rx_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_rx_tbl),
+	.pcs_tbl		= sdm845_ufsphy_pcs_tbl,
+	.pcs_tbl_num		= ARRAY_SIZE(sdm845_ufsphy_pcs_tbl),
+	.clk_list		= sdm845_ufs_phy_clk_l,
+	.num_clks		= ARRAY_SIZE(sdm845_ufs_phy_clk_l),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+	.regs			= sdm845_ufsphy_regs_layout,
+
+	.start_ctrl		= SERDES_START,
+	.pwrdn_ctrl		= SW_PWRDN,
+	.mask_pcs_ready		= PCS_READY,
+
+	.is_dual_lane_phy	= true,
+	.tx_b_lane_offset	= 0x400,
+	.rx_b_lane_offset	= 0x400,
+
+	.no_pcs_sw_reset	= true,
+};
+
  static void qcom_qmp_phy_configure(void __iomem *base,
  				   const unsigned int *regs,
  				   const struct qmp_phy_init_tbl tbl[],
@@ -938,7 +1059,9 @@ static void qcom_qmp_phy_configure(void __iomem 
 *base,
  static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
  {
  	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	struct qmp_phy *qphy = qmp->phys[0];
  	void __iomem *serdes = qmp->serdes;
+	void __iomem *pcs = qphy->pcs;
  	void __iomem *dp_com = qmp->dp_com;
  	int ret, i;

@@ -1114,18 +1237,27 @@ static int qcom_qmp_phy_init(struct phy
*phy)
/* Tx, Rx, and PCS configurations */ qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl,
cfg->tx_tbl_num);
/* Configuration for other LANE for USB-DP combo PHY */

drivers/phy/qualcomm/phy-qcom-qmp.c +1 -1
-	if (cfg->has_phy_dp_com_ctrl)
+	if (cfg->is_dual_lane_phy)
  		qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs,
Quoted 9 lines

drivers/phy/qualcomm/phy-qcom-qmp.c

Quoted 5 lines
  				       cfg->tx_tbl, cfg->tx_tbl_num);
    	qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, 

cfg->rx_tbl_num);

drivers/phy/qualcomm/phy-qcom-qmp.c +1 -1
-	if (cfg->has_phy_dp_com_ctrl)
+	if (cfg->is_dual_lane_phy)

And these couple of changes too to the new patch. This helps in bisecting in the time of issue.

Right, shall do so

Quoted 148 lines
Quoted 148 lines

qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs,

  				       cfg->rx_tbl, cfg->rx_tbl_num);
    	qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, 
cfg->pcs_tbl_num);
    	/*
drivers/phy/qualcomm/phy-qcom-qmp.c +1 -0
+	 * UFS PHY requires the deassert of software reset before serdes 

start.

drivers/phy/qualcomm/phy-qcom-qmp.c +1 -0
+	 * For UFS PHY that has not software reset control bits in its 

address

drivers/phy/qualcomm/phy-qcom-qmp.c +47 -1
+	 * space, it should skip starting serdes here. UFS PHY Serdes shall
+	 * start when UFS explicitly calls PHY power on.
+	 */
+	if ((cfg->type == PHY_TYPE_UFS) && cfg->no_pcs_sw_reset)
+		goto out;
+
+	/*
  	 * Pull out PHY from POWER DOWN state.
  	 * This is active low enable signal to power-down PHY.
  	 */
@@ -1154,6 +1286,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
  	}
  	qmp->phy_initialized = true;
  +out:
  	return ret;
    err_pcs_ready:
@@ -1176,7 +1309,8 @@ static int qcom_qmp_phy_exit(struct phy *phy)
  	clk_disable_unprepare(qphy->pipe_clk);
    	/* PHY reset */
-	qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+	if (!cfg->no_pcs_sw_reset)
+		qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
    	/* stop SerDes and Phy-Coding-Sublayer */
  	qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], 
 cfg->start_ctrl);
@@ -1194,6 +1328,44 @@ static int qcom_qmp_phy_exit(struct phy *phy)
  	return 0;
  }
  +static int qcom_qmp_phy_poweron(struct phy *phy)
+{
+	struct qmp_phy *qphy = phy_get_drvdata(phy);
+	struct qcom_qmp *qmp = qphy->qmp;
+	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	void __iomem *pcs = qphy->pcs;
+	void __iomem *status;
+	unsigned int mask, val;
+	int ret = 0;
+
+	if (cfg->type != PHY_TYPE_UFS)
+		return 0;
+
+	/*
+	 * For UFS PHY that has not software reset control, serdes start
+	 * should only happen when UFS driver explicitly calls phy_power_on
+	 * after it deasserts software reset.
+	 */
+	if (cfg->no_pcs_sw_reset && !qmp->phy_initialized &&
+	    (qmp->init_count !=0)) {
+		/* start SerDes and Phy-Coding-Sublayer */
+		qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
+
+		status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
+		mask = cfg->mask_pcs_ready;
+
+		ret = readl_poll_timeout(status, val, !(val & mask), 1,
+					 PHY_INIT_COMPLETE_TIMEOUT);
+		if (ret) {
+			dev_err(qmp->dev, "phy initialization timed-out\n");
+			return ret;
+		}
+		qmp->phy_initialized = true;
+	}
+
+	return ret;
+}
+
  static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode 
 mode)
  {
  	struct qmp_phy *qphy = phy_get_drvdata(phy);
@@ -1423,6 +1595,7 @@ static int phy_pipe_clk_register(struct qcom_qmp 
 *qmp, struct device_node *np)
  static const struct phy_ops qcom_qmp_phy_gen_ops = {
  	.init		= qcom_qmp_phy_init,
  	.exit		= qcom_qmp_phy_exit,
+	.power_on	= qcom_qmp_phy_poweron,
  	.set_mode	= qcom_qmp_phy_set_mode,
  	.owner		= THIS_MODULE,
  };
drivers/phy/qualcomm/phy-qcom-qmp.c +3 -0
@@ -1528,6 +1701,9 @@ int qcom_qmp_phy_create(struct device *dev, 
 struct device_node *np, int id)
  	}, {
  		.compatible = "qcom,sdm845-qmp-usb3-uni-phy",
  		.data = &qmp_v3_usb3_uniphy_cfg,
+	}, {
+		.compatible = "qcom,sdm845-qmp-ufs-phy",
+		.data = &sdm845_ufsphy_cfg,
  	},
  	{ },
  };
drivers/phy/qualcomm/phy-qcom-qmp.h +15 -0
index 5d78d43..d201cc3 100644
@@ -184,6 +184,8 @@
  #define QSERDES_V3_COM_VCO_TUNE2_MODE0			0x0f8
  #define QSERDES_V3_COM_VCO_TUNE1_MODE1			0x0fc
  #define QSERDES_V3_COM_VCO_TUNE2_MODE1			0x100
+#define QSERDES_V3_COM_VCO_TUNE_INITVAL1		0x104
+#define QSERDES_V3_COM_VCO_TUNE_INITVAL2		0x108
  #define QSERDES_V3_COM_VCO_TUNE_TIMER1			0x11c
  #define QSERDES_V3_COM_VCO_TUNE_TIMER2			0x120
  #define QSERDES_V3_COM_CLK_SELECT			0x138
@@ -211,8 +213,13 @@
  /* Only for QMP V3 PHY - RX registers */
  #define QSERDES_V3_RX_UCDR_SO_GAIN_HALF			0x00c
  #define QSERDES_V3_RX_UCDR_SO_GAIN			0x014
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF		0x024
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER		0x028
+#define QSERDES_V3_RX_UCDR_SVS_SO_GAIN			0x02c
  #define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN		0x030
  #define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE	0x034
+#define QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW		0x03c
+#define QSERDES_V3_RX_UCDR_PI_CONTROLS			0x044
  #define QSERDES_V3_RX_RX_TERM_BW			0x07c
  #define QSERDES_V3_RX_VGA_CAL_CNTRL1			0x0bc
  #define QSERDES_V3_RX_VGA_CAL_CNTRL2			0x0c0
@@ -239,6 +246,8 @@
  #define QPHY_V3_PCS_TXMGN_V3				0x018
  #define QPHY_V3_PCS_TXMGN_V4				0x01c
  #define QPHY_V3_PCS_TXMGN_LS				0x020
+#define QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL		0x02c
+#define QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL		0x034
  #define QPHY_V3_PCS_TXDEEMPH_M6DB_V0			0x024
  #define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0			0x028
  #define QPHY_V3_PCS_TXDEEMPH_M6DB_V1			0x02c
@@ -275,6 +284,12 @@
  #define QPHY_V3_PCS_FLL_CNT_VAL_L			0x0cc
  #define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL			0x0d0
  #define QPHY_V3_PCS_FLL_MAN_CODE			0x0d4
+#define QPHY_V3_PCS_RX_SYM_RESYNC_CTRL			0x134
+#define QPHY_V3_PCS_RX_MIN_HIBERN8_TIME			0x138
+#define QPHY_V3_PCS_RX_SIGDET_CTRL1			0x13c
+#define QPHY_V3_PCS_RX_SIGDET_CTRL2			0x140
+#define QPHY_V3_PCS_TX_MID_TERM_CTRL1			0x1bc
+#define QPHY_V3_PCS_MULTI_LANE_CTRL1			0x1c4
  #define QPHY_V3_PCS_RX_SIGDET_LVL			0x1d8
  #define QPHY_V3_PCS_REFGEN_REQ_CONFIG1			0x20c
  #define QPHY_V3_PCS_REFGEN_REQ_CONFIG2			0x210
author
#9 lore raw

PATCH v6 3/3 dt-bindings: phy-qcom-qmp: Add UFS phy compatible string for sdm845

In reply to Can Guo

Update the compatible string for UFS QMP PHY on SDM845.

---
 Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt +3 -1
index cef8765..930d94c 100644
@@ -11,7 +11,8 @@ Required properties:
 	       "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996,
 	       "qcom,qmp-v3-usb3-phy" for USB3 QMP V3 phy,
 	       "qcom,sdm845-qmp-usb3-phy" for USB3 QMP V3 phy on sdm845,
-	       "qcom,sdm845-qmp-usb3-uni-phy" for USB3 QMP V3 UNI phy on sdm845.
+	       "qcom,sdm845-qmp-usb3-uni-phy" for USB3 QMP V3 UNI phy on sdm845,
+	       "qcom,sdm845-qmp-ufs-phy" for UFS QMP phy on sdm845.
 
  - reg: offset and length of register set for PHY's common serdes block.
 
@@ -29,6 +30,7 @@ Required properties:
 		"aux" for phy aux clock,
 		"ref" for 19.2 MHz ref clk,
 		"com_aux" for phy common block aux clock,
+		"ref_aux" for phy reference aux clock,
 		For "qcom,msm8996-qmp-pcie-phy" must contain:
 			"aux", "cfg_ahb", "ref".
 		For "qcom,msm8996-qmp-usb3-phy" must contain:
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project