2021-03-28 20:55:27

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 0/7] phy: qcom-qmp: provide DP phy support for sm8250

Changes since v4:
- Fix typo in the qcom,sc7180-qmp-usb3-phy name in the first patch

Changes since v3:
- Move qcom,sc7180-qmp-usb3-phy and qcom,sdm845-qmp-usb3-phy from
qcom,qmp-usb3-dp.yaml to qcom,qmp-phy.yaml
- Do not touch qcom,sm8250-qmp-usb3-phy compatible

Changes since v2:
- Drop unused qmp_v4_usb3_rx_tbl

Changes since v1:
- Provide dt bindings
- Split register renaming from sm8250-dp-phy patch
- Add respective changes to sm8250 device tree

The following changes since commit a38fd8748464831584a19438cbb3082b5a2dab15:

Linux 5.12-rc2 (2021-03-05 17:33:41 -0800)

are available in the Git repository at:

https://git.linaro.org/people/dmitry.baryshkov/kernel.git sm8250-dp-phy

for you to fetch changes up to aef044832f8f34495c35f8324ee55e2500dc3db5:

arm64: dts: qcom: use dp_phy to provide clocks to dispcc (2021-03-28 23:43:31 +0300)

----------------------------------------------------------------
Dmitry Baryshkov (7):
dt-bindings: phy: qcom,qmp-usb3-dp-phy: move usb3 compatibles back to qcom,qmp-phy.yaml
dt-bindings: phy: qcom,qmp-usb3-dp: Add support for SM8250
phy: qcom-qmp: move DP functions to callbacks
phy: qcom-qmp: rename common registers
phy: qcom-qmp: add support for sm8250-usb3-dp phy
arm64: dts: qcom: sm8250: switch usb1 qmp phy to USB3+DP mode
arm64: dts: qcom: use dp_phy to provide clocks to dispcc

.../devicetree/bindings/phy/qcom,qmp-phy.yaml | 2 +
.../bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 3 +-
arch/arm64/boot/dts/qcom/sm8250.dtsi | 31 +-
drivers/phy/qualcomm/phy-qcom-qmp.c | 850 +++++++++++++++------
drivers/phy/qualcomm/phy-qcom-qmp.h | 77 +-
5 files changed, 693 insertions(+), 270 deletions(-)



2021-03-28 20:58:44

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 2/7] dt-bindings: phy: qcom,qmp-usb3-dp: Add support for SM8250

Add compatible for SM8250 in QMP USB3 DP PHY bindings.

Signed-off-by: Dmitry Baryshkov <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
index 62c0179d1765..217aa6c91893 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
@@ -15,6 +15,7 @@ properties:
enum:
- qcom,sc7180-qmp-usb3-dp-phy
- qcom,sdm845-qmp-usb3-dp-phy
+ - qcom,sm8250-qmp-usb3-dp-phy
reg:
items:
- description: Address and length of PHY's USB serdes block.
--
2.30.2

2021-03-28 20:59:43

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 4/7] phy: qcom-qmp: rename common registers

A plenty of DP PHY registers are common between V3 and V4. To simplify
V4 code, rename all common registers.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 50 ++++++++++++++---------------
drivers/phy/qualcomm/phy-qcom-qmp.h | 37 ++++++++++-----------
2 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 4150096fd350..097bc005ba43 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -2435,20 +2435,20 @@ static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy)
{
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
- qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+ qphy->pcs + QSERDES_DP_PHY_PD_CTL);

/* Turn on BIAS current for PHY/PLL */
writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX |
QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL,
qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);

- writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL);

writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_LANE_0_1_PWRDN |
DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN |
DP_PHY_PD_CTL_DP_CLAMP_EN,
- qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+ qphy->pcs + QSERDES_DP_PHY_PD_CTL);

writel(QSERDES_V3_COM_BIAS_EN |
QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN |
@@ -2456,16 +2456,16 @@ static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy)
QSERDES_V3_COM_CLKBUF_RX_DRIVE_L,
qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);

- writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0);
- writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
- writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
- writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3);
- writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4);
- writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5);
- writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6);
- writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7);
- writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8);
- writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9);
+ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0);
+ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
+ writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
+ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3);
+ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4);
+ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5);
+ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6);
+ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7);
+ writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8);
+ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9);
qphy->dp_aux_cfg = 0;

writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
@@ -2556,9 +2556,9 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
* writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
*/
val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
- writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+ writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL);

- writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
+ writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE);
writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);

@@ -2588,11 +2588,11 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);

- writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
- writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
- writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
- writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
- writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
+ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
+ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG);
+ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
+ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG);

writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL);

@@ -2603,7 +2603,7 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
10000))
return -ETIMEDOUT;

- writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);

if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
status,
@@ -2612,9 +2612,9 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
10000))
return -ETIMEDOUT;

- writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG);
udelay(2000);
- writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);

return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
status,
@@ -2636,7 +2636,7 @@ static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy)
qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
val = cfg1_settings[qphy->dp_aux_cfg];

- writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
+ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);

return 0;
}
@@ -3898,7 +3898,7 @@ static int qcom_qmp_phy_power_off(struct phy *phy)

if (cfg->type == PHY_TYPE_DP) {
/* Assert DP PHY power down */
- writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL);
} else {
/* PHY reset */
if (!cfg->no_pcs_sw_reset)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index 71ce3aa174ae..981d8ee891c0 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -349,13 +349,13 @@
#define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4 0x5c
#define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5 0x60

-/* Only for QMP V3 PHY - DP PHY registers */
-#define QSERDES_V3_DP_PHY_REVISION_ID0 0x000
-#define QSERDES_V3_DP_PHY_REVISION_ID1 0x004
-#define QSERDES_V3_DP_PHY_REVISION_ID2 0x008
-#define QSERDES_V3_DP_PHY_REVISION_ID3 0x00c
-#define QSERDES_V3_DP_PHY_CFG 0x010
-#define QSERDES_V3_DP_PHY_PD_CTL 0x018
+/* QMP PHY - DP PHY registers */
+#define QSERDES_DP_PHY_REVISION_ID0 0x000
+#define QSERDES_DP_PHY_REVISION_ID1 0x004
+#define QSERDES_DP_PHY_REVISION_ID2 0x008
+#define QSERDES_DP_PHY_REVISION_ID3 0x00c
+#define QSERDES_DP_PHY_CFG 0x010
+#define QSERDES_DP_PHY_PD_CTL 0x018
# define DP_PHY_PD_CTL_PWRDN 0x001
# define DP_PHY_PD_CTL_PSR_PWRDN 0x002
# define DP_PHY_PD_CTL_AUX_PWRDN 0x004
@@ -363,18 +363,19 @@
# define DP_PHY_PD_CTL_LANE_2_3_PWRDN 0x010
# define DP_PHY_PD_CTL_PLL_PWRDN 0x020
# define DP_PHY_PD_CTL_DP_CLAMP_EN 0x040
-#define QSERDES_V3_DP_PHY_MODE 0x01c
-#define QSERDES_V3_DP_PHY_AUX_CFG0 0x020
-#define QSERDES_V3_DP_PHY_AUX_CFG1 0x024
-#define QSERDES_V3_DP_PHY_AUX_CFG2 0x028
-#define QSERDES_V3_DP_PHY_AUX_CFG3 0x02c
-#define QSERDES_V3_DP_PHY_AUX_CFG4 0x030
-#define QSERDES_V3_DP_PHY_AUX_CFG5 0x034
-#define QSERDES_V3_DP_PHY_AUX_CFG6 0x038
-#define QSERDES_V3_DP_PHY_AUX_CFG7 0x03c
-#define QSERDES_V3_DP_PHY_AUX_CFG8 0x040
-#define QSERDES_V3_DP_PHY_AUX_CFG9 0x044
+#define QSERDES_DP_PHY_MODE 0x01c
+#define QSERDES_DP_PHY_AUX_CFG0 0x020
+#define QSERDES_DP_PHY_AUX_CFG1 0x024
+#define QSERDES_DP_PHY_AUX_CFG2 0x028
+#define QSERDES_DP_PHY_AUX_CFG3 0x02c
+#define QSERDES_DP_PHY_AUX_CFG4 0x030
+#define QSERDES_DP_PHY_AUX_CFG5 0x034
+#define QSERDES_DP_PHY_AUX_CFG6 0x038
+#define QSERDES_DP_PHY_AUX_CFG7 0x03c
+#define QSERDES_DP_PHY_AUX_CFG8 0x040
+#define QSERDES_DP_PHY_AUX_CFG9 0x044

+/* Only for QMP V3 PHY - DP PHY registers */
#define QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK 0x048
# define PHY_AUX_STOP_ERR_MASK 0x01
# define PHY_AUX_DEC_ERR_MASK 0x02
--
2.30.2

2021-03-28 21:00:19

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 1/7] dt-bindings: phy: qcom,qmp-usb3-dp-phy: move usb3 compatibles back to qcom,qmp-phy.yaml

The commit 724fabf5df13 ("dt-bindings: phy: qcom,qmp-usb3-dp: Add DP phy
information") has support for DP part of USB3+DP combo PHYs. However
this change is not backwards compatible, placing additional requirements
onto qcom,sc7180-qmp-usb3-phy and qcom,sdm845-qmp-usb3-phy device nodes
(to include separate DP part, etc). However the aforementioned nodes do
not inclue DP part, they strictly follow the schema defined in the
qcom,qmp-phy.yaml file. Move those compatibles, leaving
qcom,qmp-usb3-dp-phy.yaml to describe only real "combo" USB3+DP device nodes.

Fixes: 724fabf5df13 ("dt-bindings: phy: qcom,qmp-usb3-dp: Add DP phy information")
Cc: Stephen Boyd <[email protected]>
Cc: Sandeep Maheswaram <[email protected]>
Signed-off-by: Dmitry Baryshkov <[email protected]>
Acked-by: Rob Herring <[email protected]>
Reviewed-by: Stephen Boyd <[email protected]>
---
Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml | 2 ++
Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 2 --
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
index 626447fee092..7808ec8bc712 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
@@ -25,11 +25,13 @@ properties:
- qcom,msm8998-qmp-pcie-phy
- qcom,msm8998-qmp-ufs-phy
- qcom,msm8998-qmp-usb3-phy
+ - qcom,sc7180-qmp-usb3-phy
- qcom,sc8180x-qmp-ufs-phy
- qcom,sc8180x-qmp-usb3-phy
- qcom,sdm845-qhp-pcie-phy
- qcom,sdm845-qmp-pcie-phy
- qcom,sdm845-qmp-ufs-phy
+ - qcom,sdm845-qmp-usb3-phy
- qcom,sdm845-qmp-usb3-uni-phy
- qcom,sm8150-qmp-ufs-phy
- qcom,sm8150-qmp-usb3-phy
diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
index 33974ad10afe..62c0179d1765 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
@@ -14,9 +14,7 @@ properties:
compatible:
enum:
- qcom,sc7180-qmp-usb3-dp-phy
- - qcom,sc7180-qmp-usb3-phy
- qcom,sdm845-qmp-usb3-dp-phy
- - qcom,sdm845-qmp-usb3-phy
reg:
items:
- description: Address and length of PHY's USB serdes block.
--
2.30.2

2021-03-28 21:01:49

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 3/7] phy: qcom-qmp: move DP functions to callbacks

In preparation to adding support for V4 DP PHY move DP functions to
callbacks at struct qmp_phy_cfg.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 438 +++++++++++++++-------------
1 file changed, 231 insertions(+), 207 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 9cdebe7f26cb..4150096fd350 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -2268,6 +2268,8 @@ static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
};

+struct qmp_phy;
+
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
/* phy-type - PCIE/UFS/USB */
@@ -2307,6 +2309,12 @@ struct qmp_phy_cfg {
const struct qmp_phy_init_tbl *serdes_tbl_hbr3;
int serdes_tbl_hbr3_num;

+ /* DP PHY callbacks */
+ int (*configure_dp_phy)(struct qmp_phy *qphy);
+ void (*configure_dp_tx)(struct qmp_phy *qphy);
+ int (*calibrate_dp_phy)(struct qmp_phy *qphy);
+ void (*dp_aux_init)(struct qmp_phy *qphy);
+
/* clock ids to be requested */
const char * const *clk_list;
int num_clks;
@@ -2423,6 +2431,216 @@ struct qcom_qmp {
struct reset_control *ufs_reset;
};

+static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy)
+{
+ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
+ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
+ qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+
+ /* Turn on BIAS current for PHY/PLL */
+ writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX |
+ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL,
+ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
+
+ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+
+ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
+ DP_PHY_PD_CTL_LANE_0_1_PWRDN |
+ DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN |
+ DP_PHY_PD_CTL_DP_CLAMP_EN,
+ qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+
+ writel(QSERDES_V3_COM_BIAS_EN |
+ QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN |
+ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL |
+ QSERDES_V3_COM_CLKBUF_RX_DRIVE_L,
+ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
+
+ writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0);
+ writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
+ writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
+ writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3);
+ writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4);
+ writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5);
+ writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6);
+ writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7);
+ writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8);
+ writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9);
+ qphy->dp_aux_cfg = 0;
+
+ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
+ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
+ PHY_AUX_REQ_ERR_MASK,
+ qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK);
+}
+
+static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = {
+ { 0x00, 0x0c, 0x14, 0x19 },
+ { 0x00, 0x0b, 0x12, 0xff },
+ { 0x00, 0x0b, 0xff, 0xff },
+ { 0x04, 0xff, 0xff, 0xff }
+};
+
+static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = {
+ { 0x08, 0x0f, 0x16, 0x1f },
+ { 0x11, 0x1e, 0x1f, 0xff },
+ { 0x19, 0x1f, 0xff, 0xff },
+ { 0x1f, 0xff, 0xff, 0xff }
+};
+
+static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
+{
+ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
+ unsigned int v_level = 0, p_level = 0;
+ u32 bias_en, drvr_en;
+ u8 voltage_swing_cfg, pre_emphasis_cfg;
+ int i;
+
+ for (i = 0; i < dp_opts->lanes; i++) {
+ v_level = max(v_level, dp_opts->voltage[i]);
+ p_level = max(p_level, dp_opts->pre[i]);
+ }
+
+ if (dp_opts->lanes == 1) {
+ bias_en = 0x3e;
+ drvr_en = 0x13;
+ } else {
+ bias_en = 0x3f;
+ drvr_en = 0x10;
+ }
+
+ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level];
+ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level];
+
+ /* TODO: Move check to config check */
+ if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF)
+ return;
+
+ /* Enable MUX to use Cursor values from these registers */
+ voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN;
+ pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN;
+
+ writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL);
+ writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL);
+ writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL);
+ writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL);
+
+ writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN);
+ writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
+ writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN);
+ writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
+}
+
+static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
+{
+ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
+ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
+ u32 val, phy_vco_div, status;
+ unsigned long pixel_freq;
+
+ val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
+ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
+
+ /*
+ * TODO: Assume orientation is CC1 for now and two lanes, need to
+ * use type-c connector to understand orientation and lanes.
+ *
+ * Otherwise val changes to be like below if this code understood
+ * the orientation of the type-c cable.
+ *
+ * if (lane_cnt == 4 || orientation == ORIENTATION_CC2)
+ * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
+ * if (lane_cnt == 4 || orientation == ORIENTATION_CC1)
+ * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
+ * if (orientation == ORIENTATION_CC2)
+ * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
+ */
+ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
+ writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
+
+ writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
+ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
+ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);
+
+ switch (dp_opts->link_rate) {
+ case 1620:
+ phy_vco_div = 0x1;
+ pixel_freq = 1620000000UL / 2;
+ break;
+ case 2700:
+ phy_vco_div = 0x1;
+ pixel_freq = 2700000000UL / 2;
+ break;
+ case 5400:
+ phy_vco_div = 0x2;
+ pixel_freq = 5400000000UL / 4;
+ break;
+ case 8100:
+ phy_vco_div = 0x0;
+ pixel_freq = 8100000000UL / 6;
+ break;
+ default:
+ /* Other link rates aren't supported */
+ return -EINVAL;
+ }
+ writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV);
+
+ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
+ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
+
+ writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
+ writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+
+ writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL);
+
+ if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS,
+ status,
+ ((status & BIT(0)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+
+ if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
+ status,
+ ((status & BIT(1)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+ udelay(2000);
+ writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
+
+ return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
+ status,
+ ((status & BIT(1)) > 0),
+ 500,
+ 10000);
+}
+
+/*
+ * We need to calibrate the aux setting here as many times
+ * as the caller tries
+ */
+static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy)
+{
+ static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d };
+ u8 val;
+
+ qphy->dp_aux_cfg++;
+ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
+ val = cfg1_settings[qphy->dp_aux_cfg];
+
+ writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
+
+ return 0;
+}
+
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
{
u32 reg;
@@ -2871,6 +3089,11 @@ static const struct qmp_phy_cfg sc7180_dpphy_cfg = {

.has_phy_dp_com_ctrl = true,
.is_dual_lane_phy = true,
+
+ .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init,
+ .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx,
+ .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy,
+ .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate,
};

static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = {
@@ -3332,227 +3555,28 @@ static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy)
return 0;
}

-static void qcom_qmp_phy_dp_aux_init(struct qmp_phy *qphy)
-{
- writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
- DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
- qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
-
- /* Turn on BIAS current for PHY/PLL */
- writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX |
- QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL,
- qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
-
- writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
-
- writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
- DP_PHY_PD_CTL_LANE_0_1_PWRDN |
- DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN |
- DP_PHY_PD_CTL_DP_CLAMP_EN,
- qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
-
- writel(QSERDES_V3_COM_BIAS_EN |
- QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN |
- QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL |
- QSERDES_V3_COM_CLKBUF_RX_DRIVE_L,
- qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
-
- writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0);
- writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
- writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
- writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3);
- writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4);
- writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5);
- writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6);
- writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7);
- writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8);
- writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9);
- qphy->dp_aux_cfg = 0;
-
- writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
- PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
- PHY_AUX_REQ_ERR_MASK,
- qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK);
-}
-
-static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = {
- { 0x00, 0x0c, 0x14, 0x19 },
- { 0x00, 0x0b, 0x12, 0xff },
- { 0x00, 0x0b, 0xff, 0xff },
- { 0x04, 0xff, 0xff, 0xff }
-};
-
-static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = {
- { 0x08, 0x0f, 0x16, 0x1f },
- { 0x11, 0x1e, 0x1f, 0xff },
- { 0x19, 0x1f, 0xff, 0xff },
- { 0x1f, 0xff, 0xff, 0xff }
-};
-
-static void qcom_qmp_phy_configure_dp_tx(struct qmp_phy *qphy)
-{
- const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
- unsigned int v_level = 0, p_level = 0;
- u32 bias_en, drvr_en;
- u8 voltage_swing_cfg, pre_emphasis_cfg;
- int i;
-
- for (i = 0; i < dp_opts->lanes; i++) {
- v_level = max(v_level, dp_opts->voltage[i]);
- p_level = max(p_level, dp_opts->pre[i]);
- }
-
- if (dp_opts->lanes == 1) {
- bias_en = 0x3e;
- drvr_en = 0x13;
- } else {
- bias_en = 0x3f;
- drvr_en = 0x10;
- }
-
- voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level];
- pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level];
-
- /* TODO: Move check to config check */
- if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF)
- return;
-
- /* Enable MUX to use Cursor values from these registers */
- voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN;
- pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN;
-
- writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL);
- writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL);
- writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL);
- writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL);
-
- writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN);
- writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
- writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN);
- writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
-}
-
static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
{
const struct phy_configure_opts_dp *dp_opts = &opts->dp;
struct qmp_phy *qphy = phy_get_drvdata(phy);
+ const struct qmp_phy_cfg *cfg = qphy->cfg;

memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts));
if (qphy->dp_opts.set_voltages) {
- qcom_qmp_phy_configure_dp_tx(qphy);
+ cfg->configure_dp_tx(qphy);
qphy->dp_opts.set_voltages = 0;
}

return 0;
}

-static int qcom_qmp_phy_configure_dp_phy(struct qmp_phy *qphy)
-{
- const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
- const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
- u32 val, phy_vco_div, status;
- unsigned long pixel_freq;
-
- val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
- DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
-
- /*
- * TODO: Assume orientation is CC1 for now and two lanes, need to
- * use type-c connector to understand orientation and lanes.
- *
- * Otherwise val changes to be like below if this code understood
- * the orientation of the type-c cable.
- *
- * if (lane_cnt == 4 || orientation == ORIENTATION_CC2)
- * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
- * if (lane_cnt == 4 || orientation == ORIENTATION_CC1)
- * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
- * if (orientation == ORIENTATION_CC2)
- * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
- */
- val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
- writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
-
- writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
- writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
- writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);
-
- switch (dp_opts->link_rate) {
- case 1620:
- phy_vco_div = 0x1;
- pixel_freq = 1620000000UL / 2;
- break;
- case 2700:
- phy_vco_div = 0x1;
- pixel_freq = 2700000000UL / 2;
- break;
- case 5400:
- phy_vco_div = 0x2;
- pixel_freq = 5400000000UL / 4;
- break;
- case 8100:
- phy_vco_div = 0x0;
- pixel_freq = 8100000000UL / 6;
- break;
- default:
- /* Other link rates aren't supported */
- return -EINVAL;
- }
- writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV);
-
- clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
- clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
-
- writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
- writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
- writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
- writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
- writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
-
- writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL);
-
- if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS,
- status,
- ((status & BIT(0)) > 0),
- 500,
- 10000))
- return -ETIMEDOUT;
-
- writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
-
- if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
- status,
- ((status & BIT(1)) > 0),
- 500,
- 10000))
- return -ETIMEDOUT;
-
- writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
- udelay(2000);
- writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
-
- return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
- status,
- ((status & BIT(1)) > 0),
- 500,
- 10000);
-}
-
-/*
- * We need to calibrate the aux setting here as many times
- * as the caller tries
- */
static int qcom_qmp_dp_phy_calibrate(struct phy *phy)
{
struct qmp_phy *qphy = phy_get_drvdata(phy);
- static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d };
- u8 val;
-
- qphy->dp_aux_cfg++;
- qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
- val = cfg1_settings[qphy->dp_aux_cfg];
+ const struct qmp_phy_cfg *cfg = qphy->cfg;

- writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
+ if (cfg->calibrate_dp_phy)
+ return cfg->calibrate_dp_phy(qphy);

return 0;
}
@@ -3729,7 +3753,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
return ret;

if (cfg->type == PHY_TYPE_DP)
- qcom_qmp_phy_dp_aux_init(qphy);
+ cfg->dp_aux_init(qphy);

return 0;
}
@@ -3783,7 +3807,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy)

/* Configure special DP tx tunings */
if (cfg->type == PHY_TYPE_DP)
- qcom_qmp_phy_configure_dp_tx(qphy);
+ cfg->configure_dp_tx(qphy);

qcom_qmp_phy_configure_lane(rx, cfg->regs,
cfg->rx_tbl, cfg->rx_tbl_num, 1);
@@ -3802,7 +3826,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy)

/* Configure link rate, swing, etc. */
if (cfg->type == PHY_TYPE_DP) {
- qcom_qmp_phy_configure_dp_phy(qphy);
+ cfg->configure_dp_phy(qphy);
} else {
qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
if (cfg->pcs_tbl_sec)
--
2.30.2

2021-03-28 21:02:34

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 6/7] arm64: dts: qcom: sm8250: switch usb1 qmp phy to USB3+DP mode

USB1 QMP PHY is not just a USB3 PHY, but USB3+DP PHY. Change device tree
nodes accordingly.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
arch/arm64/boot/dts/qcom/sm8250.dtsi | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index 947e1accae3a..0f79e6885004 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -2097,12 +2097,11 @@ usb_2_hsphy: phy@88e4000 {
};

usb_1_qmpphy: phy@88e9000 {
- compatible = "qcom,sm8250-qmp-usb3-phy";
+ compatible = "qcom,sm8250-qmp-usb3-dp-phy";
reg = <0 0x088e9000 0 0x200>,
- <0 0x088e8000 0 0x20>;
- reg-names = "reg-base", "dp_com";
+ <0 0x088e8000 0 0x40>,
+ <0 0x088ea000 0 0x200>;
status = "disabled";
- #clock-cells = <1>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
@@ -2116,7 +2115,7 @@ usb_1_qmpphy: phy@88e9000 {
<&gcc GCC_USB3_PHY_PRIM_BCR>;
reset-names = "phy", "common";

- usb_1_ssphy: lanes@88e9200 {
+ usb_1_ssphy: usb3-phy@88e9200 {
reg = <0 0x088e9200 0 0x200>,
<0 0x088e9400 0 0x200>,
<0 0x088e9c00 0 0x400>,
@@ -2128,6 +2127,20 @@ usb_1_ssphy: lanes@88e9200 {
clock-names = "pipe0";
clock-output-names = "usb3_phy_pipe_clk_src";
};
+
+ dp_phy: dp-phy@88ea200 {
+ reg = <0 0x088ea200 0 0x200>,
+ <0 0x088ea400 0 0x200>,
+ <0 0x088eac00 0 0x400>,
+ <0 0x088ea600 0 0x200>,
+ <0 0x088ea800 0 0x200>,
+ <0 0x088eaa00 0 0x100>;
+ #phy-cells = <0>;
+ #clock-cells = <1>;
+ clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+ clock-names = "pipe0";
+ clock-output-names = "usb3_phy_pipe_clk_src";
+ };
};

usb_2_qmpphy: phy@88eb000 {
--
2.30.2

2021-03-28 21:02:49

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 5/7] phy: qcom-qmp: add support for sm8250-usb3-dp phy

Add support for QMP V4 Combo USB3+DP PHY (for SM8250 platform).

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 388 ++++++++++++++++++++++++++--
drivers/phy/qualcomm/phy-qcom-qmp.h | 40 ++-
2 files changed, 406 insertions(+), 22 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 097bc005ba43..a47da2fff7a1 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -1840,6 +1840,86 @@ static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
};

+static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f),
+};
+
+static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04),
+};
+
+static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08),
+};
+
+static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08),
+};
+
+static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08),
+};
+
+static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20),
+};
+
static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
@@ -2488,11 +2568,10 @@ static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = {
{ 0x1f, 0xff, 0xff, 0xff }
};

-static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
+static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, unsigned int drv_lvl, unsigned int emp_post)
{
const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
unsigned int v_level = 0, p_level = 0;
- u32 bias_en, drvr_en;
u8 voltage_swing_cfg, pre_emphasis_cfg;
int i;

@@ -2501,29 +2580,42 @@ static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
p_level = max(p_level, dp_opts->pre[i]);
}

- if (dp_opts->lanes == 1) {
- bias_en = 0x3e;
- drvr_en = 0x13;
- } else {
- bias_en = 0x3f;
- drvr_en = 0x10;
- }
-
voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level];
pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level];

/* TODO: Move check to config check */
if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF)
- return;
+ return -EINVAL;

/* Enable MUX to use Cursor values from these registers */
voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN;
pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN;

- writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL);
- writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL);
- writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL);
- writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL);
+ writel(voltage_swing_cfg, qphy->tx + drv_lvl);
+ writel(pre_emphasis_cfg, qphy->tx + emp_post);
+ writel(voltage_swing_cfg, qphy->tx2 + drv_lvl);
+ writel(pre_emphasis_cfg, qphy->tx2 + emp_post);
+
+ return 0;
+}
+
+static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
+{
+ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
+ u32 bias_en, drvr_en;
+
+ if (qcom_qmp_phy_configure_dp_swing(qphy,
+ QSERDES_V3_TX_TX_DRV_LVL,
+ QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0)
+ return;
+
+ if (dp_opts->lanes == 1) {
+ bias_en = 0x3e;
+ drvr_en = 0x13;
+ } else {
+ bias_en = 0x3f;
+ drvr_en = 0x10;
+ }

writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN);
writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
@@ -2531,12 +2623,10 @@ static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
}

-static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
+static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy)
{
- const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
- const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
- u32 val, phy_vco_div, status;
- unsigned long pixel_freq;
+ u32 val;
+ bool reverse = false;

val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
@@ -2559,6 +2649,19 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL);

writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE);
+
+ return reverse;
+}
+
+static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
+{
+ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
+ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
+ u32 phy_vco_div, status;
+ unsigned long pixel_freq;
+
+ qcom_qmp_phy_configure_dp_mode(qphy);
+
writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);

@@ -2641,6 +2744,204 @@ static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy)
return 0;
}

+static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy)
+{
+ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
+ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
+ qphy->pcs + QSERDES_DP_PHY_PD_CTL);
+
+ /* Turn on BIAS current for PHY/PLL */
+ writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
+
+ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0);
+ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
+ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
+ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3);
+ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4);
+ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5);
+ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6);
+ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7);
+ writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8);
+ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9);
+ qphy->dp_aux_cfg = 0;
+
+ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
+ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
+ PHY_AUX_REQ_ERR_MASK,
+ qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK);
+}
+
+static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy)
+{
+ /* Program default values before writing proper values */
+ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL);
+ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL);
+
+ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL);
+ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL);
+
+ qcom_qmp_phy_configure_dp_swing(qphy,
+ QSERDES_V4_TX_TX_DRV_LVL,
+ QSERDES_V4_TX_TX_EMP_POST1_LVL);
+}
+
+static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy)
+{
+ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
+ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
+ u32 phy_vco_div, status;
+ unsigned long pixel_freq;
+ u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
+ bool reverse;
+
+ writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1);
+
+ reverse = qcom_qmp_phy_configure_dp_mode(qphy);
+
+ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
+ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
+
+ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL);
+ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL);
+
+ switch (dp_opts->link_rate) {
+ case 1620:
+ phy_vco_div = 0x1;
+ pixel_freq = 1620000000UL / 2;
+ break;
+ case 2700:
+ phy_vco_div = 0x1;
+ pixel_freq = 2700000000UL / 2;
+ break;
+ case 5400:
+ phy_vco_div = 0x2;
+ pixel_freq = 5400000000UL / 4;
+ break;
+ case 8100:
+ phy_vco_div = 0x0;
+ pixel_freq = 8100000000UL / 6;
+ break;
+ default:
+ /* Other link rates aren't supported */
+ return -EINVAL;
+ }
+ writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV);
+
+ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
+ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
+
+ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
+ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG);
+ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
+ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG);
+
+ writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL);
+
+ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS,
+ status,
+ ((status & BIT(0)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS,
+ status,
+ ((status & BIT(0)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS,
+ status,
+ ((status & BIT(1)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
+
+ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
+ status,
+ ((status & BIT(0)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
+ status,
+ ((status & BIT(1)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ /*
+ * At least for 7nm DP PHY this has to be done after enabling link
+ * clock.
+ */
+
+ if (dp_opts->lanes == 1) {
+ bias0_en = reverse ? 0x3e : 0x15;
+ bias1_en = reverse ? 0x15 : 0x3e;
+ drvr0_en = reverse ? 0x13 : 0x10;
+ drvr1_en = reverse ? 0x10 : 0x13;
+ } else if (dp_opts->lanes == 2) {
+ bias0_en = reverse ? 0x3f : 0x15;
+ bias1_en = reverse ? 0x15 : 0x3f;
+ drvr0_en = 0x10;
+ drvr1_en = 0x10;
+ } else {
+ bias0_en = 0x3f;
+ bias1_en = 0x3f;
+ drvr0_en = 0x10;
+ drvr1_en = 0x10;
+ }
+
+ writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN);
+ writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN);
+ writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN);
+ writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN);
+
+ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG);
+ udelay(2000);
+ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
+
+ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
+ status,
+ ((status & BIT(1)) > 0),
+ 500,
+ 10000))
+ return -ETIMEDOUT;
+
+ writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV);
+ writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV);
+
+ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL);
+ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL);
+
+ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL);
+ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL);
+
+ return 0;
+}
+
+/*
+ * We need to calibrate the aux setting here as many times
+ * as the caller tries
+ */
+static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy)
+{
+ static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d };
+ u8 val;
+
+ qphy->dp_aux_cfg++;
+ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
+ val = cfg1_settings[qphy->dp_aux_cfg];
+
+ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
+
+ return 0;
+}
+
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
{
u32 reg;
@@ -3346,6 +3647,46 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
.pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
};

+static const struct qmp_phy_cfg sm8250_dpphy_cfg = {
+ .type = PHY_TYPE_DP,
+ .nlanes = 1,
+
+ .serdes_tbl = qmp_v4_dp_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl),
+ .tx_tbl = qmp_v4_dp_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl),
+
+ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr,
+ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr),
+ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr,
+ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr),
+ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2,
+ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2),
+ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3,
+ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3),
+
+ .clk_list = qmp_v4_phy_clk_l,
+ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l),
+ .reset_list = msm8996_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v4_usb3phy_regs_layout,
+
+ .has_phy_dp_com_ctrl = true,
+ .is_dual_lane_phy = true,
+
+ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init,
+ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx,
+ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy,
+ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate,
+};
+
+static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = {
+ .usb_cfg = &sm8250_usb3phy_cfg,
+ .dp_cfg = &sm8250_dpphy_cfg,
+};
+
static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
.type = PHY_TYPE_USB3,
.nlanes = 1,
@@ -4601,6 +4942,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, {
.compatible = "qcom,sm8250-qmp-usb3-phy",
.data = &sm8250_usb3phy_cfg,
+ }, {
+ .compatible = "qcom,sm8250-qmp-usb3-dp-phy",
+ /* It's a combo phy */
}, {
.compatible = "qcom,sm8250-qmp-usb3-uni-phy",
.data = &sm8250_usb3_uniphy_cfg,
@@ -4635,6 +4979,10 @@ static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = {
.compatible = "qcom,sc7180-qmp-usb3-dp-phy",
.data = &sc7180_usb3dpphy_cfg,
},
+ {
+ .compatible = "qcom,sm8250-qmp-usb3-dp-phy",
+ .data = &sm8250_usb3dpphy_cfg,
+ },
{ }
};

diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index 981d8ee891c0..67bd2dd0d8c5 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -397,6 +397,7 @@
#define QSERDES_V3_DP_PHY_STATUS 0x0c0

/* Only for QMP V4 PHY - QSERDES COM registers */
+#define QSERDES_V4_COM_BG_TIMER 0x00c
#define QSERDES_V4_COM_SSC_EN_CENTER 0x010
#define QSERDES_V4_COM_SSC_PER1 0x01c
#define QSERDES_V4_COM_SSC_PER2 0x020
@@ -404,7 +405,9 @@
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0 0x028
#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1 0x030
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1 0x034
+#define QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN 0x044
#define QSERDES_V4_COM_CLK_ENABLE1 0x048
+#define QSERDES_V4_COM_SYS_CLK_CTRL 0x04c
#define QSERDES_V4_COM_SYSCLK_BUF_ENABLE 0x050
#define QSERDES_V4_COM_PLL_IVCO 0x058
#define QSERDES_V4_COM_CMN_IPTRIM 0x060
@@ -415,6 +418,7 @@
#define QSERDES_V4_COM_PLL_CCTRL_MODE0 0x084
#define QSERDES_V4_COM_PLL_CCTRL_MODE1 0x088
#define QSERDES_V4_COM_SYSCLK_EN_SEL 0x094
+#define QSERDES_V4_COM_RESETSM_CNTRL 0x09c
#define QSERDES_V4_COM_LOCK_CMP_EN 0x0a4
#define QSERDES_V4_COM_LOCK_CMP1_MODE0 0x0ac
#define QSERDES_V4_COM_LOCK_CMP2_MODE0 0x0b0
@@ -428,16 +432,24 @@
#define QSERDES_V4_COM_DIV_FRAC_START1_MODE1 0x0d8
#define QSERDES_V4_COM_DIV_FRAC_START2_MODE1 0x0dc
#define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0
+#define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0 0x0ec
+#define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0 0x0f0
+#define QSERDES_V4_COM_VCO_TUNE_CTRL 0x108
#define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c
#define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110
#define QSERDES_V4_COM_VCO_TUNE2_MODE0 0x114
#define QSERDES_V4_COM_VCO_TUNE1_MODE1 0x118
#define QSERDES_V4_COM_VCO_TUNE2_MODE1 0x11c
#define QSERDES_V4_COM_VCO_TUNE_INITVAL2 0x124
+#define QSERDES_V4_COM_CMN_STATUS 0x140
#define QSERDES_V4_COM_CLK_SELECT 0x154
#define QSERDES_V4_COM_HSCLK_SEL 0x158
#define QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL 0x15c
+#define QSERDES_V4_COM_CORECLK_DIV_MODE0 0x168
#define QSERDES_V4_COM_CORECLK_DIV_MODE1 0x16c
+#define QSERDES_V4_COM_CORE_CLK_EN 0x174
+#define QSERDES_V4_COM_C_READY_STATUS 0x178
+#define QSERDES_V4_COM_CMN_CONFIG 0x17c
#define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0
@@ -446,19 +458,32 @@
#define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8

/* Only for QMP V4 PHY - TX registers */
+#define QSERDES_V4_TX_CLKBUF_ENABLE 0x08
+#define QSERDES_V4_TX_TX_EMP_POST1_LVL 0x0c
+#define QSERDES_V4_TX_TX_DRV_LVL 0x14
+#define QSERDES_V4_TX_RESET_TSYNC_EN 0x1c
+#define QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN 0x20
+#define QSERDES_V4_TX_TX_BAND 0x24
+#define QSERDES_V4_TX_INTERFACE_SELECT 0x2c
#define QSERDES_V4_TX_RES_CODE_LANE_TX 0x34
#define QSERDES_V4_TX_RES_CODE_LANE_RX 0x38
#define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX 0x3c
#define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX 0x40
+#define QSERDES_V4_TX_TRANSCEIVER_BIAS_EN 0x54
+#define QSERDES_V4_TX_HIGHZ_DRVR_EN 0x58
+#define QSERDES_V4_TX_TX_POL_INV 0x5c
+#define QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN 0x60
#define QSERDES_V4_TX_LANE_MODE_1 0x84
#define QSERDES_V4_TX_LANE_MODE_2 0x88
#define QSERDES_V4_TX_RCV_DETECT_LVL_2 0x9c
+#define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8
+#define QSERDES_V4_TX_TX_INTERFACE_MODE 0xbc
#define QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0xd8
#define QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0xdC
#define QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0xe0
#define QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0xe4
-#define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8
-#define QSERDES_V4_TX_PI_QEC_CTRL 0x104
+#define QSERDES_V4_TX_VMODE_CTRL1 0xe8
+#define QSERDES_V4_TX_PI_QEC_CTRL 0x104

/* Only for QMP V4 PHY - RX registers */
#define QSERDES_V4_RX_UCDR_FO_GAIN 0x008
@@ -515,6 +540,17 @@
#define QSERDES_V4_RX_DCC_CTRL1 0x1bc
#define QSERDES_V4_RX_VTH_CODE 0x1c4

+/* Only for QMP V4 PHY - DP PHY registers */
+#define QSERDES_V4_DP_PHY_CFG_1 0x014
+#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK 0x054
+#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_CLEAR 0x058
+#define QSERDES_V4_DP_PHY_VCO_DIV 0x070
+#define QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL 0x078
+#define QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL 0x09c
+#define QSERDES_V4_DP_PHY_SPARE0 0x0c8
+#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8
+#define QSERDES_V4_DP_PHY_STATUS 0x0dc
+
/* Only for QMP V4 PHY - UFS PCS registers */
#define QPHY_V4_PCS_UFS_PHY_START 0x000
#define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL 0x004
--
2.30.2

2021-03-28 21:04:06

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH v5 7/7] arm64: dts: qcom: use dp_phy to provide clocks to dispcc

Plug dp_phy-provided clocks to display clock controller.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
arch/arm64/boot/dts/qcom/sm8250.dtsi | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index 0f79e6885004..a2478bd3590a 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -2600,8 +2600,8 @@ dispcc: clock-controller@af00000 {
<&dsi0_phy 1>,
<&dsi1_phy 0>,
<&dsi1_phy 1>,
- <0>,
- <0>,
+ <&dp_phy 0>,
+ <&dp_phy 1>,
<0>,
<0>,
<0>,
@@ -2614,8 +2614,8 @@ dispcc: clock-controller@af00000 {
"dsi0_phy_pll_out_dsiclk",
"dsi1_phy_pll_out_byteclk",
"dsi1_phy_pll_out_dsiclk",
- "dp_link_clk_divsel_ten",
- "dp_vco_divided_clk_src_mux",
+ "dp_phy_pll_link_clk",
+ "dp_phy_pll_vco_div_clk",
"dptx1_phy_pll_link_clk",
"dptx1_phy_pll_vco_div_clk",
"dptx2_phy_pll_link_clk",
--
2.30.2

2021-03-30 03:30:23

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 1/7] dt-bindings: phy: qcom,qmp-usb3-dp-phy: move usb3 compatibles back to qcom,qmp-phy.yaml

On Sun 28 Mar 15:52 CDT 2021, Dmitry Baryshkov wrote:

> The commit 724fabf5df13 ("dt-bindings: phy: qcom,qmp-usb3-dp: Add DP phy
> information") has support for DP part of USB3+DP combo PHYs. However
> this change is not backwards compatible, placing additional requirements
> onto qcom,sc7180-qmp-usb3-phy and qcom,sdm845-qmp-usb3-phy device nodes
> (to include separate DP part, etc). However the aforementioned nodes do
> not inclue DP part, they strictly follow the schema defined in the
> qcom,qmp-phy.yaml file. Move those compatibles, leaving
> qcom,qmp-usb3-dp-phy.yaml to describe only real "combo" USB3+DP device nodes.
>
> Fixes: 724fabf5df13 ("dt-bindings: phy: qcom,qmp-usb3-dp: Add DP phy information")
> Cc: Stephen Boyd <[email protected]>
> Cc: Sandeep Maheswaram <[email protected]>
> Signed-off-by: Dmitry Baryshkov <[email protected]>
> Acked-by: Rob Herring <[email protected]>
> Reviewed-by: Stephen Boyd <[email protected]>

Reviewed-by: Bjorn Andersson <[email protected]>

> ---
> Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml | 2 ++
> Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 2 --
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
> index 626447fee092..7808ec8bc712 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml
> @@ -25,11 +25,13 @@ properties:
> - qcom,msm8998-qmp-pcie-phy
> - qcom,msm8998-qmp-ufs-phy
> - qcom,msm8998-qmp-usb3-phy
> + - qcom,sc7180-qmp-usb3-phy
> - qcom,sc8180x-qmp-ufs-phy
> - qcom,sc8180x-qmp-usb3-phy
> - qcom,sdm845-qhp-pcie-phy
> - qcom,sdm845-qmp-pcie-phy
> - qcom,sdm845-qmp-ufs-phy
> + - qcom,sdm845-qmp-usb3-phy
> - qcom,sdm845-qmp-usb3-uni-phy
> - qcom,sm8150-qmp-ufs-phy
> - qcom,sm8150-qmp-usb3-phy
> diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
> index 33974ad10afe..62c0179d1765 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
> @@ -14,9 +14,7 @@ properties:
> compatible:
> enum:
> - qcom,sc7180-qmp-usb3-dp-phy
> - - qcom,sc7180-qmp-usb3-phy
> - qcom,sdm845-qmp-usb3-dp-phy
> - - qcom,sdm845-qmp-usb3-phy
> reg:
> items:
> - description: Address and length of PHY's USB serdes block.
> --
> 2.30.2
>

2021-03-30 03:30:55

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 2/7] dt-bindings: phy: qcom,qmp-usb3-dp: Add support for SM8250

On Sun 28 Mar 15:52 CDT 2021, Dmitry Baryshkov wrote:

> Add compatible for SM8250 in QMP USB3 DP PHY bindings.
>
> Signed-off-by: Dmitry Baryshkov <[email protected]>
> Acked-by: Rob Herring <[email protected]>

Reviewed-by: Bjorn Andersson <[email protected]>

> ---
> Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
> index 62c0179d1765..217aa6c91893 100644
> --- a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
> +++ b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml
> @@ -15,6 +15,7 @@ properties:
> enum:
> - qcom,sc7180-qmp-usb3-dp-phy
> - qcom,sdm845-qmp-usb3-dp-phy
> + - qcom,sm8250-qmp-usb3-dp-phy
> reg:
> items:
> - description: Address and length of PHY's USB serdes block.
> --
> 2.30.2
>

2021-03-30 03:30:55

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 4/7] phy: qcom-qmp: rename common registers

On Sun 28 Mar 15:52 CDT 2021, Dmitry Baryshkov wrote:

> A plenty of DP PHY registers are common between V3 and V4. To simplify
> V4 code, rename all common registers.
>
> Signed-off-by: Dmitry Baryshkov <[email protected]>

Reviewed-by: Bjorn Andersson <[email protected]>

Regards,
Bjorn

> ---
> drivers/phy/qualcomm/phy-qcom-qmp.c | 50 ++++++++++++++---------------
> drivers/phy/qualcomm/phy-qcom-qmp.h | 37 ++++++++++-----------
> 2 files changed, 44 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
> index 4150096fd350..097bc005ba43 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
> @@ -2435,20 +2435,20 @@ static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy)
> {
> writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
> - qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> + qphy->pcs + QSERDES_DP_PHY_PD_CTL);
>
> /* Turn on BIAS current for PHY/PLL */
> writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX |
> QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL,
> qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
>
> - writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> + writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL);
>
> writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> DP_PHY_PD_CTL_LANE_0_1_PWRDN |
> DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN |
> DP_PHY_PD_CTL_DP_CLAMP_EN,
> - qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> + qphy->pcs + QSERDES_DP_PHY_PD_CTL);
>
> writel(QSERDES_V3_COM_BIAS_EN |
> QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN |
> @@ -2456,16 +2456,16 @@ static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy)
> QSERDES_V3_COM_CLKBUF_RX_DRIVE_L,
> qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
>
> - writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0);
> - writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
> - writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
> - writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3);
> - writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4);
> - writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5);
> - writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6);
> - writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7);
> - writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8);
> - writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9);
> + writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0);
> + writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
> + writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
> + writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3);
> + writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4);
> + writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5);
> + writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6);
> + writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7);
> + writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8);
> + writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9);
> qphy->dp_aux_cfg = 0;
>
> writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
> @@ -2556,9 +2556,9 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
> */
> val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
> - writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> + writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL);
>
> - writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
> + writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE);
> writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
> writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);
>
> @@ -2588,11 +2588,11 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
> clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
>
> - writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
> - writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> - writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> - writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> - writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
> + writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
> + writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG);
> + writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
> + writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG);
>
> writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL);
>
> @@ -2603,7 +2603,7 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> 10000))
> return -ETIMEDOUT;
>
> - writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
>
> if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
> status,
> @@ -2612,9 +2612,9 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> 10000))
> return -ETIMEDOUT;
>
> - writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG);
> udelay(2000);
> - writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
>
> return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
> status,
> @@ -2636,7 +2636,7 @@ static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy)
> qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
> val = cfg1_settings[qphy->dp_aux_cfg];
>
> - writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
> + writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
>
> return 0;
> }
> @@ -3898,7 +3898,7 @@ static int qcom_qmp_phy_power_off(struct phy *phy)
>
> if (cfg->type == PHY_TYPE_DP) {
> /* Assert DP PHY power down */
> - writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> + writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL);
> } else {
> /* PHY reset */
> if (!cfg->no_pcs_sw_reset)
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
> index 71ce3aa174ae..981d8ee891c0 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp.h
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
> @@ -349,13 +349,13 @@
> #define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4 0x5c
> #define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5 0x60
>
> -/* Only for QMP V3 PHY - DP PHY registers */
> -#define QSERDES_V3_DP_PHY_REVISION_ID0 0x000
> -#define QSERDES_V3_DP_PHY_REVISION_ID1 0x004
> -#define QSERDES_V3_DP_PHY_REVISION_ID2 0x008
> -#define QSERDES_V3_DP_PHY_REVISION_ID3 0x00c
> -#define QSERDES_V3_DP_PHY_CFG 0x010
> -#define QSERDES_V3_DP_PHY_PD_CTL 0x018
> +/* QMP PHY - DP PHY registers */
> +#define QSERDES_DP_PHY_REVISION_ID0 0x000
> +#define QSERDES_DP_PHY_REVISION_ID1 0x004
> +#define QSERDES_DP_PHY_REVISION_ID2 0x008
> +#define QSERDES_DP_PHY_REVISION_ID3 0x00c
> +#define QSERDES_DP_PHY_CFG 0x010
> +#define QSERDES_DP_PHY_PD_CTL 0x018
> # define DP_PHY_PD_CTL_PWRDN 0x001
> # define DP_PHY_PD_CTL_PSR_PWRDN 0x002
> # define DP_PHY_PD_CTL_AUX_PWRDN 0x004
> @@ -363,18 +363,19 @@
> # define DP_PHY_PD_CTL_LANE_2_3_PWRDN 0x010
> # define DP_PHY_PD_CTL_PLL_PWRDN 0x020
> # define DP_PHY_PD_CTL_DP_CLAMP_EN 0x040
> -#define QSERDES_V3_DP_PHY_MODE 0x01c
> -#define QSERDES_V3_DP_PHY_AUX_CFG0 0x020
> -#define QSERDES_V3_DP_PHY_AUX_CFG1 0x024
> -#define QSERDES_V3_DP_PHY_AUX_CFG2 0x028
> -#define QSERDES_V3_DP_PHY_AUX_CFG3 0x02c
> -#define QSERDES_V3_DP_PHY_AUX_CFG4 0x030
> -#define QSERDES_V3_DP_PHY_AUX_CFG5 0x034
> -#define QSERDES_V3_DP_PHY_AUX_CFG6 0x038
> -#define QSERDES_V3_DP_PHY_AUX_CFG7 0x03c
> -#define QSERDES_V3_DP_PHY_AUX_CFG8 0x040
> -#define QSERDES_V3_DP_PHY_AUX_CFG9 0x044
> +#define QSERDES_DP_PHY_MODE 0x01c
> +#define QSERDES_DP_PHY_AUX_CFG0 0x020
> +#define QSERDES_DP_PHY_AUX_CFG1 0x024
> +#define QSERDES_DP_PHY_AUX_CFG2 0x028
> +#define QSERDES_DP_PHY_AUX_CFG3 0x02c
> +#define QSERDES_DP_PHY_AUX_CFG4 0x030
> +#define QSERDES_DP_PHY_AUX_CFG5 0x034
> +#define QSERDES_DP_PHY_AUX_CFG6 0x038
> +#define QSERDES_DP_PHY_AUX_CFG7 0x03c
> +#define QSERDES_DP_PHY_AUX_CFG8 0x040
> +#define QSERDES_DP_PHY_AUX_CFG9 0x044
>
> +/* Only for QMP V3 PHY - DP PHY registers */
> #define QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK 0x048
> # define PHY_AUX_STOP_ERR_MASK 0x01
> # define PHY_AUX_DEC_ERR_MASK 0x02
> --
> 2.30.2
>

2021-03-30 03:30:56

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 3/7] phy: qcom-qmp: move DP functions to callbacks

On Sun 28 Mar 15:52 CDT 2021, Dmitry Baryshkov wrote:

> In preparation to adding support for V4 DP PHY move DP functions to
> callbacks at struct qmp_phy_cfg.
>

Reviewed-by: Bjorn Andersson <[email protected]>

Regards,
Bjorn

> Signed-off-by: Dmitry Baryshkov <[email protected]>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp.c | 438 +++++++++++++++-------------
> 1 file changed, 231 insertions(+), 207 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
> index 9cdebe7f26cb..4150096fd350 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
> @@ -2268,6 +2268,8 @@ static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_tbl[] = {
> QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
> };
>
> +struct qmp_phy;
> +
> /* struct qmp_phy_cfg - per-PHY initialization config */
> struct qmp_phy_cfg {
> /* phy-type - PCIE/UFS/USB */
> @@ -2307,6 +2309,12 @@ struct qmp_phy_cfg {
> const struct qmp_phy_init_tbl *serdes_tbl_hbr3;
> int serdes_tbl_hbr3_num;
>
> + /* DP PHY callbacks */
> + int (*configure_dp_phy)(struct qmp_phy *qphy);
> + void (*configure_dp_tx)(struct qmp_phy *qphy);
> + int (*calibrate_dp_phy)(struct qmp_phy *qphy);
> + void (*dp_aux_init)(struct qmp_phy *qphy);
> +
> /* clock ids to be requested */
> const char * const *clk_list;
> int num_clks;
> @@ -2423,6 +2431,216 @@ struct qcom_qmp {
> struct reset_control *ufs_reset;
> };
>
> +static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy)
> +{
> + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
> + qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> +
> + /* Turn on BIAS current for PHY/PLL */
> + writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX |
> + QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL,
> + qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
> +
> + writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> +
> + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> + DP_PHY_PD_CTL_LANE_0_1_PWRDN |
> + DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN |
> + DP_PHY_PD_CTL_DP_CLAMP_EN,
> + qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> +
> + writel(QSERDES_V3_COM_BIAS_EN |
> + QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN |
> + QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL |
> + QSERDES_V3_COM_CLKBUF_RX_DRIVE_L,
> + qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
> +
> + writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0);
> + writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
> + writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
> + writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3);
> + writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4);
> + writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5);
> + writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6);
> + writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7);
> + writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8);
> + writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9);
> + qphy->dp_aux_cfg = 0;
> +
> + writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
> + PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
> + PHY_AUX_REQ_ERR_MASK,
> + qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK);
> +}
> +
> +static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = {
> + { 0x00, 0x0c, 0x14, 0x19 },
> + { 0x00, 0x0b, 0x12, 0xff },
> + { 0x00, 0x0b, 0xff, 0xff },
> + { 0x04, 0xff, 0xff, 0xff }
> +};
> +
> +static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = {
> + { 0x08, 0x0f, 0x16, 0x1f },
> + { 0x11, 0x1e, 0x1f, 0xff },
> + { 0x19, 0x1f, 0xff, 0xff },
> + { 0x1f, 0xff, 0xff, 0xff }
> +};
> +
> +static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
> +{
> + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> + unsigned int v_level = 0, p_level = 0;
> + u32 bias_en, drvr_en;
> + u8 voltage_swing_cfg, pre_emphasis_cfg;
> + int i;
> +
> + for (i = 0; i < dp_opts->lanes; i++) {
> + v_level = max(v_level, dp_opts->voltage[i]);
> + p_level = max(p_level, dp_opts->pre[i]);
> + }
> +
> + if (dp_opts->lanes == 1) {
> + bias_en = 0x3e;
> + drvr_en = 0x13;
> + } else {
> + bias_en = 0x3f;
> + drvr_en = 0x10;
> + }
> +
> + voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level];
> + pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level];
> +
> + /* TODO: Move check to config check */
> + if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF)
> + return;
> +
> + /* Enable MUX to use Cursor values from these registers */
> + voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN;
> + pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN;
> +
> + writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL);
> + writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL);
> + writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL);
> + writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL);
> +
> + writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN);
> + writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
> + writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN);
> + writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
> +}
> +
> +static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> +{
> + const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
> + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> + u32 val, phy_vco_div, status;
> + unsigned long pixel_freq;
> +
> + val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
> +
> + /*
> + * TODO: Assume orientation is CC1 for now and two lanes, need to
> + * use type-c connector to understand orientation and lanes.
> + *
> + * Otherwise val changes to be like below if this code understood
> + * the orientation of the type-c cable.
> + *
> + * if (lane_cnt == 4 || orientation == ORIENTATION_CC2)
> + * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
> + * if (lane_cnt == 4 || orientation == ORIENTATION_CC1)
> + * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
> + * if (orientation == ORIENTATION_CC2)
> + * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
> + */
> + val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
> + writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> +
> + writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
> + writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
> + writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);
> +
> + switch (dp_opts->link_rate) {
> + case 1620:
> + phy_vco_div = 0x1;
> + pixel_freq = 1620000000UL / 2;
> + break;
> + case 2700:
> + phy_vco_div = 0x1;
> + pixel_freq = 2700000000UL / 2;
> + break;
> + case 5400:
> + phy_vco_div = 0x2;
> + pixel_freq = 5400000000UL / 4;
> + break;
> + case 8100:
> + phy_vco_div = 0x0;
> + pixel_freq = 8100000000UL / 6;
> + break;
> + default:
> + /* Other link rates aren't supported */
> + return -EINVAL;
> + }
> + writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV);
> +
> + clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
> + clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
> +
> + writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
> + writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> +
> + writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL);
> +
> + if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS,
> + status,
> + ((status & BIT(0)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> +
> + if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
> + status,
> + ((status & BIT(1)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> + udelay(2000);
> + writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> +
> + return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
> + status,
> + ((status & BIT(1)) > 0),
> + 500,
> + 10000);
> +}
> +
> +/*
> + * We need to calibrate the aux setting here as many times
> + * as the caller tries
> + */
> +static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy)
> +{
> + static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d };
> + u8 val;
> +
> + qphy->dp_aux_cfg++;
> + qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
> + val = cfg1_settings[qphy->dp_aux_cfg];
> +
> + writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
> +
> + return 0;
> +}
> +
> static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
> {
> u32 reg;
> @@ -2871,6 +3089,11 @@ static const struct qmp_phy_cfg sc7180_dpphy_cfg = {
>
> .has_phy_dp_com_ctrl = true,
> .is_dual_lane_phy = true,
> +
> + .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init,
> + .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx,
> + .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy,
> + .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate,
> };
>
> static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = {
> @@ -3332,227 +3555,28 @@ static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy)
> return 0;
> }
>
> -static void qcom_qmp_phy_dp_aux_init(struct qmp_phy *qphy)
> -{
> - writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> - DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
> - qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> -
> - /* Turn on BIAS current for PHY/PLL */
> - writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX |
> - QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL,
> - qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
> -
> - writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> -
> - writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> - DP_PHY_PD_CTL_LANE_0_1_PWRDN |
> - DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN |
> - DP_PHY_PD_CTL_DP_CLAMP_EN,
> - qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> -
> - writel(QSERDES_V3_COM_BIAS_EN |
> - QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN |
> - QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL |
> - QSERDES_V3_COM_CLKBUF_RX_DRIVE_L,
> - qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN);
> -
> - writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0);
> - writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
> - writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
> - writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3);
> - writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4);
> - writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5);
> - writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6);
> - writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7);
> - writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8);
> - writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9);
> - qphy->dp_aux_cfg = 0;
> -
> - writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
> - PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
> - PHY_AUX_REQ_ERR_MASK,
> - qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK);
> -}
> -
> -static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = {
> - { 0x00, 0x0c, 0x14, 0x19 },
> - { 0x00, 0x0b, 0x12, 0xff },
> - { 0x00, 0x0b, 0xff, 0xff },
> - { 0x04, 0xff, 0xff, 0xff }
> -};
> -
> -static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = {
> - { 0x08, 0x0f, 0x16, 0x1f },
> - { 0x11, 0x1e, 0x1f, 0xff },
> - { 0x19, 0x1f, 0xff, 0xff },
> - { 0x1f, 0xff, 0xff, 0xff }
> -};
> -
> -static void qcom_qmp_phy_configure_dp_tx(struct qmp_phy *qphy)
> -{
> - const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> - unsigned int v_level = 0, p_level = 0;
> - u32 bias_en, drvr_en;
> - u8 voltage_swing_cfg, pre_emphasis_cfg;
> - int i;
> -
> - for (i = 0; i < dp_opts->lanes; i++) {
> - v_level = max(v_level, dp_opts->voltage[i]);
> - p_level = max(p_level, dp_opts->pre[i]);
> - }
> -
> - if (dp_opts->lanes == 1) {
> - bias_en = 0x3e;
> - drvr_en = 0x13;
> - } else {
> - bias_en = 0x3f;
> - drvr_en = 0x10;
> - }
> -
> - voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level];
> - pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level];
> -
> - /* TODO: Move check to config check */
> - if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF)
> - return;
> -
> - /* Enable MUX to use Cursor values from these registers */
> - voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN;
> - pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN;
> -
> - writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL);
> - writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL);
> - writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL);
> - writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL);
> -
> - writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN);
> - writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
> - writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN);
> - writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
> -}
> -
> static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
> {
> const struct phy_configure_opts_dp *dp_opts = &opts->dp;
> struct qmp_phy *qphy = phy_get_drvdata(phy);
> + const struct qmp_phy_cfg *cfg = qphy->cfg;
>
> memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts));
> if (qphy->dp_opts.set_voltages) {
> - qcom_qmp_phy_configure_dp_tx(qphy);
> + cfg->configure_dp_tx(qphy);
> qphy->dp_opts.set_voltages = 0;
> }
>
> return 0;
> }
>
> -static int qcom_qmp_phy_configure_dp_phy(struct qmp_phy *qphy)
> -{
> - const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
> - const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> - u32 val, phy_vco_div, status;
> - unsigned long pixel_freq;
> -
> - val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> - DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
> -
> - /*
> - * TODO: Assume orientation is CC1 for now and two lanes, need to
> - * use type-c connector to understand orientation and lanes.
> - *
> - * Otherwise val changes to be like below if this code understood
> - * the orientation of the type-c cable.
> - *
> - * if (lane_cnt == 4 || orientation == ORIENTATION_CC2)
> - * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
> - * if (lane_cnt == 4 || orientation == ORIENTATION_CC1)
> - * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
> - * if (orientation == ORIENTATION_CC2)
> - * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
> - */
> - val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
> - writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
> -
> - writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
> - writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
> - writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);
> -
> - switch (dp_opts->link_rate) {
> - case 1620:
> - phy_vco_div = 0x1;
> - pixel_freq = 1620000000UL / 2;
> - break;
> - case 2700:
> - phy_vco_div = 0x1;
> - pixel_freq = 2700000000UL / 2;
> - break;
> - case 5400:
> - phy_vco_div = 0x2;
> - pixel_freq = 5400000000UL / 4;
> - break;
> - case 8100:
> - phy_vco_div = 0x0;
> - pixel_freq = 8100000000UL / 6;
> - break;
> - default:
> - /* Other link rates aren't supported */
> - return -EINVAL;
> - }
> - writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV);
> -
> - clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
> - clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
> -
> - writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2);
> - writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> - writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> - writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> - writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> -
> - writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL);
> -
> - if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS,
> - status,
> - ((status & BIT(0)) > 0),
> - 500,
> - 10000))
> - return -ETIMEDOUT;
> -
> - writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> -
> - if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
> - status,
> - ((status & BIT(1)) > 0),
> - 500,
> - 10000))
> - return -ETIMEDOUT;
> -
> - writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> - udelay(2000);
> - writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG);
> -
> - return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS,
> - status,
> - ((status & BIT(1)) > 0),
> - 500,
> - 10000);
> -}
> -
> -/*
> - * We need to calibrate the aux setting here as many times
> - * as the caller tries
> - */
> static int qcom_qmp_dp_phy_calibrate(struct phy *phy)
> {
> struct qmp_phy *qphy = phy_get_drvdata(phy);
> - static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d };
> - u8 val;
> -
> - qphy->dp_aux_cfg++;
> - qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
> - val = cfg1_settings[qphy->dp_aux_cfg];
> + const struct qmp_phy_cfg *cfg = qphy->cfg;
>
> - writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1);
> + if (cfg->calibrate_dp_phy)
> + return cfg->calibrate_dp_phy(qphy);
>
> return 0;
> }
> @@ -3729,7 +3753,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
> return ret;
>
> if (cfg->type == PHY_TYPE_DP)
> - qcom_qmp_phy_dp_aux_init(qphy);
> + cfg->dp_aux_init(qphy);
>
> return 0;
> }
> @@ -3783,7 +3807,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy)
>
> /* Configure special DP tx tunings */
> if (cfg->type == PHY_TYPE_DP)
> - qcom_qmp_phy_configure_dp_tx(qphy);
> + cfg->configure_dp_tx(qphy);
>
> qcom_qmp_phy_configure_lane(rx, cfg->regs,
> cfg->rx_tbl, cfg->rx_tbl_num, 1);
> @@ -3802,7 +3826,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy)
>
> /* Configure link rate, swing, etc. */
> if (cfg->type == PHY_TYPE_DP) {
> - qcom_qmp_phy_configure_dp_phy(qphy);
> + cfg->configure_dp_phy(qphy);
> } else {
> qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
> if (cfg->pcs_tbl_sec)
> --
> 2.30.2
>

2021-03-30 03:32:50

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 5/7] phy: qcom-qmp: add support for sm8250-usb3-dp phy

On Sun 28 Mar 15:52 CDT 2021, Dmitry Baryshkov wrote:

> Add support for QMP V4 Combo USB3+DP PHY (for SM8250 platform).
>
> Signed-off-by: Dmitry Baryshkov <[email protected]>

Acked-by: Bjorn Andersson <[email protected]>

Regards,
Bjorn

> ---
> drivers/phy/qualcomm/phy-qcom-qmp.c | 388 ++++++++++++++++++++++++++--
> drivers/phy/qualcomm/phy-qcom-qmp.h | 40 ++-
> 2 files changed, 406 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
> index 097bc005ba43..a47da2fff7a1 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
> @@ -1840,6 +1840,86 @@ static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = {
> QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
> };
>
> +static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f),
> +};
> +
> +static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04),
> +};
> +
> +static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08),
> +};
> +
> +static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08),
> +};
> +
> +static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a),
> + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08),
> +};
> +
> +static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = {
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a),
> + QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20),
> +};
> +
> static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
> QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
> QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
> @@ -2488,11 +2568,10 @@ static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = {
> { 0x1f, 0xff, 0xff, 0xff }
> };
>
> -static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
> +static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, unsigned int drv_lvl, unsigned int emp_post)
> {
> const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> unsigned int v_level = 0, p_level = 0;
> - u32 bias_en, drvr_en;
> u8 voltage_swing_cfg, pre_emphasis_cfg;
> int i;
>
> @@ -2501,29 +2580,42 @@ static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
> p_level = max(p_level, dp_opts->pre[i]);
> }
>
> - if (dp_opts->lanes == 1) {
> - bias_en = 0x3e;
> - drvr_en = 0x13;
> - } else {
> - bias_en = 0x3f;
> - drvr_en = 0x10;
> - }
> -
> voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level];
> pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level];
>
> /* TODO: Move check to config check */
> if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF)
> - return;
> + return -EINVAL;
>
> /* Enable MUX to use Cursor values from these registers */
> voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN;
> pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN;
>
> - writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL);
> - writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL);
> - writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL);
> - writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL);
> + writel(voltage_swing_cfg, qphy->tx + drv_lvl);
> + writel(pre_emphasis_cfg, qphy->tx + emp_post);
> + writel(voltage_swing_cfg, qphy->tx2 + drv_lvl);
> + writel(pre_emphasis_cfg, qphy->tx2 + emp_post);
> +
> + return 0;
> +}
> +
> +static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
> +{
> + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> + u32 bias_en, drvr_en;
> +
> + if (qcom_qmp_phy_configure_dp_swing(qphy,
> + QSERDES_V3_TX_TX_DRV_LVL,
> + QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0)
> + return;
> +
> + if (dp_opts->lanes == 1) {
> + bias_en = 0x3e;
> + drvr_en = 0x13;
> + } else {
> + bias_en = 0x3f;
> + drvr_en = 0x10;
> + }
>
> writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN);
> writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
> @@ -2531,12 +2623,10 @@ static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy)
> writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN);
> }
>
> -static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> +static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy)
> {
> - const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
> - const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> - u32 val, phy_vco_div, status;
> - unsigned long pixel_freq;
> + u32 val;
> + bool reverse = false;
>
> val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
> @@ -2559,6 +2649,19 @@ static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL);
>
> writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE);
> +
> + return reverse;
> +}
> +
> +static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy)
> +{
> + const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
> + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> + u32 phy_vco_div, status;
> + unsigned long pixel_freq;
> +
> + qcom_qmp_phy_configure_dp_mode(qphy);
> +
> writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL);
> writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL);
>
> @@ -2641,6 +2744,204 @@ static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy)
> return 0;
> }
>
> +static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy)
> +{
> + writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
> + DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
> + qphy->pcs + QSERDES_DP_PHY_PD_CTL);
> +
> + /* Turn on BIAS current for PHY/PLL */
> + writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
> +
> + writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0);
> + writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
> + writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
> + writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3);
> + writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4);
> + writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5);
> + writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6);
> + writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7);
> + writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8);
> + writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9);
> + qphy->dp_aux_cfg = 0;
> +
> + writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
> + PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
> + PHY_AUX_REQ_ERR_MASK,
> + qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK);
> +}
> +
> +static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy)
> +{
> + /* Program default values before writing proper values */
> + writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL);
> + writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL);
> +
> + writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL);
> + writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL);
> +
> + qcom_qmp_phy_configure_dp_swing(qphy,
> + QSERDES_V4_TX_TX_DRV_LVL,
> + QSERDES_V4_TX_TX_EMP_POST1_LVL);
> +}
> +
> +static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy)
> +{
> + const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks;
> + const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
> + u32 phy_vco_div, status;
> + unsigned long pixel_freq;
> + u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
> + bool reverse;
> +
> + writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1);
> +
> + reverse = qcom_qmp_phy_configure_dp_mode(qphy);
> +
> + writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
> + writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2);
> +
> + writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL);
> + writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL);
> +
> + switch (dp_opts->link_rate) {
> + case 1620:
> + phy_vco_div = 0x1;
> + pixel_freq = 1620000000UL / 2;
> + break;
> + case 2700:
> + phy_vco_div = 0x1;
> + pixel_freq = 2700000000UL / 2;
> + break;
> + case 5400:
> + phy_vco_div = 0x2;
> + pixel_freq = 5400000000UL / 4;
> + break;
> + case 8100:
> + phy_vco_div = 0x0;
> + pixel_freq = 8100000000UL / 6;
> + break;
> + default:
> + /* Other link rates aren't supported */
> + return -EINVAL;
> + }
> + writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV);
> +
> + clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000);
> + clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq);
> +
> + writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
> + writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG);
> + writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG);
> + writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG);
> +
> + writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL);
> +
> + if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS,
> + status,
> + ((status & BIT(0)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS,
> + status,
> + ((status & BIT(0)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS,
> + status,
> + ((status & BIT(1)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
> +
> + if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
> + status,
> + ((status & BIT(0)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
> + status,
> + ((status & BIT(1)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + /*
> + * At least for 7nm DP PHY this has to be done after enabling link
> + * clock.
> + */
> +
> + if (dp_opts->lanes == 1) {
> + bias0_en = reverse ? 0x3e : 0x15;
> + bias1_en = reverse ? 0x15 : 0x3e;
> + drvr0_en = reverse ? 0x13 : 0x10;
> + drvr1_en = reverse ? 0x10 : 0x13;
> + } else if (dp_opts->lanes == 2) {
> + bias0_en = reverse ? 0x3f : 0x15;
> + bias1_en = reverse ? 0x15 : 0x3f;
> + drvr0_en = 0x10;
> + drvr1_en = 0x10;
> + } else {
> + bias0_en = 0x3f;
> + bias1_en = 0x3f;
> + drvr0_en = 0x10;
> + drvr1_en = 0x10;
> + }
> +
> + writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN);
> + writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN);
> + writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN);
> + writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN);
> +
> + writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG);
> + udelay(2000);
> + writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG);
> +
> + if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS,
> + status,
> + ((status & BIT(1)) > 0),
> + 500,
> + 10000))
> + return -ETIMEDOUT;
> +
> + writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV);
> + writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV);
> +
> + writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL);
> + writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL);
> +
> + writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL);
> + writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL);
> +
> + return 0;
> +}
> +
> +/*
> + * We need to calibrate the aux setting here as many times
> + * as the caller tries
> + */
> +static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy)
> +{
> + static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d };
> + u8 val;
> +
> + qphy->dp_aux_cfg++;
> + qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings);
> + val = cfg1_settings[qphy->dp_aux_cfg];
> +
> + writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1);
> +
> + return 0;
> +}
> +
> static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
> {
> u32 reg;
> @@ -3346,6 +3647,46 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
> .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
> };
>
> +static const struct qmp_phy_cfg sm8250_dpphy_cfg = {
> + .type = PHY_TYPE_DP,
> + .nlanes = 1,
> +
> + .serdes_tbl = qmp_v4_dp_serdes_tbl,
> + .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl),
> + .tx_tbl = qmp_v4_dp_tx_tbl,
> + .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl),
> +
> + .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr,
> + .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr),
> + .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr,
> + .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr),
> + .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2,
> + .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2),
> + .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3,
> + .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3),
> +
> + .clk_list = qmp_v4_phy_clk_l,
> + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l),
> + .reset_list = msm8996_usb3phy_reset_l,
> + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
> + .vreg_list = qmp_phy_vreg_l,
> + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
> + .regs = qmp_v4_usb3phy_regs_layout,
> +
> + .has_phy_dp_com_ctrl = true,
> + .is_dual_lane_phy = true,
> +
> + .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init,
> + .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx,
> + .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy,
> + .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate,
> +};
> +
> +static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = {
> + .usb_cfg = &sm8250_usb3phy_cfg,
> + .dp_cfg = &sm8250_dpphy_cfg,
> +};
> +
> static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
> .type = PHY_TYPE_USB3,
> .nlanes = 1,
> @@ -4601,6 +4942,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
> }, {
> .compatible = "qcom,sm8250-qmp-usb3-phy",
> .data = &sm8250_usb3phy_cfg,
> + }, {
> + .compatible = "qcom,sm8250-qmp-usb3-dp-phy",
> + /* It's a combo phy */
> }, {
> .compatible = "qcom,sm8250-qmp-usb3-uni-phy",
> .data = &sm8250_usb3_uniphy_cfg,
> @@ -4635,6 +4979,10 @@ static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = {
> .compatible = "qcom,sc7180-qmp-usb3-dp-phy",
> .data = &sc7180_usb3dpphy_cfg,
> },
> + {
> + .compatible = "qcom,sm8250-qmp-usb3-dp-phy",
> + .data = &sm8250_usb3dpphy_cfg,
> + },
> { }
> };
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
> index 981d8ee891c0..67bd2dd0d8c5 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp.h
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
> @@ -397,6 +397,7 @@
> #define QSERDES_V3_DP_PHY_STATUS 0x0c0
>
> /* Only for QMP V4 PHY - QSERDES COM registers */
> +#define QSERDES_V4_COM_BG_TIMER 0x00c
> #define QSERDES_V4_COM_SSC_EN_CENTER 0x010
> #define QSERDES_V4_COM_SSC_PER1 0x01c
> #define QSERDES_V4_COM_SSC_PER2 0x020
> @@ -404,7 +405,9 @@
> #define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0 0x028
> #define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1 0x030
> #define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1 0x034
> +#define QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN 0x044
> #define QSERDES_V4_COM_CLK_ENABLE1 0x048
> +#define QSERDES_V4_COM_SYS_CLK_CTRL 0x04c
> #define QSERDES_V4_COM_SYSCLK_BUF_ENABLE 0x050
> #define QSERDES_V4_COM_PLL_IVCO 0x058
> #define QSERDES_V4_COM_CMN_IPTRIM 0x060
> @@ -415,6 +418,7 @@
> #define QSERDES_V4_COM_PLL_CCTRL_MODE0 0x084
> #define QSERDES_V4_COM_PLL_CCTRL_MODE1 0x088
> #define QSERDES_V4_COM_SYSCLK_EN_SEL 0x094
> +#define QSERDES_V4_COM_RESETSM_CNTRL 0x09c
> #define QSERDES_V4_COM_LOCK_CMP_EN 0x0a4
> #define QSERDES_V4_COM_LOCK_CMP1_MODE0 0x0ac
> #define QSERDES_V4_COM_LOCK_CMP2_MODE0 0x0b0
> @@ -428,16 +432,24 @@
> #define QSERDES_V4_COM_DIV_FRAC_START1_MODE1 0x0d8
> #define QSERDES_V4_COM_DIV_FRAC_START2_MODE1 0x0dc
> #define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0
> +#define QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0 0x0ec
> +#define QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0 0x0f0
> +#define QSERDES_V4_COM_VCO_TUNE_CTRL 0x108
> #define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c
> #define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110
> #define QSERDES_V4_COM_VCO_TUNE2_MODE0 0x114
> #define QSERDES_V4_COM_VCO_TUNE1_MODE1 0x118
> #define QSERDES_V4_COM_VCO_TUNE2_MODE1 0x11c
> #define QSERDES_V4_COM_VCO_TUNE_INITVAL2 0x124
> +#define QSERDES_V4_COM_CMN_STATUS 0x140
> #define QSERDES_V4_COM_CLK_SELECT 0x154
> #define QSERDES_V4_COM_HSCLK_SEL 0x158
> #define QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL 0x15c
> +#define QSERDES_V4_COM_CORECLK_DIV_MODE0 0x168
> #define QSERDES_V4_COM_CORECLK_DIV_MODE1 0x16c
> +#define QSERDES_V4_COM_CORE_CLK_EN 0x174
> +#define QSERDES_V4_COM_C_READY_STATUS 0x178
> +#define QSERDES_V4_COM_CMN_CONFIG 0x17c
> #define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184
> #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac
> #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0
> @@ -446,19 +458,32 @@
> #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8
>
> /* Only for QMP V4 PHY - TX registers */
> +#define QSERDES_V4_TX_CLKBUF_ENABLE 0x08
> +#define QSERDES_V4_TX_TX_EMP_POST1_LVL 0x0c
> +#define QSERDES_V4_TX_TX_DRV_LVL 0x14
> +#define QSERDES_V4_TX_RESET_TSYNC_EN 0x1c
> +#define QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN 0x20
> +#define QSERDES_V4_TX_TX_BAND 0x24
> +#define QSERDES_V4_TX_INTERFACE_SELECT 0x2c
> #define QSERDES_V4_TX_RES_CODE_LANE_TX 0x34
> #define QSERDES_V4_TX_RES_CODE_LANE_RX 0x38
> #define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX 0x3c
> #define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX 0x40
> +#define QSERDES_V4_TX_TRANSCEIVER_BIAS_EN 0x54
> +#define QSERDES_V4_TX_HIGHZ_DRVR_EN 0x58
> +#define QSERDES_V4_TX_TX_POL_INV 0x5c
> +#define QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN 0x60
> #define QSERDES_V4_TX_LANE_MODE_1 0x84
> #define QSERDES_V4_TX_LANE_MODE_2 0x88
> #define QSERDES_V4_TX_RCV_DETECT_LVL_2 0x9c
> +#define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8
> +#define QSERDES_V4_TX_TX_INTERFACE_MODE 0xbc
> #define QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0xd8
> #define QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0xdC
> #define QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0xe0
> #define QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0xe4
> -#define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8
> -#define QSERDES_V4_TX_PI_QEC_CTRL 0x104
> +#define QSERDES_V4_TX_VMODE_CTRL1 0xe8
> +#define QSERDES_V4_TX_PI_QEC_CTRL 0x104
>
> /* Only for QMP V4 PHY - RX registers */
> #define QSERDES_V4_RX_UCDR_FO_GAIN 0x008
> @@ -515,6 +540,17 @@
> #define QSERDES_V4_RX_DCC_CTRL1 0x1bc
> #define QSERDES_V4_RX_VTH_CODE 0x1c4
>
> +/* Only for QMP V4 PHY - DP PHY registers */
> +#define QSERDES_V4_DP_PHY_CFG_1 0x014
> +#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK 0x054
> +#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_CLEAR 0x058
> +#define QSERDES_V4_DP_PHY_VCO_DIV 0x070
> +#define QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL 0x078
> +#define QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL 0x09c
> +#define QSERDES_V4_DP_PHY_SPARE0 0x0c8
> +#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8
> +#define QSERDES_V4_DP_PHY_STATUS 0x0dc
> +
> /* Only for QMP V4 PHY - UFS PCS registers */
> #define QPHY_V4_PCS_UFS_PHY_START 0x000
> #define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL 0x004
> --
> 2.30.2
>

2021-03-30 03:36:22

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 6/7] arm64: dts: qcom: sm8250: switch usb1 qmp phy to USB3+DP mode

On Sun 28 Mar 15:52 CDT 2021, Dmitry Baryshkov wrote:

> USB1 QMP PHY is not just a USB3 PHY, but USB3+DP PHY. Change device tree
> nodes accordingly.
>
> Signed-off-by: Dmitry Baryshkov <[email protected]>

Reviewed-by: Bjorn Andersson <[email protected]>

@Vinod, will you let me know when you've picked the driver changes so I
can pick the two DT patches?

Regards,
Bjorn

> ---
> arch/arm64/boot/dts/qcom/sm8250.dtsi | 23 ++++++++++++++++++-----
> 1 file changed, 18 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
> index 947e1accae3a..0f79e6885004 100644
> --- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
> @@ -2097,12 +2097,11 @@ usb_2_hsphy: phy@88e4000 {
> };
>
> usb_1_qmpphy: phy@88e9000 {
> - compatible = "qcom,sm8250-qmp-usb3-phy";
> + compatible = "qcom,sm8250-qmp-usb3-dp-phy";
> reg = <0 0x088e9000 0 0x200>,
> - <0 0x088e8000 0 0x20>;
> - reg-names = "reg-base", "dp_com";
> + <0 0x088e8000 0 0x40>,
> + <0 0x088ea000 0 0x200>;
> status = "disabled";
> - #clock-cells = <1>;
> #address-cells = <2>;
> #size-cells = <2>;
> ranges;
> @@ -2116,7 +2115,7 @@ usb_1_qmpphy: phy@88e9000 {
> <&gcc GCC_USB3_PHY_PRIM_BCR>;
> reset-names = "phy", "common";
>
> - usb_1_ssphy: lanes@88e9200 {
> + usb_1_ssphy: usb3-phy@88e9200 {
> reg = <0 0x088e9200 0 0x200>,
> <0 0x088e9400 0 0x200>,
> <0 0x088e9c00 0 0x400>,
> @@ -2128,6 +2127,20 @@ usb_1_ssphy: lanes@88e9200 {
> clock-names = "pipe0";
> clock-output-names = "usb3_phy_pipe_clk_src";
> };
> +
> + dp_phy: dp-phy@88ea200 {
> + reg = <0 0x088ea200 0 0x200>,
> + <0 0x088ea400 0 0x200>,
> + <0 0x088eac00 0 0x400>,
> + <0 0x088ea600 0 0x200>,
> + <0 0x088ea800 0 0x200>,
> + <0 0x088eaa00 0 0x100>;
> + #phy-cells = <0>;
> + #clock-cells = <1>;
> + clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
> + clock-names = "pipe0";
> + clock-output-names = "usb3_phy_pipe_clk_src";
> + };
> };
>
> usb_2_qmpphy: phy@88eb000 {
> --
> 2.30.2
>

2021-03-30 03:36:22

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v5 7/7] arm64: dts: qcom: use dp_phy to provide clocks to dispcc

On Sun 28 Mar 15:52 CDT 2021, Dmitry Baryshkov wrote:

> Plug dp_phy-provided clocks to display clock controller.
>

Reviewed-by: Bjorn Andersson <[email protected]>

Regards,
Bjorn

> Signed-off-by: Dmitry Baryshkov <[email protected]>
> ---
> arch/arm64/boot/dts/qcom/sm8250.dtsi | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
> index 0f79e6885004..a2478bd3590a 100644
> --- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
> @@ -2600,8 +2600,8 @@ dispcc: clock-controller@af00000 {
> <&dsi0_phy 1>,
> <&dsi1_phy 0>,
> <&dsi1_phy 1>,
> - <0>,
> - <0>,
> + <&dp_phy 0>,
> + <&dp_phy 1>,
> <0>,
> <0>,
> <0>,
> @@ -2614,8 +2614,8 @@ dispcc: clock-controller@af00000 {
> "dsi0_phy_pll_out_dsiclk",
> "dsi1_phy_pll_out_byteclk",
> "dsi1_phy_pll_out_dsiclk",
> - "dp_link_clk_divsel_ten",
> - "dp_vco_divided_clk_src_mux",
> + "dp_phy_pll_link_clk",
> + "dp_phy_pll_vco_div_clk",
> "dptx1_phy_pll_link_clk",
> "dptx1_phy_pll_vco_div_clk",
> "dptx2_phy_pll_link_clk",
> --
> 2.30.2
>

2021-03-31 12:27:56

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH v5 0/7] phy: qcom-qmp: provide DP phy support for sm8250

On 28-03-21, 23:52, Dmitry Baryshkov wrote:
> Changes since v4:
> - Fix typo in the qcom,sc7180-qmp-usb3-phy name in the first patch
>
> Changes since v3:
> - Move qcom,sc7180-qmp-usb3-phy and qcom,sdm845-qmp-usb3-phy from
> qcom,qmp-usb3-dp.yaml to qcom,qmp-phy.yaml
> - Do not touch qcom,sm8250-qmp-usb3-phy compatible
>
> Changes since v2:
> - Drop unused qmp_v4_usb3_rx_tbl
>
> Changes since v1:
> - Provide dt bindings
> - Split register renaming from sm8250-dp-phy patch
> - Add respective changes to sm8250 device tree
>
> The following changes since commit a38fd8748464831584a19438cbb3082b5a2dab15:
>
> Linux 5.12-rc2 (2021-03-05 17:33:41 -0800)

This should be based on phy-next. This fails to apply for me. Can you
please rebase and acks and resend

Thanks

--
~Vinod